INIT_LIST_HEAD(&hd->connections);
ida_init(&hd->cport_id_map);
+ hd->endo = gb_endo_create(hd);
+ if (!hd->endo) {
+ greybus_remove_hd(hd);
+ return NULL;
+ }
+
return hd;
}
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 */
+ /*
+ * Tear down all interfaces, modules, and the endo that is associated
+ * with this host controller before freeing the memory associated with
+ * the host controller.
+ */
gb_remove_interfaces(hd);
+ gb_endo_remove(hd->endo);
kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
}
EXPORT_SYMBOL_GPL(greybus_remove_hd);
}
for (i = 0; endo_modules[i] != 0x00; ++i) {
-// module = gb_module_create(&endo->dev, endo_modules[i]);
+ module = gb_module_create(&endo->dev, endo_modules[i]);
if (!module)
return -EINVAL;
}
return 0;
}
-static void remove_modules(struct gb_endo *endo)
-{
- /*
- * We really don't care how many modules have been created, or what the
- * configuration of them are, let's just enumerate over everything in
- * the system and delete all found modules.
- */
-
-}
-
struct gb_endo *gb_endo_create(struct greybus_host_device *hd)
{
struct gb_endo *endo;
if (!endo)
return;
- /* remove all modules first */
- remove_modules(endo);
+ /* remove all modules for this endo */
+ gb_module_remove_all(endo);
device_unregister(&endo->dev);
}
return interface_id;
}
+struct module_find {
+ struct gb_endo *endo;
+ u8 module_id;
+};
+
static int module_find(struct device *dev, void *data)
{
struct gb_module *module;
- u8 *module_id = data;
+ struct module_find *find = data;
if (!is_gb_module(dev))
return 0;
module = to_gb_module(dev);
- if (module->module_id == *module_id)
+ if ((module->module_id == find->module_id) &&
+ (module->dev.parent == &find->endo->dev))
return 1;
return 0;
* Search the list of modules in the system. If one is found, return it, with
* the reference count incremented.
*/
-static struct gb_module *gb_module_find(u8 module_id)
+struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id)
{
struct device *dev;
struct gb_module *module = NULL;
+ struct module_find find;
+
+ find.module_id = module_id;
+ find.endo = hd->endo;
dev = bus_find_device(&greybus_bus_type, NULL,
- &module_id, module_find);
+ &find, module_find);
if (dev)
module = to_gb_module(dev);
return module;
}
-static struct gb_module *gb_module_create(struct greybus_host_device *hd,
- u8 module_id)
+struct gb_module *gb_module_create(struct device *parent, u8 module_id)
{
struct gb_module *module;
int retval;
return NULL;
module->module_id = module_id;
- module->refcount = 1;
- module->dev.parent = hd->parent;
+ 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 = hd->parent->dma_mask;
+ module->dev.dma_mask = parent->dma_mask;
device_initialize(&module->dev);
dev_set_name(&module->dev, "%d", module_id);
return module;
}
-struct gb_module *gb_module_find_or_create(struct greybus_host_device *hd,
- u8 module_id)
+static int module_remove(struct device *dev, void *data)
{
struct gb_module *module;
+ struct gb_endo *endo = data;
- module = gb_module_find(module_id);
- if (module) {
- module->refcount++;
- return module;
- }
+ if (!is_gb_module(dev))
+ return 0;
+
+ module = to_gb_module(dev);
+ if (module->dev.parent == &endo->dev)
+ device_unregister(&module->dev);
- return gb_module_create(hd, module_id);
+ return 0;
}
-void gb_module_remove(struct gb_module *module)
+void gb_module_remove_all(struct gb_endo *endo)
{
- if (!module)
- return;
-
- if (!--module->refcount)
- device_unregister(&module->dev);
+ bus_for_each_dev(&greybus_bus_type, NULL, endo, module_remove);
}
-
struct gb_module {
struct device dev;
u8 module_id; /* Physical location within the Endo */
- u16 refcount;
};
#define to_gb_module(d) container_of(d, struct gb_module, dev)
struct greybus_host_device;
/* Greybus "private" definitions */
-struct gb_module *gb_module_find_or_create(struct greybus_host_device *hd,
- u8 module_id);
-void gb_module_remove(struct gb_module *module);
+struct gb_module *gb_module_find(struct greybus_host_device *hd, u8 module_id);
+struct gb_module *gb_module_create(struct device *parent, u8 module_id);
+void gb_module_remove_all(struct gb_endo *endo);
u8 get_module_id(u8 interface_id);