]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/staging/greybus/core.c
greybus: Random spell fixes
[karo-tx-linux.git] / drivers / staging / greybus / core.c
index bc27ad68cc8551db0501519595825b0731c9bf14..9203ebd2db7fd9198c3991580a18e667fe7c69eb 100644 (file)
@@ -32,26 +32,59 @@ EXPORT_SYMBOL_GPL(greybus_disabled);
 
 static int greybus_module_match(struct device *dev, struct device_driver *drv)
 {
-       struct greybus_driver *driver = to_greybus_driver(dev->driver);
+       struct greybus_driver *driver = to_greybus_driver(drv);
        struct gb_module *gmod = to_gb_module(dev);
        const struct greybus_module_id *id;
 
        id = gb_module_match_id(gmod, driver->id_table);
        if (id)
                return 1;
-       /* FIXME - Dyanmic ids? */
+       /* FIXME - Dynamic ids? */
        return 0;
 }
 
 static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
-       /* struct gb_module *gmod = to_gb_module(dev); */
+       struct gb_module *gmod = NULL;
+       struct gb_interface *interface = NULL;
+       struct gb_connection *connection = NULL;
+
+       if (is_gb_module(dev)) {
+               gmod = to_gb_module(dev);
+       } else if (is_gb_interface(dev)) {
+               interface = to_gb_interface(dev);
+               gmod = interface->gmod;
+       } else if (is_gb_connection(dev)) {
+               connection = to_gb_connection(dev);
+               interface = connection->interface;
+               gmod = interface->gmod;
+       } else {
+               dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n");
+               return -EINVAL;
+       }
+
+       if (connection) {
+               // FIXME
+               // add a uevent that can "load" a connection type
+               return 0;
+       }
 
-       /* FIXME - add some uevents here... */
+       if (interface) {
+               // FIXME
+               // add a uevent that can "load" a interface type
+               // This is what we need to bind a driver to so use the info
+               // in gmod here as well
+               return 0;
+       }
+
+       // FIXME
+       // "just" a module, be vague here, nothing binds to a module except
+       // the greybus core, so there's not much, if anything, we need to
+       // advertise.
        return 0;
 }
 
