greybus: fix tracepoint-related whitespace issues
[cascardo/linux.git] / drivers / staging / greybus / module.c
index 43e8bab..7f0ed9f 100644 (file)
@@ -1,72 +1,75 @@
 /*
- * Greybus module code
+ * Greybus Module code
  *
- * Copyright 2014 Google Inc.
- * Copyright 2014 Linaro Ltd.
+ * Copyright 2016 Google Inc.
+ * Copyright 2016 Linaro Ltd.
  *
  * Released under the GPLv2 only.
  */
 
 #include "greybus.h"
+#include "greybus_trace.h"
 
 
-/* module sysfs attributes */
-static ssize_t epm_show(struct device *dev, struct device_attribute *attr,
-                       char *buf)
+static ssize_t eject_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t len)
 {
-       // FIXME
-       // Implement something here when we have a working control protocol
-       return sprintf(buf, "1\n");
-}
+       struct gb_module *module = to_gb_module(dev);
+       struct gb_interface *intf;
+       size_t i;
+       long val;
+       int ret;
+
+       ret = kstrtol(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       if (!val)
+               return len;
+
+       for (i = 0; i < module->num_interfaces; ++i) {
+               intf = module->interfaces[i];
+
+               mutex_lock(&intf->mutex);
+               /* Set flag to prevent concurrent activation. */
+               intf->ejected = true;
+               gb_interface_disable(intf);
+               gb_interface_deactivate(intf);
+               mutex_unlock(&intf->mutex);
+       }
 
-static ssize_t epm_store(struct device *dev, struct device_attribute *attr,
-                        const char *buf, size_t size)
-{
-       // FIXME
-       // Implement something here when we have a working control protocol
-       return 0;
-}
-static DEVICE_ATTR_RW(epm);
+       /* Tell the SVC to eject the primary interface. */
+       ret = gb_svc_intf_eject(module->hd->svc, module->module_id);
+       if (ret)
+               return ret;
 
-static ssize_t power_control_show(struct device *dev,
-                                 struct device_attribute *addr, char *buf)
-{
-       // FIXME
-       // Implement something here when we have a working control protocol
-       return sprintf(buf, "1\n");
+       return len;
 }
+static DEVICE_ATTR_WO(eject);
 
-static ssize_t power_control_store(struct device *dev,
-                                  struct device_attribute *attr,
-                                  const char *buf, size_t size)
+static ssize_t module_id_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
 {
-       // FIXME
-       // Implement something here when we have a working control protocol
-       return 0;
-}
-static DEVICE_ATTR_RW(power_control);
+       struct gb_module *module = to_gb_module(dev);
 
-static ssize_t present_show(struct device *dev,
-                           struct device_attribute *addr, char *buf)
-{
-       // FIXME
-       // Implement something here when we have a working control protocol
-       return sprintf(buf, "1\n");
+       return sprintf(buf, "%u\n", module->module_id);
 }
+static DEVICE_ATTR_RO(module_id);
 
-static ssize_t present_store(struct device *dev, struct device_attribute *attr,
-                            const char *buf, size_t size)
+static ssize_t num_interfaces_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
 {
-       // FIXME
-       // Implement something here when we have a working control protocol
-       return 0;
+       struct gb_module *module = to_gb_module(dev);
+
+       return sprintf(buf, "%zu\n", module->num_interfaces);
 }
-static DEVICE_ATTR_RW(present);
+static DEVICE_ATTR_RO(num_interfaces);
 
 static struct attribute *module_attrs[] = {
-       &dev_attr_epm.attr,
-       &dev_attr_power_control.attr,
-       &dev_attr_present.attr,
+       &dev_attr_eject.attr,
+       &dev_attr_module_id.attr,
+       &dev_attr_num_interfaces.attr,
        NULL,
 };
 ATTRIBUTE_GROUPS(module);
@@ -75,104 +78,175 @@ static void gb_module_release(struct device *dev)
 {
        struct gb_module *module = to_gb_module(dev);
 
+       trace_gb_module_release(module);
+
        kfree(module);
 }
 
 struct device_type greybus_module_type = {
-       .name =         "greybus_module",
-       .release =      gb_module_release,
+       .name           = "greybus_module",
+       .release        = gb_module_release,
 };
 
-struct module_find {
-       struct gb_endo *endo;
-       u8 module_id;
-};
-
-static int module_find(struct device *dev, void *data)
+struct gb_module *gb_module_create(struct gb_host_device *hd, u8 module_id,
+                                       size_t num_interfaces)
 {
+       struct gb_interface *intf;
        struct gb_module *module;
-       struct module_find *find = data;
+       int i;
 
-       if (!is_gb_module(dev))
-               return 0;
+       module = kzalloc(sizeof(*module) + num_interfaces * sizeof(intf),
+                               GFP_KERNEL);
+       if (!module)
+               return NULL;
 
-       module = to_gb_module(dev);
-       if ((module->module_id == find->module_id) &&
-           (module->dev.parent == &find->endo->dev))
-               return 1;
+       module->hd = hd;
+       module->module_id = module_id;
+       module->num_interfaces = num_interfaces;
 
-       return 0;
+       module->dev.parent = &hd->dev;
+       module->dev.bus = &greybus_bus_type;
+       module->dev.type = &greybus_module_type;
+       module->dev.groups = module_groups;
+       module->dev.dma_mask = hd->dev.dma_mask;
+       device_initialize(&module->dev);
+       dev_set_name(&module->dev, "%d-%u", hd->bus_id, module_id);
+
+       trace_gb_module_create(module);
+
+       for (i = 0; i < num_interfaces; ++i) {
+               intf = gb_interface_create(module, module_id + i);
+               if (!intf) {
+                       dev_err(&module->dev, "failed to create interface %u\n",
+                                       module_id + i);
+                       goto err_put_interfaces;
+               }
+               module->interfaces[i] = intf;
+       }
+
+       return module;
+
+err_put_interfaces:
+       for (--i; i > 0; --i)
+               gb_interface_put(module->interfaces[i]);
+
+       put_device(&module->dev);
+
+       return NULL;
 }
 
 /*
- * Search the list of modules in the system.  If one is found, return it, with
- * the reference count incremented.
+ * Register and enable an interface after first attempting to activate it.
  */
-struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id)
+static void gb_module_register_interface(struct gb_interface *intf)
 {
-       struct device *dev;
-       struct gb_module *module = NULL;
-       struct module_find find;
+       struct gb_module *module = intf->module;
+       u8 intf_id = intf->interface_id;
+       int ret;
+       int retries = 3;
 
-       if (!module_id)
-               return NULL;
+       mutex_lock(&intf->mutex);
+
+       while (retries--) {
+               ret = gb_interface_activate(intf);
+               if (ret != -EAGAIN)
+                       break;
+       }
+       if (ret) {
+               dev_err(&module->dev, "failed to activate interface %u: %d\n",
+                               intf_id, ret);
+
+               /*
+                * -EAGAIN indicates that the Greybus operation
+                * interface_activate determined the remote interface to be
+                * UniPro-only.  At present, we assume a UniPro-only module
+                * to be a Greybus module that failed to send its mailbox
+                * poke.  There is some reason to believe that this is
+                * because of a bug in the ES3 bootrom.  If we exhause our
+                * retries trying to activate such an interface, convert
+                * the error code back into a "no device" error.
+                */
+               if (ret == -EAGAIN)
+                       ret = -ENODEV;
+
+               gb_interface_add(intf);
+               goto err_unlock;
+       }
+
+       ret = gb_interface_add(intf);
+       if (ret)
+               goto err_interface_deactivate;
 
-       find.module_id = module_id;
-       find.endo = hd->endo;
+       ret = gb_interface_enable(intf);
+       if (ret) {
+               dev_err(&module->dev, "failed to enable interface %u: %d\n",
+                               intf_id, ret);
+               goto err_interface_deactivate;
+       }
 
-       dev = bus_find_device(&greybus_bus_type, NULL,
-                             &find, module_find);
-       if (dev)
-               module = to_gb_module(dev);
+       mutex_unlock(&intf->mutex);
 
-       return module;
+       return;
+
+err_interface_deactivate:
+       gb_interface_deactivate(intf);
+err_unlock:
+       mutex_unlock(&intf->mutex);
 }
 
