summaryrefslogtreecommitdiff
path: root/drivers/staging/greybus/module.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2014-10-24 17:34:46 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-10-24 17:40:59 +0800
commitf0f61b90427b776b884821cde483528580f6d630 (patch)
tree51666ef5ef41806e6d8f5f5b27ce69da286a460e /drivers/staging/greybus/module.c
parent2d5e4fa9dc2e629b1ace5fa715f1d6bb2a71d61f (diff)
greybus: hook up greybus to the driver model
This patch hooks up modules, interfaces, and connections to the driver model. Now we have a correct hierarchy, and drivers can be correctly bound to the proper portions in the future. Devices are correctly reference counted and torn down in the proper order on removal of a module. Some basic sysfs attributes have been created for interfaces and connections. Module attributes are not working properly, but that will be fixed in future changes. This has been tested on Alex's machine, with multiple hotplug and unplug operations of a module working correctly. Signed-off-by: Greg Kroah-Hartman <greg@kroah.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/greybus/module.c')
-rw-r--r--drivers/staging/greybus/module.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c
index b1ec0904fb28..f9415c0f735e 100644
--- a/drivers/staging/greybus/module.c
+++ b/drivers/staging/greybus/module.c
@@ -44,15 +44,18 @@ const struct greybus_module_id *gb_module_match_id(struct gb_module *gmod,
return NULL;
}
-static void gb_module_interfaces_exit(struct gb_module *gmod)
+static void greybus_module_release(struct device *dev)
{
- struct gb_interface *interface;
- struct gb_interface *next;
+ struct gb_module *gmod = to_gb_module(dev);
- list_for_each_entry_safe(interface, next, &gmod->interfaces, links)
- gb_interface_destroy(interface);
+ kfree(gmod);
}
+static struct device_type greybus_module_type = {
+ .name = "greybus_module",
+ .release = greybus_module_release,
+};
+
/*
* A Greybus module represents a user-replacable component on an Ara
* phone.
@@ -65,6 +68,7 @@ static void gb_module_interfaces_exit(struct gb_module *gmod)
struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id)
{
struct gb_module *gmod;
+ int retval;
gmod = kzalloc(sizeof(*gmod), GFP_KERNEL);
if (!gmod)
@@ -78,6 +82,21 @@ struct gb_module *gb_module_create(struct greybus_host_device *hd, u8 module_id)
list_add_tail(&gmod->links, &hd->modules);
spin_unlock_irq(&gb_modules_lock);
+ 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) {
+ put_device(&gmod->dev);
+ return NULL;
+ }
+
return gmod;
}
@@ -93,18 +112,15 @@ void gb_module_destroy(struct gb_module *gmod)
list_del(&gmod->links);
spin_unlock_irq(&gb_modules_lock);
- gb_module_interfaces_exit(gmod);
/* XXX Do something with gmod->gb_tty */
- put_device(&gmod->dev);
- /* kfree(gmod->dev->name); */
+ gb_interface_destroy(gmod);
kfree(gmod->product_string);
kfree(gmod->vendor_string);
/* kref_put(module->hd); */
-
- kfree(gmod);
+ device_del(&gmod->dev);
}
struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id)