-static struct bus_type greybus_bus_type = {
+struct bus_type greybus_bus_type = {
        .name =         "greybus",
        .match =        greybus_module_match,
        .uevent =       greybus_uevent,
@@ -115,104 +148,6 @@ void greybus_deregister(struct greybus_driver *driver)
 EXPORT_SYMBOL_GPL(greybus_deregister);
 
 
-static void greybus_module_release(struct device *dev)
-{
-       struct gb_module *gmod = to_gb_module(dev);
-
-       gb_module_destroy(gmod);
-}
-
-static struct device_type greybus_module_type = {
-       .name =         "greybus_module",
-       .release =      greybus_module_release,
-};
-
-static const struct greybus_module_id fake_greybus_module_id = {
-       GREYBUS_DEVICE(0x42, 0x42)
-};
-
-
-/**
- * gb_add_module
- *
- * Pass in a buffer that _should_ contain a Greybus module manifest
- * and register a greybus device structure with the kernel core.
- */
-void gb_add_module(struct greybus_host_device *hd, u8 module_id,
-                  u8 *data, int size)
-{
-       struct gb_module *gmod;
-       int retval;
-
-       gmod = gb_module_create(hd, module_id);
-       if (!gmod) {
-               dev_err(hd->parent, "failed to create module\n");
-               return;
-       }
-
-       /*
-        * Parse the manifest and build up our data structures
-        * representing what's in it.
-        */
-       if (!gb_manifest_parse(gmod, data, size)) {
-               dev_err(hd->parent, "manifest error\n");
-               goto err_module;
-       }
-
-       /*
-        * XXX
-        * We've successfully parsed the manifest.  Now we need to
-        * allocate CPort Id's for connecting to the CPorts found on
-        * other modules.  For each of these, establish a connection
-        * between the local and remote CPorts (including
-        * configuring the switch to allow them to communicate).
-        */
-
-       gmod->dev.parent = hd->parent;
-       gmod->dev.driver = NULL;
-       gmod->dev.bus = &greybus_bus_type;
-       gmod->dev.type = &greybus_module_type;
-       gmod->dev.groups = greybus_module_groups;
-       gmod->dev.dma_mask = hd->parent->dma_mask;
-       device_initialize(&gmod->dev);
-       dev_set_name(&gmod->dev, "%d", module_id);
-
-       retval = device_add(&gmod->dev);
-       if (retval)
-               goto err_device;
-
-       gb_module_interfaces_init(gmod);
-
-       return;
-err_device:
-       put_device(&gmod->dev);
-err_module:
-       greybus_module_release(&gmod->dev);
-}
-
-void gb_remove_module(struct greybus_host_device *hd, u8 module_id)
-{
-       struct gb_module *gmod;
-       bool found = false;
-
-       list_for_each_entry(gmod, &hd->modules, links)
-               if (gmod->module_id == module_id) {
-                       found = true;
-                       break;
-               }
-
-       if (found)
-               greybus_remove_device(gmod);
-       else
-               dev_err(hd->parent, "module id %d remove error\n", module_id);
-}
-
-void greybus_remove_device(struct gb_module *gmod)
-{
-       device_del(&gmod->dev);
-       put_device(&gmod->dev);
-}
-
 static DEFINE_MUTEX(hd_mutex);
 
 static void free_hd(struct kref *kref)
@@ -230,6 +165,16 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
 {
        struct greybus_host_device *hd;
 
+       /*
+        * Validate that the driver implements all of the callbacks
+        * so that we don't have to every time we make them.
+        */
+       if ((!driver->buffer_send) || (!driver->buffer_cancel) ||
+           (!driver->submit_svc)) {
+               pr_err("Must implement all greybus_host_driver callbacks!\n");
+               return NULL;
+       }
+
        hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL);
        if (!hd)
                return NULL;
@@ -238,9 +183,8 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
        hd->parent = parent;
        hd->driver = driver;
        INIT_LIST_HEAD(&hd->modules);
-       hd->connections = RB_ROOT;
+       INIT_LIST_HEAD(&hd->connections);
        ida_init(&hd->cport_id_map);
-       spin_lock_init(&hd->cport_id_map_lock);
 
        return hd;
 }
@@ -248,6 +192,9 @@ EXPORT_SYMBOL_GPL(greybus_create_hd);
 
 void greybus_remove_hd(struct greybus_host_device *hd)
 {
+       /* Tear down all modules that happen to be associated with this host
+        * controller */
+       gb_remove_modules(hd);
        kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
 }
 EXPORT_SYMBOL_GPL(greybus_remove_hd);
@@ -276,38 +223,27 @@ static int __init gb_init(void)
                goto error_ap;
        }
 
-       retval = gb_gbuf_init();
-       if (retval) {
-               pr_err("gb_gbuf_init failed\n");
-               goto error_gbuf;
-       }
-
        retval = gb_operation_init();
        if (retval) {
                pr_err("gb_operation_init failed\n");
                goto error_operation;
        }
 
-       retval = gb_tty_init();
-       if (retval) {
-               pr_err("gb_tty_init failed\n");
-               goto error_tty;
+       if (!gb_protocol_init()) {
+               /* This only fails for duplicate protocol registration */
+               retval = -EEXIST;
+               pr_err("gb_protocol_init failed\n");
+               goto error_protocol;
        }
 
-       return 0;
+       return 0;       /* Success */
 
-error_tty:
+error_protocol:
        gb_operation_exit();
-
 error_operation:
-       gb_gbuf_exit();
-
-error_gbuf:
        gb_ap_exit();
-
 error_ap:
        bus_unregister(&greybus_bus_type);
-
 error_bus:
        gb_debugfs_cleanup();
 
@@ -316,9 +252,8 @@ error_bus:
 
 static void __exit gb_exit(void)
 {
-       gb_tty_exit();
+       gb_protocol_exit();
        gb_operation_exit();
-       gb_gbuf_exit();
        gb_ap_exit();
        bus_unregister(&greybus_bus_type);
        gb_debugfs_cleanup();