summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/greybus/core.c14
-rw-r--r--drivers/staging/greybus/endo.c16
-rw-r--r--drivers/staging/greybus/greybus.h2
-rw-r--r--drivers/staging/greybus/interface.c4
-rw-r--r--drivers/staging/greybus/module.c52
-rw-r--r--drivers/staging/greybus/module.h7
6 files changed, 50 insertions, 45 deletions
diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c
index 7c701f3..4580209 100644
--- a/drivers/staging/greybus/core.c
+++ b/drivers/staging/greybus/core.c
@@ -198,15 +198,25 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
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);
diff --git a/drivers/staging/greybus/endo.c b/drivers/staging/greybus/endo.c
index e3bb25f..28e1f28 100644
--- a/drivers/staging/greybus/endo.c
+++ b/drivers/staging/greybus/endo.c
@@ -91,7 +91,7 @@ static int create_modules(struct gb_endo *endo)
}
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;
}
@@ -99,16 +99,6 @@ static int create_modules(struct gb_endo *endo)
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;
@@ -156,8 +146,8 @@ void gb_endo_remove(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);
}
diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h
index e0aae42..109727f 100644
--- a/drivers/staging/greybus/greybus.h
+++ b/drivers/staging/greybus/greybus.h
@@ -98,6 +98,8 @@ struct greybus_host_device {
/* Host device buffer constraints */
size_t buffer_size_max;
+ struct gb_endo *endo;
+
/* Private data for the host driver */
unsigned long hd_priv[0] __aligned(sizeof(s64));
};
diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c
index 5b1d5dd..63665a2 100644
--- a/drivers/staging/greybus/interface.c
+++ b/drivers/staging/greybus/interface.c
@@ -92,7 +92,7 @@ static struct gb_interface *gb_interface_create(struct greybus_host_device *hd,
return NULL;
}
- module = gb_module_find_or_create(hd, get_module_id(interface_id));
+ module = gb_module_find(hd, get_module_id(interface_id));
if (!module)
return NULL;
@@ -157,7 +157,7 @@ static void gb_interface_destroy(struct gb_interface *intf)
module = intf->module;
device_unregister(&intf->dev);
- gb_module_remove(module);
+ put_device(&module->dev);
}
/**
diff --git a/drivers/staging/greybus/module.c b/drivers/staging/greybus/module.c
index 780d163..202f141 100644
--- a/drivers/staging/greybus/module.c
+++ b/drivers/staging/greybus/module.c
@@ -94,16 +94,22 @@ u8 get_module_id(u8 interface_id)
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;
@@ -113,21 +119,24 @@ static int module_find(struct device *dev, void *data)
* 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;
@@ -137,12 +146,11 @@ static struct gb_module *gb_module_create(struct greybus_host_device *hd,
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);
@@ -158,26 +166,22 @@ static struct gb_module *gb_module_create(struct greybus_host_device *hd,
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);
}
-
diff --git a/drivers/staging/greybus/module.h b/drivers/staging/greybus/module.h
index f3e3bdd..c23ac98 100644
--- a/drivers/staging/greybus/module.h
+++ b/drivers/staging/greybus/module.h
@@ -13,16 +13,15 @@
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);