-struct gb_module *gb_module_create(struct device *parent, u8 module_id)
+static void gb_module_deregister_interface(struct gb_interface *intf)
 {
-       struct gb_module *module;
-       int retval;
+       /* Mark as disconnected to prevent I/O during disable. */
+       if (intf->module->disconnected)
+               intf->disconnected = true;
 
-       module = kzalloc(sizeof(*module), GFP_KERNEL);
-       if (!module)
-               return NULL;
+       mutex_lock(&intf->mutex);
+       gb_interface_disable(intf);
+       gb_interface_deactivate(intf);
+       mutex_unlock(&intf->mutex);
 
-       module->module_id = module_id;
-       module->dev.parent = parent;
-       module->dev.bus = &greybus_bus_type;
-       module->dev.type = &greybus_module_type;
-       module->dev.groups = module_groups;
-       module->dev.dma_mask = parent->dma_mask;
-       device_initialize(&module->dev);
-       dev_set_name(&module->dev, "%s:%hhu", dev_name(parent), module_id);
+       gb_interface_del(intf);
+}
 
-       retval = device_add(&module->dev);
-       if (retval) {
-               pr_err("failed to add module device for id 0x%02hhx\n",
-                       module_id);
-               put_device(&module->dev);
-               return NULL;
+/* Register a module and its interfaces. */
+int gb_module_add(struct gb_module *module)
+{
+       size_t i;
+       int ret;
+
+       ret = device_add(&module->dev);
+       if (ret) {
+               dev_err(&module->dev, "failed to register module: %d\n", ret);
+               return ret;
        }
 
-       return module;
+       trace_gb_module_add(module);
+
+       for (i = 0; i < module->num_interfaces; ++i)
+               gb_module_register_interface(module->interfaces[i]);
+
+       return 0;
 }
 
-static int module_remove(struct device *dev, void *data)
+/* Deregister a module and its interfaces. */
+void gb_module_del(struct gb_module *module)
 {
-       struct gb_module *module;
-       struct gb_endo *endo = data;
+       size_t i;
 
-       if (!is_gb_module(dev))
-               return 0;
+       for (i = 0; i < module->num_interfaces; ++i)
+               gb_module_deregister_interface(module->interfaces[i]);
 
-       module = to_gb_module(dev);
-       if (module->dev.parent == &endo->dev)
-               device_unregister(&module->dev);
+       trace_gb_module_del(module);
 
-       return 0;
+       device_del(&module->dev);
 }
 
-void gb_module_remove_all(struct gb_endo *endo)
+void gb_module_put(struct gb_module *module)
 {
-       bus_for_each_dev(&greybus_bus_type, NULL, endo, module_remove);
+       size_t i;
+
+       for (i = 0; i < module->num_interfaces; ++i)
+               gb_interface_put(module->interfaces[i]);
+
+       put_device(&module->dev);
 }