This patch introduces struct interface_private as a replacement for the struct most_inst_obj. This structure holds private data that is only needed by the core module and will be accessed by a pointer from within the most_interface structure. As a result of this replacement the bus helper functions can be used to search for devices. Signed-off-by: Christian Gromm <christian.gromm@xxxxxxxxxxxxx> --- drivers/staging/most/core.c | 200 +++++++++++++++++++++----------------------- drivers/staging/most/core.h | 2 + 2 files changed, 99 insertions(+), 103 deletions(-) diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 4caea38..87178a8 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -62,7 +62,6 @@ struct most_channel { struct mutex nq_mutex; /* nq thread synchronization */ int is_starving; struct most_interface *iface; - struct most_inst_obj *inst; struct most_channel_config cfg; bool keep_mbo; bool enqueue_halt; @@ -79,12 +78,11 @@ struct most_channel { #define to_channel(d) container_of(d, struct most_channel, dev) -struct most_inst_obj { +struct interface_private { int dev_id; - struct most_interface *iface; - struct list_head channel_list; + char name[STRING_SIZE]; struct most_channel *channel[MAX_CHANNELS]; - struct list_head list; + struct list_head channel_list; }; static const struct { @@ -478,9 +476,6 @@ static const struct attribute_group *channel_attr_groups[] = { /* ___ ___ * ___I N S T A N C E___ */ - -static struct list_head instance_list; - static ssize_t description_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -551,33 +546,38 @@ static struct most_aim *match_module(char *name) return NULL; } -static ssize_t links_show(struct device_driver *drv, char *buf) +int print_links(struct device *dev, void *data) { - struct most_channel *c; - struct most_inst_obj *i; int offs = 0; + char *buf = data; + struct most_channel *c; + struct most_interface *iface = to_most_interface(dev); - list_for_each_entry(i, &instance_list, list) { - list_for_each_entry(c, &i->channel_list, list) { - if (c->pipe0.aim) { - offs += snprintf(buf + offs, - PAGE_SIZE - offs, - "%s:%s:%s\n", - c->pipe0.aim->name, - dev_name(&i->iface->dev), - dev_name(&c->dev)); - } - if (c->pipe1.aim) { - offs += snprintf(buf + offs, - PAGE_SIZE - offs, - "%s:%s:%s\n", - c->pipe1.aim->name, - dev_name(&i->iface->dev), - dev_name(&c->dev)); - } + list_for_each_entry(c, &iface->p->channel_list, list) { + if (c->pipe0.aim) { + offs += snprintf(buf + offs, + PAGE_SIZE - offs, + "%s:%s:%s\n", + c->pipe0.aim->name, + dev_name(&iface->dev), + dev_name(&c->dev)); + } + if (c->pipe1.aim) { + offs += snprintf(buf + offs, + PAGE_SIZE - offs, + "%s:%s:%s\n", + c->pipe1.aim->name, + dev_name(&iface->dev), + dev_name(&c->dev)); } } - return offs; + return 0; +} + +static ssize_t links_show(struct device_driver *drv, char *buf) +{ + bus_for_each_dev(&mc.bus, NULL, buf, print_links); + return strlen(buf); } static ssize_t modules_show(struct device_driver *drv, char *buf) @@ -633,6 +633,13 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d) return 0; } +static int match_bus_dev(struct device *dev, void *data) +{ + char *mdev_name = data; + + return !strcmp(dev_name(dev), mdev_name); +} + /** * get_channel - get pointer to channel object * @mdev: name of the device instance @@ -642,28 +649,19 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d) */ static struct most_channel *get_channel(char *mdev, char *mdev_ch) { + struct device *dev = NULL; + struct most_interface *iface; struct most_channel *c, *tmp; - struct most_inst_obj *i, *i_tmp; - int found = 0; - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - if (!strcmp(dev_name(&i->iface->dev), mdev)) { - found++; - break; - } - } - if (unlikely(!found)) - return ERR_PTR(-EIO); - - list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (!strcmp(dev_name(&c->dev), mdev_ch)) { - found++; - break; - } + dev = bus_find_device(&mc.bus, NULL, mdev, match_bus_dev); + if (!dev) + return NULL; + iface = to_most_interface(dev); + list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { + if (!strcmp(dev_name(&c->dev), mdev_ch)) + return c; } - if (unlikely(found < 2)) - return ERR_PTR(-EIO); - return c; + return NULL; } static @@ -741,7 +739,7 @@ static ssize_t add_link_store(struct device_driver *drv, } c = get_channel(mdev, mdev_ch); - if (IS_ERR(c)) + if (!c) return -ENODEV; ret = link_channel_to_aim(c, aim, aim_param); @@ -780,7 +778,7 @@ static ssize_t remove_link_store(struct device_driver *drv, return ret; aim = match_module(aim_name); c = get_channel(mdev, mdev_ch); - if (IS_ERR(c)) + if (!c) return -ENODEV; if (aim->disconnect_channel(c->iface, c->channel_id)) @@ -1048,8 +1046,7 @@ static void most_write_completion(struct mbo *mbo) int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) { - struct most_inst_obj *inst = iface->priv; - struct most_channel *c = inst->channel[id]; + struct most_channel *c = iface->p->channel[id]; unsigned long flags; int empty; @@ -1081,11 +1078,10 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id, { struct mbo *mbo; struct most_channel *c; - struct most_inst_obj *inst = iface->priv; unsigned long flags; int *num_buffers_ptr; - c = inst->channel[id]; + c = iface->p->channel[id]; if (unlikely(!c)) return NULL; @@ -1187,8 +1183,7 @@ int most_start_channel(struct most_interface *iface, int id, { int num_buffer; int ret; - struct most_inst_obj *inst = iface->priv; - struct most_channel *c = inst->channel[id]; + struct most_channel *c = iface->p->channel[id]; if (unlikely(!c)) return -EINVAL; @@ -1256,15 +1251,13 @@ EXPORT_SYMBOL_GPL(most_start_channel); int most_stop_channel(struct most_interface *iface, int id, struct most_aim *aim) { - struct most_inst_obj *inst; struct most_channel *c; if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { pr_err("Bad interface or index out of range\n"); return -EINVAL; } - inst = iface->priv; - c = inst->channel[id]; + c = iface->p->channel[id]; if (unlikely(!c)) return -EINVAL; @@ -1326,33 +1319,38 @@ int most_register_aim(struct most_aim *aim) } EXPORT_SYMBOL_GPL(most_register_aim); +static int disconnect_channels(struct device *dev, void *data) +{ + struct most_interface *iface; + struct most_channel *c, *tmp; + struct most_aim *aim = data; + + iface = to_most_interface(dev); + list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { + if (c->pipe0.aim == aim || c->pipe1.aim == aim) + aim->disconnect_channel(c->iface, c->channel_id); + if (c->pipe0.aim == aim) + c->pipe0.aim = NULL; + if (c->pipe1.aim == aim) + c->pipe1.aim = NULL; + } + return 0; +} + /** * most_deregister_aim - deregisters an AIM (driver) with the core * @aim: AIM to be removed */ int most_deregister_aim(struct most_aim *aim) { - struct most_channel *c, *tmp; - struct most_inst_obj *i, *i_tmp; - if (!aim) { pr_err("Bad driver\n"); return -EINVAL; } - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (c->pipe0.aim == aim || c->pipe1.aim == aim) - aim->disconnect_channel( - c->iface, c->channel_id); - if (c->pipe0.aim == aim) - c->pipe0.aim = NULL; - if (c->pipe1.aim == aim) - c->pipe1.aim = NULL; - } - } + bus_for_each_dev(&mc.bus, NULL, aim, disconnect_channels); list_del(&aim->list); - pr_info("deregistering application interfacing module %s\n", aim->name); + pr_info("deregistering module %s\n", aim->name); return 0; } EXPORT_SYMBOL_GPL(most_deregister_aim); @@ -1378,10 +1376,8 @@ int most_register_interface(struct most_interface *iface) { unsigned int i; int id; - char name[STRING_SIZE]; char channel_name[STRING_SIZE]; struct most_channel *c; - struct most_inst_obj *inst; if (!iface || !iface->enqueue || !iface->configure || !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { @@ -1395,27 +1391,24 @@ int most_register_interface(struct most_interface *iface) return id; } - inst = kzalloc(sizeof(*inst), GFP_KERNEL); - if (!inst) { + iface->p = kzalloc(sizeof(*iface->p), GFP_KERNEL); + if (!iface->p) { pr_info("Failed to allocate interface instance\n"); ida_simple_remove(&mdev_id, id); return -ENOMEM; } - iface->priv = inst; - INIT_LIST_HEAD(&inst->channel_list); - inst->iface = iface; - inst->dev_id = id; - list_add_tail(&inst->list, &instance_list); - snprintf(name, STRING_SIZE, "mdev%d", id); - iface->dev.init_name = name; + INIT_LIST_HEAD(&iface->p->channel_list); + iface->p->dev_id = id; + snprintf(iface->p->name, STRING_SIZE, "mdev%d", id); + iface->dev.init_name = iface->p->name; iface->dev.bus = &mc.bus; iface->dev.parent = &mc.dev; iface->dev.groups = interface_attr_groups; iface->dev.release = release_interface; if (device_register(&iface->dev)) { pr_err("registering iface->dev failed\n"); - kfree(inst); + kfree(iface->p); ida_simple_remove(&mdev_id, id); return -ENOMEM; } @@ -1428,7 +1421,6 @@ int most_register_interface(struct most_interface *iface) else snprintf(channel_name, STRING_SIZE, "%s", name_suffix); - /* this increments the reference count of this instance */ c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) goto free_instance; @@ -1438,12 +1430,11 @@ int most_register_interface(struct most_interface *iface) c->dev.release = release_channel; if (device_register(&c->dev)) { pr_err("registering c->dev failed\n"); - goto free_instance; + goto free_instance_nodev; } - inst->channel[i] = c; + iface->p->channel[i] = c; c->is_starving = 0; c->iface = iface; - c->inst = inst; c->channel_id = i; c->keep_mbo = false; c->enqueue_halt = false; @@ -1462,14 +1453,22 @@ int most_register_interface(struct most_interface *iface) atomic_set(&c->mbo_ref, 0); mutex_init(&c->start_mutex); mutex_init(&c->nq_mutex); - list_add_tail(&c->list, &inst->channel_list); + list_add_tail(&c->list, &iface->p->channel_list); } pr_info("registered new MOST device mdev%d (%s)\n", id, iface->description); return 0; +free_instance_nodev: + kfree(c); + free_instance: - pr_info("Failed allocate channel(s)\n"); + while (i > 0) { + c = iface->p->channel[--i]; + device_unregister(&c->dev); + kfree(c); + } + kfree(iface->p); device_unregister(&iface->dev); ida_simple_remove(&mdev_id, id); return -ENOMEM; @@ -1487,12 +1486,10 @@ void most_deregister_interface(struct most_interface *iface) { int i; struct most_channel *c; - struct most_inst_obj *inst; pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description); - inst = iface->priv; for (i = 0; i < iface->num_channels; i++) { - c = inst->channel[i]; + c = iface->p->channel[i]; if (c->pipe0.aim) c->pipe0.aim->disconnect_channel(c->iface, c->channel_id); @@ -1506,8 +1503,8 @@ void most_deregister_interface(struct most_interface *iface) kfree(c); } - ida_simple_remove(&mdev_id, inst->dev_id); - kfree(inst); + ida_simple_remove(&mdev_id, iface->p->dev_id); + kfree(iface->p); device_unregister(&iface->dev); } EXPORT_SYMBOL_GPL(most_deregister_interface); @@ -1524,8 +1521,7 @@ EXPORT_SYMBOL_GPL(most_deregister_interface); */ void most_stop_enqueue(struct most_interface *iface, int id) { - struct most_inst_obj *inst = iface->priv; - struct most_channel *c = inst->channel[id]; + struct most_channel *c = iface->p->channel[id]; if (!c) return; @@ -1546,8 +1542,7 @@ EXPORT_SYMBOL_GPL(most_stop_enqueue); */ void most_resume_enqueue(struct most_interface *iface, int id) { - struct most_inst_obj *inst = iface->priv; - struct most_channel *c = inst->channel[id]; + struct most_channel *c = iface->p->channel[id]; if (!c) return; @@ -1570,7 +1565,6 @@ static int __init most_init(void) int err; pr_info("init()\n"); - INIT_LIST_HEAD(&instance_list); INIT_LIST_HEAD(&mc.mod_list); ida_init(&mdev_id); diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index a4fb75c..fe0ad62 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -26,6 +26,7 @@ #include <linux/device.h> struct module; +struct interface_private; /** * Interface type @@ -254,6 +255,7 @@ struct most_interface { unsigned char link_stat, unsigned char *mac_addr)); void *priv; + struct interface_private *p; }; #define to_most_interface(d) container_of(d, struct most_interface, dev) -- 2.7.4 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel