staging: most: core: replace struct most_inst_obj

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@microchip.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Christian Gromm 2017-11-21 15:04:56 +01:00 committed by Greg Kroah-Hartman
parent ec0c2f62ab
commit 9136fccf38
2 changed files with 99 additions and 103 deletions

View File

@ -56,7 +56,6 @@ struct most_channel {
struct mutex nq_mutex; /* nq thread synchronization */ struct mutex nq_mutex; /* nq thread synchronization */
int is_starving; int is_starving;
struct most_interface *iface; struct most_interface *iface;
struct most_inst_obj *inst;
struct most_channel_config cfg; struct most_channel_config cfg;
bool keep_mbo; bool keep_mbo;
bool enqueue_halt; bool enqueue_halt;
@ -73,12 +72,11 @@ struct most_channel {
#define to_channel(d) container_of(d, struct most_channel, dev) #define to_channel(d) container_of(d, struct most_channel, dev)
struct most_inst_obj { struct interface_private {
int dev_id; int dev_id;
struct most_interface *iface; char name[STRING_SIZE];
struct list_head channel_list;
struct most_channel *channel[MAX_CHANNELS]; struct most_channel *channel[MAX_CHANNELS];
struct list_head list; struct list_head channel_list;
}; };
static const struct { static const struct {
@ -472,9 +470,6 @@ static const struct attribute_group *channel_attr_groups[] = {
/* ___ ___ /* ___ ___
* ___I N S T A N C E___ * ___I N S T A N C E___
*/ */
static struct list_head instance_list;
static ssize_t description_show(struct device *dev, static ssize_t description_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
@ -545,33 +540,38 @@ static struct most_aim *match_module(char *name)
return NULL; 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; 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, &iface->p->channel_list, list) {
list_for_each_entry(c, &i->channel_list, list) { if (c->pipe0.aim) {
if (c->pipe0.aim) { offs += snprintf(buf + offs,
offs += snprintf(buf + offs, PAGE_SIZE - offs,
PAGE_SIZE - offs, "%s:%s:%s\n",
"%s:%s:%s\n", c->pipe0.aim->name,
c->pipe0.aim->name, dev_name(&iface->dev),
dev_name(&i->iface->dev), dev_name(&c->dev));
dev_name(&c->dev)); }
} if (c->pipe1.aim) {
if (c->pipe1.aim) { offs += snprintf(buf + offs,
offs += snprintf(buf + offs, PAGE_SIZE - offs,
PAGE_SIZE - offs, "%s:%s:%s\n",
"%s:%s:%s\n", c->pipe1.aim->name,
c->pipe1.aim->name, dev_name(&iface->dev),
dev_name(&i->iface->dev), dev_name(&c->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) static ssize_t modules_show(struct device_driver *drv, char *buf)
@ -627,6 +627,13 @@ static int split_string(char *buf, char **a, char **b, char **c, char **d)
return 0; 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 * get_channel - get pointer to channel object
* @mdev: name of the device instance * @mdev: name of the device instance
@ -636,28 +643,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) 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_channel *c, *tmp;
struct most_inst_obj *i, *i_tmp;
int found = 0;
list_for_each_entry_safe(i, i_tmp, &instance_list, list) { dev = bus_find_device(&mc.bus, NULL, mdev, match_bus_dev);
if (!strcmp(dev_name(&i->iface->dev), mdev)) { if (!dev)
found++; return NULL;
break; 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)) return NULL;
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;
}
}
if (unlikely(found < 2))
return ERR_PTR(-EIO);
return c;
} }
static static
@ -735,7 +733,7 @@ static ssize_t add_link_store(struct device_driver *drv,
} }
c = get_channel(mdev, mdev_ch); c = get_channel(mdev, mdev_ch);
if (IS_ERR(c)) if (!c)
return -ENODEV; return -ENODEV;
ret = link_channel_to_aim(c, aim, aim_param); ret = link_channel_to_aim(c, aim, aim_param);
@ -774,7 +772,7 @@ static ssize_t remove_link_store(struct device_driver *drv,
return ret; return ret;
aim = match_module(aim_name); aim = match_module(aim_name);
c = get_channel(mdev, mdev_ch); c = get_channel(mdev, mdev_ch);
if (IS_ERR(c)) if (!c)
return -ENODEV; return -ENODEV;
if (aim->disconnect_channel(c->iface, c->channel_id)) if (aim->disconnect_channel(c->iface, c->channel_id))
@ -1042,8 +1040,7 @@ static void most_write_completion(struct mbo *mbo)
int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) 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 = iface->p->channel[id];
struct most_channel *c = inst->channel[id];
unsigned long flags; unsigned long flags;
int empty; int empty;
@ -1075,11 +1072,10 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id,
{ {
struct mbo *mbo; struct mbo *mbo;
struct most_channel *c; struct most_channel *c;
struct most_inst_obj *inst = iface->priv;
unsigned long flags; unsigned long flags;
int *num_buffers_ptr; int *num_buffers_ptr;
c = inst->channel[id]; c = iface->p->channel[id];
if (unlikely(!c)) if (unlikely(!c))
return NULL; return NULL;
@ -1181,8 +1177,7 @@ int most_start_channel(struct most_interface *iface, int id,
{ {
int num_buffer; int num_buffer;
int ret; int ret;
struct most_inst_obj *inst = iface->priv; struct most_channel *c = iface->p->channel[id];
struct most_channel *c = inst->channel[id];
if (unlikely(!c)) if (unlikely(!c))
return -EINVAL; return -EINVAL;
@ -1250,15 +1245,13 @@ EXPORT_SYMBOL_GPL(most_start_channel);
int most_stop_channel(struct most_interface *iface, int id, int most_stop_channel(struct most_interface *iface, int id,
struct most_aim *aim) struct most_aim *aim)
{ {
struct most_inst_obj *inst;
struct most_channel *c; struct most_channel *c;
if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
pr_err("Bad interface or index out of range\n"); pr_err("Bad interface or index out of range\n");
return -EINVAL; return -EINVAL;
} }
inst = iface->priv; c = iface->p->channel[id];
c = inst->channel[id];
if (unlikely(!c)) if (unlikely(!c))
return -EINVAL; return -EINVAL;
@ -1320,33 +1313,38 @@ int most_register_aim(struct most_aim *aim)
} }
EXPORT_SYMBOL_GPL(most_register_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 * most_deregister_aim - deregisters an AIM (driver) with the core
* @aim: AIM to be removed * @aim: AIM to be removed
*/ */
int most_deregister_aim(struct most_aim *aim) int most_deregister_aim(struct most_aim *aim)
{ {
struct most_channel *c, *tmp;
struct most_inst_obj *i, *i_tmp;
if (!aim) { if (!aim) {
pr_err("Bad driver\n"); pr_err("Bad driver\n");
return -EINVAL; return -EINVAL;
} }
list_for_each_entry_safe(i, i_tmp, &instance_list, list) { bus_for_each_dev(&mc.bus, NULL, aim, disconnect_channels);
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;
}
}
list_del(&aim->list); list_del(&aim->list);
pr_info("deregistering application interfacing module %s\n", aim->name); pr_info("deregistering module %s\n", aim->name);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(most_deregister_aim); EXPORT_SYMBOL_GPL(most_deregister_aim);
@ -1372,10 +1370,8 @@ int most_register_interface(struct most_interface *iface)
{ {
unsigned int i; unsigned int i;
int id; int id;
char name[STRING_SIZE];
char channel_name[STRING_SIZE]; char channel_name[STRING_SIZE];
struct most_channel *c; struct most_channel *c;
struct most_inst_obj *inst;
if (!iface || !iface->enqueue || !iface->configure || if (!iface || !iface->enqueue || !iface->configure ||
!iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) {
@ -1389,27 +1385,24 @@ int most_register_interface(struct most_interface *iface)
return id; return id;
} }
inst = kzalloc(sizeof(*inst), GFP_KERNEL); iface->p = kzalloc(sizeof(*iface->p), GFP_KERNEL);
if (!inst) { if (!iface->p) {
pr_info("Failed to allocate interface instance\n"); pr_info("Failed to allocate interface instance\n");
ida_simple_remove(&mdev_id, id); ida_simple_remove(&mdev_id, id);
return -ENOMEM; return -ENOMEM;
} }
iface->priv = inst; INIT_LIST_HEAD(&iface->p->channel_list);
INIT_LIST_HEAD(&inst->channel_list); iface->p->dev_id = id;
inst->iface = iface; snprintf(iface->p->name, STRING_SIZE, "mdev%d", id);
inst->dev_id = id; iface->dev.init_name = iface->p->name;
list_add_tail(&inst->list, &instance_list);
snprintf(name, STRING_SIZE, "mdev%d", id);
iface->dev.init_name = name;
iface->dev.bus = &mc.bus; iface->dev.bus = &mc.bus;
iface->dev.parent = &mc.dev; iface->dev.parent = &mc.dev;
iface->dev.groups = interface_attr_groups; iface->dev.groups = interface_attr_groups;
iface->dev.release = release_interface; iface->dev.release = release_interface;
if (device_register(&iface->dev)) { if (device_register(&iface->dev)) {
pr_err("registering iface->dev failed\n"); pr_err("registering iface->dev failed\n");
kfree(inst); kfree(iface->p);
ida_simple_remove(&mdev_id, id); ida_simple_remove(&mdev_id, id);
return -ENOMEM; return -ENOMEM;
} }
@ -1422,7 +1415,6 @@ int most_register_interface(struct most_interface *iface)
else else
snprintf(channel_name, STRING_SIZE, "%s", name_suffix); snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
/* this increments the reference count of this instance */
c = kzalloc(sizeof(*c), GFP_KERNEL); c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c) if (!c)
goto free_instance; goto free_instance;
@ -1432,12 +1424,11 @@ int most_register_interface(struct most_interface *iface)
c->dev.release = release_channel; c->dev.release = release_channel;
if (device_register(&c->dev)) { if (device_register(&c->dev)) {
pr_err("registering c->dev failed\n"); 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->is_starving = 0;
c->iface = iface; c->iface = iface;
c->inst = inst;
c->channel_id = i; c->channel_id = i;
c->keep_mbo = false; c->keep_mbo = false;
c->enqueue_halt = false; c->enqueue_halt = false;
@ -1456,14 +1447,22 @@ int most_register_interface(struct most_interface *iface)
atomic_set(&c->mbo_ref, 0); atomic_set(&c->mbo_ref, 0);
mutex_init(&c->start_mutex); mutex_init(&c->start_mutex);
mutex_init(&c->nq_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", pr_info("registered new MOST device mdev%d (%s)\n",
id, iface->description); id, iface->description);
return 0; return 0;
free_instance_nodev:
kfree(c);
free_instance: 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); device_unregister(&iface->dev);
ida_simple_remove(&mdev_id, id); ida_simple_remove(&mdev_id, id);
return -ENOMEM; return -ENOMEM;
@ -1481,12 +1480,10 @@ void most_deregister_interface(struct most_interface *iface)
{ {
int i; int i;
struct most_channel *c; struct most_channel *c;
struct most_inst_obj *inst;
pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description); 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++) { for (i = 0; i < iface->num_channels; i++) {
c = inst->channel[i]; c = iface->p->channel[i];
if (c->pipe0.aim) if (c->pipe0.aim)
c->pipe0.aim->disconnect_channel(c->iface, c->pipe0.aim->disconnect_channel(c->iface,
c->channel_id); c->channel_id);
@ -1500,8 +1497,8 @@ void most_deregister_interface(struct most_interface *iface)
kfree(c); kfree(c);
} }
ida_simple_remove(&mdev_id, inst->dev_id); ida_simple_remove(&mdev_id, iface->p->dev_id);
kfree(inst); kfree(iface->p);
device_unregister(&iface->dev); device_unregister(&iface->dev);
} }
EXPORT_SYMBOL_GPL(most_deregister_interface); EXPORT_SYMBOL_GPL(most_deregister_interface);
@ -1518,8 +1515,7 @@ EXPORT_SYMBOL_GPL(most_deregister_interface);
*/ */
void most_stop_enqueue(struct most_interface *iface, int id) void most_stop_enqueue(struct most_interface *iface, int id)
{ {
struct most_inst_obj *inst = iface->priv; struct most_channel *c = iface->p->channel[id];
struct most_channel *c = inst->channel[id];
if (!c) if (!c)
return; return;
@ -1540,8 +1536,7 @@ EXPORT_SYMBOL_GPL(most_stop_enqueue);
*/ */
void most_resume_enqueue(struct most_interface *iface, int id) void most_resume_enqueue(struct most_interface *iface, int id)
{ {
struct most_inst_obj *inst = iface->priv; struct most_channel *c = iface->p->channel[id];
struct most_channel *c = inst->channel[id];
if (!c) if (!c)
return; return;
@ -1564,7 +1559,6 @@ static int __init most_init(void)
int err; int err;
pr_info("init()\n"); pr_info("init()\n");
INIT_LIST_HEAD(&instance_list);
INIT_LIST_HEAD(&mc.mod_list); INIT_LIST_HEAD(&mc.mod_list);
ida_init(&mdev_id); ida_init(&mdev_id);

View File

@ -20,6 +20,7 @@
#include <linux/device.h> #include <linux/device.h>
struct module; struct module;
struct interface_private;
/** /**
* Interface type * Interface type
@ -248,6 +249,7 @@ struct most_interface {
unsigned char link_stat, unsigned char link_stat,
unsigned char *mac_addr)); unsigned char *mac_addr));
void *priv; void *priv;
struct interface_private *p;
}; };
#define to_most_interface(d) container_of(d, struct most_interface, dev) #define to_most_interface(d) container_of(d, struct most_interface, dev)