The following patch adapts the driver to use the device model by: - adopting the MOST bus_type - registering the core as a busdriver - removing private kobject/kset usage - removing private lists and structures to track registered modules and making use of the device model API - removing prefix of modules - allowing adapter drivers (a.k.a. HDM) to register MOST devices - registering AIM modules as components with the core to build the user space experience of the driver stack - using attribute groups to create the sysfs files - renaming variables to prevent collision with the introduced device structs. Signed-off-by: Christian Gromm <christian.gromm@xxxxxxxxxxxxx> --- drivers/staging/most/cdev/cdev.c | 6 +- drivers/staging/most/core.c | 930 ++++++++++++------------------------- drivers/staging/most/core.h | 9 +- drivers/staging/most/dim2/dim2.c | 20 +- drivers/staging/most/dim2/sysfs.c | 92 +--- drivers/staging/most/dim2/sysfs.h | 6 +- drivers/staging/most/i2c/i2c.c | 7 +- drivers/staging/most/net/net.c | 4 +- drivers/staging/most/sound/sound.c | 5 +- drivers/staging/most/usb/usb.c | 244 +++------- drivers/staging/most/video/video.c | 4 +- 11 files changed, 405 insertions(+), 922 deletions(-) diff --git a/drivers/staging/most/cdev/cdev.c b/drivers/staging/most/cdev/cdev.c index 3dce5e0..4b4c112 100644 --- a/drivers/staging/most/cdev/cdev.c +++ b/drivers/staging/most/cdev/cdev.c @@ -427,14 +427,14 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) */ static int aim_probe(struct most_interface *iface, int channel_id, struct most_channel_config *cfg, - struct kobject *parent, char *name) + char *name) { struct aim_channel *c; unsigned long cl_flags; int retval; int current_minor; - if ((!iface) || (!cfg) || (!parent) || (!name)) { + if ((!iface) || (!cfg) || (!name)) { pr_info("Probing AIM with bad arguments"); return -EINVAL; } @@ -498,7 +498,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, } static struct most_aim cdev_aim = { - .name = "cdev", + .name = "aim_cdev", .probe_channel = aim_probe, .disconnect_channel = aim_disconnect_channel, .rx_completion = aim_rx_completion, diff --git a/drivers/staging/most/core.c b/drivers/staging/most/core.c index 6ee6acf..54a56a0 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -33,7 +33,7 @@ #define STRING_SIZE 80 static struct class *most_class; -static struct device *core_dev; +static struct device core_dev; static struct ida mdev_id; static int dummy_num_buffers; @@ -44,7 +44,7 @@ struct most_c_aim_obj { }; struct most_c_obj { - struct kobject kobj; + struct device dev; struct completion cleanup; atomic_t mbo_ref; atomic_t mbo_nq_level; @@ -69,14 +69,13 @@ struct most_c_obj { wait_queue_head_t hdm_fifo_wq; }; -#define to_c_obj(d) container_of(d, struct most_c_obj, kobj) +#define to_c_obj(d) container_of(d, struct most_c_obj, dev) struct most_inst_obj { int dev_id; struct most_interface *iface; struct list_head channel_list; struct most_c_obj *channel[MAX_CHANNELS]; - struct kobject kobj; struct list_head list; }; @@ -91,8 +90,23 @@ struct most_inst_obj { { MOST_CH_ISOC, "isoc_avp\n"}, }; -#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) +int most_match(struct device *dev, struct device_driver *drv) +{ + if (!strcmp(dev_name(dev), "most")) + return 0; + else + return 1; +} + +static struct bus_type most_bus_type = { + .name = "most", + .match = most_match, +}; +static struct device_driver mostcore = { + .name = "most_core", + .bus = &most_bus_type, +}; /** * list_pop_mbo - retrieves the first MBO of the list and removes it * @ptr: the list head to grab the MBO from. @@ -108,67 +122,6 @@ struct most_inst_obj { * ___C H A N N E L___ */ -/** - * struct most_c_attr - to access the attributes of a channel object - * @attr: attributes of a channel - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_c_attr { - struct attribute attr; - ssize_t (*show)(struct most_c_obj *d, - struct most_c_attr *attr, - char *buf); - ssize_t (*store)(struct most_c_obj *d, - struct most_c_attr *attr, - const char *buf, - size_t count); -}; - -#define to_channel_attr(a) container_of(a, struct most_c_attr, attr) - -/** - * channel_attr_show - show function of channel object - * @kobj: pointer to its kobject - * @attr: pointer to its attributes - * @buf: buffer - */ -static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct most_c_attr *channel_attr = to_channel_attr(attr); - struct most_c_obj *c_obj = to_c_obj(kobj); - - if (!channel_attr->show) - return -EIO; - - return channel_attr->show(c_obj, channel_attr, buf); -} - -/** - * channel_attr_store - store function of channel object - * @kobj: pointer to its kobject - * @attr: pointer to its attributes - * @buf: buffer - * @len: length of buffer - */ -static ssize_t channel_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_c_attr *channel_attr = to_channel_attr(attr); - struct most_c_obj *c_obj = to_c_obj(kobj); - - if (!channel_attr->store) - return -EIO; - return channel_attr->store(c_obj, channel_attr, buf, len); -} - -static const struct sysfs_ops most_channel_sysfs_ops = { - .show = channel_attr_show, - .store = channel_attr_store, -}; /** * most_free_mbo_coherent - free an MBO and its coherent buffer @@ -241,21 +194,11 @@ static int flush_trash_fifo(struct most_c_obj *c) return 0; } -/** - * most_channel_release - release function of channel object - * @kobj: pointer to channel's kobject - */ -static void most_channel_release(struct kobject *kobj) -{ - struct most_c_obj *c = to_c_obj(kobj); - - kfree(c); -} - -static ssize_t available_directions_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t available_directions_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; strcpy(buf, ""); @@ -267,10 +210,11 @@ static ssize_t available_directions_show(struct most_c_obj *c, return strlen(buf); } -static ssize_t available_datatypes_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t available_datatypes_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; strcpy(buf, ""); @@ -286,65 +230,75 @@ static ssize_t available_datatypes_show(struct most_c_obj *c, return strlen(buf); } -static ssize_t number_of_packet_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t number_of_packet_buffers_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", c->iface->channel_vector[i].num_buffers_packet); } -static ssize_t number_of_stream_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t number_of_stream_buffers_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", c->iface->channel_vector[i].num_buffers_streaming); } -static ssize_t size_of_packet_buffer_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t size_of_packet_buffer_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", c->iface->channel_vector[i].buffer_size_packet); } -static ssize_t size_of_stream_buffer_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t size_of_stream_buffer_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); unsigned int i = c->channel_id; return snprintf(buf, PAGE_SIZE, "%d\n", c->iface->channel_vector[i].buffer_size_streaming); } -static ssize_t channel_starving_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t channel_starving_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving); } -static ssize_t set_number_of_buffers_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_number_of_buffers_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); } -static ssize_t set_number_of_buffers_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_number_of_buffers_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); + int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); if (ret) @@ -352,18 +306,22 @@ static ssize_t set_number_of_buffers_store(struct most_c_obj *c, return count; } -static ssize_t set_buffer_size_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_buffer_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); } -static ssize_t set_buffer_size_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_buffer_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); + int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); if (ret) @@ -371,10 +329,12 @@ static ssize_t set_buffer_size_store(struct most_c_obj *c, return count; } -static ssize_t set_direction_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_direction_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + if (c->cfg.direction & MOST_CH_TX) return snprintf(buf, PAGE_SIZE, "tx\n"); else if (c->cfg.direction & MOST_CH_RX) @@ -382,11 +342,13 @@ static ssize_t set_direction_show(struct most_c_obj *c, return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } -static ssize_t set_direction_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_direction_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); + if (!strcmp(buf, "dir_rx\n")) { c->cfg.direction = MOST_CH_RX; } else if (!strcmp(buf, "rx\n")) { @@ -402,11 +364,12 @@ static ssize_t set_direction_store(struct most_c_obj *c, return count; } -static ssize_t set_datatype_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_datatype_show(struct device *dev, + struct device_attribute *attr, char *buf) { int i; + struct most_c_obj *c = to_c_obj(dev); for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) @@ -415,12 +378,13 @@ static ssize_t set_datatype_show(struct most_c_obj *c, return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } -static ssize_t set_datatype_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_datatype_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { int i; + struct most_c_obj *c = to_c_obj(dev); for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { if (!strcmp(buf, ch_data_type[i].name)) { @@ -436,18 +400,22 @@ static ssize_t set_datatype_store(struct most_c_obj *c, return count; } -static ssize_t set_subbuffer_size_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_subbuffer_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); } -static ssize_t set_subbuffer_size_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_subbuffer_size_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); + int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); if (ret) @@ -455,18 +423,22 @@ static ssize_t set_subbuffer_size_store(struct most_c_obj *c, return count; } -static ssize_t set_packets_per_xact_show(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_packets_per_xact_show(struct device *dev, + struct device_attribute *attr, char *buf) { + struct most_c_obj *c = to_c_obj(dev); + return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); } -static ssize_t set_packets_per_xact_store(struct most_c_obj *c, - struct most_c_attr *attr, +static ssize_t set_packets_per_xact_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct most_c_obj *c = to_c_obj(dev); + int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); if (ret) @@ -474,77 +446,47 @@ static ssize_t set_packets_per_xact_store(struct most_c_obj *c, return count; } -static struct most_c_attr most_c_attrs[] = { - __ATTR_RO(available_directions), - __ATTR_RO(available_datatypes), - __ATTR_RO(number_of_packet_buffers), - __ATTR_RO(number_of_stream_buffers), - __ATTR_RO(size_of_stream_buffer), - __ATTR_RO(size_of_packet_buffer), - __ATTR_RO(channel_starving), - __ATTR_RW(set_buffer_size), - __ATTR_RW(set_number_of_buffers), - __ATTR_RW(set_direction), - __ATTR_RW(set_datatype), - __ATTR_RW(set_subbuffer_size), - __ATTR_RW(set_packets_per_xact), -}; - -/** - * most_channel_def_attrs - array of default attributes of channel object - */ -static struct attribute *most_channel_def_attrs[] = { - &most_c_attrs[0].attr, - &most_c_attrs[1].attr, - &most_c_attrs[2].attr, - &most_c_attrs[3].attr, - &most_c_attrs[4].attr, - &most_c_attrs[5].attr, - &most_c_attrs[6].attr, - &most_c_attrs[7].attr, - &most_c_attrs[8].attr, - &most_c_attrs[9].attr, - &most_c_attrs[10].attr, - &most_c_attrs[11].attr, - &most_c_attrs[12].attr, +#define DEV_ATTR(_name) &dev_attr_##_name.attr + +static DEVICE_ATTR_RO(available_directions); +static DEVICE_ATTR_RO(available_datatypes); +static DEVICE_ATTR_RO(number_of_packet_buffers); +static DEVICE_ATTR_RO(number_of_stream_buffers); +static DEVICE_ATTR_RO(size_of_stream_buffer); +static DEVICE_ATTR_RO(size_of_packet_buffer); +static DEVICE_ATTR_RO(channel_starving); +static DEVICE_ATTR_RW(set_buffer_size); +static DEVICE_ATTR_RW(set_number_of_buffers); +static DEVICE_ATTR_RW(set_direction); +static DEVICE_ATTR_RW(set_datatype); +static DEVICE_ATTR_RW(set_subbuffer_size); +static DEVICE_ATTR_RW(set_packets_per_xact); + +static struct attribute *channel_attrs[] = { + DEV_ATTR(available_directions), + DEV_ATTR(available_datatypes), + DEV_ATTR(number_of_packet_buffers), + DEV_ATTR(number_of_stream_buffers), + DEV_ATTR(size_of_stream_buffer), + DEV_ATTR(size_of_packet_buffer), + DEV_ATTR(channel_starving), + DEV_ATTR(set_buffer_size), + DEV_ATTR(set_number_of_buffers), + DEV_ATTR(set_direction), + DEV_ATTR(set_datatype), + DEV_ATTR(set_subbuffer_size), + DEV_ATTR(set_packets_per_xact), NULL, }; -static struct kobj_type most_channel_ktype = { - .sysfs_ops = &most_channel_sysfs_ops, - .release = most_channel_release, - .default_attrs = most_channel_def_attrs, +static struct attribute_group channel_attr_group = { + .attrs = channel_attrs, }; -static struct kset *most_channel_kset; - -/** - * create_most_c_obj - allocates a channel object - * @name: name of the channel object - * @parent: parent kobject - * - * This create a channel object and registers it with sysfs. - * Returns a pointer to the object or NULL when something went wrong. - */ -static struct most_c_obj * -create_most_c_obj(const char *name, struct kobject *parent) -{ - struct most_c_obj *c; - int retval; - - c = kzalloc(sizeof(*c), GFP_KERNEL); - if (!c) - return NULL; - c->kobj.kset = most_channel_kset; - retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent, - "%s", name); - if (retval) { - kobject_put(&c->kobj); - return NULL; - } - kobject_uevent(&c->kobj, KOBJ_ADD); - return c; -} +static const struct attribute_group *channel_attr_groups[] = { + &channel_attr_group, + NULL, +}; /* ___ ___ * ___I N S T A N C E___ @@ -552,103 +494,22 @@ static ssize_t set_packets_per_xact_store(struct most_c_obj *c, static struct list_head instance_list; -/** - * struct most_inst_attribute - to access the attributes of instance object - * @attr: attributes of an instance - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_inst_attribute { - struct attribute attr; - ssize_t (*show)(struct most_inst_obj *d, - struct most_inst_attribute *attr, - char *buf); - ssize_t (*store)(struct most_inst_obj *d, - struct most_inst_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_instance_attr(a) \ - container_of(a, struct most_inst_attribute, attr) - -/** - * instance_attr_show - show function for an instance object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t instance_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct most_inst_attribute *instance_attr; - struct most_inst_obj *instance_obj; - - instance_attr = to_instance_attr(attr); - instance_obj = to_inst_obj(kobj); - - if (!instance_attr->show) - return -EIO; - - return instance_attr->show(instance_obj, instance_attr, buf); -} - -/** - * instance_attr_store - store function for an instance object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t instance_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_inst_attribute *instance_attr; - struct most_inst_obj *instance_obj; - - instance_attr = to_instance_attr(attr); - instance_obj = to_inst_obj(kobj); - - if (!instance_attr->store) - return -EIO; - - return instance_attr->store(instance_obj, instance_attr, buf, len); -} - -static const struct sysfs_ops most_inst_sysfs_ops = { - .show = instance_attr_show, - .store = instance_attr_store, -}; - -/** - * most_inst_release - release function for instance object - * @kobj: pointer to instance's kobject - * - * This frees the allocated memory for the instance object - */ -static void most_inst_release(struct kobject *kobj) -{ - struct most_inst_obj *inst = to_inst_obj(kobj); - - kfree(inst); -} - -static ssize_t description_show(struct most_inst_obj *instance_obj, - struct most_inst_attribute *attr, +static ssize_t description_show(struct device *dev, + struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%s\n", - instance_obj->iface->description); + struct most_interface *iface = to_most_interface(dev); + + return snprintf(buf, PAGE_SIZE, "%s\n", iface->description); } -static ssize_t interface_show(struct most_inst_obj *instance_obj, - struct most_inst_attribute *attr, +static ssize_t interface_show(struct device *dev, + struct device_attribute *attr, char *buf) { - switch (instance_obj->iface->interface) { + struct most_interface *iface = to_most_interface(dev); + + switch (iface->interface) { case ITYPE_LOOPBACK: return snprintf(buf, PAGE_SIZE, "loopback\n"); case ITYPE_I2C: @@ -671,182 +532,45 @@ static ssize_t interface_show(struct most_inst_obj *instance_obj, return snprintf(buf, PAGE_SIZE, "unknown\n"); } -static struct most_inst_attribute most_inst_attr_description = - __ATTR_RO(description); +static DEVICE_ATTR_RO(description); +static DEVICE_ATTR_RO(interface); -static struct most_inst_attribute most_inst_attr_interface = - __ATTR_RO(interface); - -static struct attribute *most_inst_def_attrs[] = { - &most_inst_attr_description.attr, - &most_inst_attr_interface.attr, +static struct attribute *interface_attrs[] = { + DEV_ATTR(description), + DEV_ATTR(interface), NULL, }; -static struct kobj_type most_inst_ktype = { - .sysfs_ops = &most_inst_sysfs_ops, - .release = most_inst_release, - .default_attrs = most_inst_def_attrs, +static struct attribute_group interface_attr_group = { + .attrs = interface_attrs, }; -static struct kset *most_inst_kset; - -/** - * create_most_inst_obj - creates an instance object - * @name: name of the object to be created - * - * This allocates memory for an instance structure, assigns the proper kset - * and registers it with sysfs. - * - * Returns a pointer to the instance object or NULL when something went wrong. - */ -static struct most_inst_obj *create_most_inst_obj(const char *name) -{ - struct most_inst_obj *inst; - int retval; - - inst = kzalloc(sizeof(*inst), GFP_KERNEL); - if (!inst) - return NULL; - inst->kobj.kset = most_inst_kset; - retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL, - "%s", name); - if (retval) { - kobject_put(&inst->kobj); - return NULL; - } - kobject_uevent(&inst->kobj, KOBJ_ADD); - return inst; -} - -/** - * destroy_most_inst_obj - MOST instance release function - * @inst: pointer to the instance object - * - * This decrements the reference counter of the instance object. - * If the reference count turns zero, its release function is called - */ -static void destroy_most_inst_obj(struct most_inst_obj *inst) -{ - struct most_c_obj *c, *tmp; +static const struct attribute_group *interface_attr_groups[] = { + &interface_attr_group, + NULL, +}; - list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - flush_trash_fifo(c); - flush_channel_fifos(c); - kobject_put(&c->kobj); - } - kobject_put(&inst->kobj); -} /* ___ ___ * ___A I M___ */ -struct most_aim_obj { - struct kobject kobj; - struct list_head list; - struct most_aim *driver; -}; - -#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj) - static struct list_head aim_list; -/** - * struct most_aim_attribute - to access the attributes of AIM object - * @attr: attributes of an AIM - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_aim_attribute { - struct attribute attr; - ssize_t (*show)(struct most_aim_obj *d, - struct most_aim_attribute *attr, - char *buf); - ssize_t (*store)(struct most_aim_obj *d, - struct most_aim_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr) - -/** - * aim_attr_show - show function of an AIM object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t aim_attr_show(struct kobject *kobj, - struct attribute *attr, - char *buf) -{ - struct most_aim_attribute *aim_attr; - struct most_aim_obj *aim_obj; - - aim_attr = to_aim_attr(attr); - aim_obj = to_aim_obj(kobj); - - if (!aim_attr->show) - return -EIO; - - return aim_attr->show(aim_obj, aim_attr, buf); -} - -/** - * aim_attr_store - store function of an AIM object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t aim_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_aim_attribute *aim_attr; - struct most_aim_obj *aim_obj; - - aim_attr = to_aim_attr(attr); - aim_obj = to_aim_obj(kobj); - - if (!aim_attr->store) - return -EIO; - return aim_attr->store(aim_obj, aim_attr, buf, len); -} - -static const struct sysfs_ops most_aim_sysfs_ops = { - .show = aim_attr_show, - .store = aim_attr_store, -}; - -/** - * most_aim_release - AIM release function - * @kobj: pointer to AIM's kobject - */ -static void most_aim_release(struct kobject *kobj) -{ - struct most_aim_obj *aim_obj = to_aim_obj(kobj); - - kfree(aim_obj); -} - -static ssize_t links_show(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, +static ssize_t links_show(struct device *dev, struct device_attribute *attr, char *buf) { struct most_c_obj *c; struct most_inst_obj *i; + struct most_aim *aim = to_most_aim(dev); int offs = 0; list_for_each_entry(i, &instance_list, list) { list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.ptr == aim_obj->driver || - c->aim1.ptr == aim_obj->driver) { + if (c->aim0.ptr == aim || c->aim1.ptr == aim) { offs += snprintf(buf + offs, PAGE_SIZE - offs, "%s:%s\n", - kobject_name(&i->kobj), - kobject_name(&c->kobj)); + dev_name(&i->iface->dev), + dev_name(&c->dev)); } } } @@ -899,15 +623,14 @@ static int split_string(char *buf, char **a, char **b, char **c) * * This retrieves the pointer to a channel object. */ -static struct -most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) +static struct most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) { struct most_c_obj *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(kobject_name(&i->kobj), mdev)) { + if (!strcmp(dev_name(&i->iface->dev), mdev)) { found++; break; } @@ -916,7 +639,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) return ERR_PTR(-EIO); list_for_each_entry_safe(c, tmp, &i->channel_list, list) { - if (!strcmp(kobject_name(&c->kobj), mdev_ch)) { + if (!strcmp(dev_name(&c->dev), mdev_ch)) { found++; break; } @@ -926,6 +649,30 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) return c; } +static int link_channel_to_aim(struct most_c_obj *c, struct most_aim *aim, + char *aim_param) +{ + int ret; + struct most_aim **aim_ptr; + + if (!c->aim0.ptr) + aim_ptr = &c->aim0.ptr; + else if (!c->aim1.ptr) + aim_ptr = &c->aim1.ptr; + else + return -ENOSPC; + + *aim_ptr = aim; + ret = aim->probe_channel(c->iface, c->channel_id, + &c->cfg, aim_param); + if (ret) { + *aim_ptr = NULL; + return ret; + } + + return 0; +} + /** * add_link_store - store() function for add_link attribute * @aim_obj: pointer to AIM object @@ -948,13 +695,13 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) * (1) would create the device node /dev/my_rxchannel * (2) would create the device node /dev/mdev1-ep81 */ -static ssize_t add_link_store(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, +static ssize_t add_link_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { struct most_c_obj *c; - struct most_aim **aim_ptr; + struct most_aim *aim = to_most_aim(dev); char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; @@ -979,20 +726,9 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj, if (IS_ERR(c)) return -ENODEV; - if (!c->aim0.ptr) - aim_ptr = &c->aim0.ptr; - else if (!c->aim1.ptr) - aim_ptr = &c->aim1.ptr; - else - return -ENOSPC; - - *aim_ptr = aim_obj->driver; - ret = aim_obj->driver->probe_channel(c->iface, c->channel_id, - &c->cfg, &c->kobj, mdev_devnod); - if (ret) { - *aim_ptr = NULL; + ret = link_channel_to_aim(c, aim, mdev_devnod); + if (ret) return ret; - } return len; } @@ -1007,12 +743,13 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj, * Example: * echo "mdev0:ep81" >remove_link */ -static ssize_t remove_link_store(struct most_aim_obj *aim_obj, - struct most_aim_attribute *attr, +static ssize_t remove_link_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { struct most_c_obj *c; + struct most_aim *aim = to_most_aim(dev); char buffer[STRING_SIZE]; char *mdev; char *mdev_ch; @@ -1028,94 +765,38 @@ static ssize_t remove_link_store(struct most_aim_obj *aim_obj, if (IS_ERR(c)) return -ENODEV; - if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) + if (aim->disconnect_channel(c->iface, c->channel_id)) return -EIO; - if (c->aim0.ptr == aim_obj->driver) + if (c->aim0.ptr == aim) c->aim0.ptr = NULL; - if (c->aim1.ptr == aim_obj->driver) + if (c->aim1.ptr == aim) c->aim1.ptr = NULL; return len; } -static struct most_aim_attribute most_aim_attrs[] = { - __ATTR_RO(links), - __ATTR_WO(add_link), - __ATTR_WO(remove_link), -}; +static DEVICE_ATTR_RO(links); +static DEVICE_ATTR_WO(add_link); +static DEVICE_ATTR_WO(remove_link); -static struct attribute *most_aim_def_attrs[] = { - &most_aim_attrs[0].attr, - &most_aim_attrs[1].attr, - &most_aim_attrs[2].attr, +static struct attribute *aim_attrs[] = { + DEV_ATTR(links), + DEV_ATTR(add_link), + DEV_ATTR(remove_link), NULL, }; -static struct kobj_type most_aim_ktype = { - .sysfs_ops = &most_aim_sysfs_ops, - .release = most_aim_release, - .default_attrs = most_aim_def_attrs, +static struct attribute_group aim_attr_group = { + .attrs = aim_attrs, }; -static struct kset *most_aim_kset; - -/** - * create_most_aim_obj - creates an AIM object - * @name: name of the AIM - * - * This creates an AIM object assigns the proper kset and registers - * it with sysfs. - * Returns a pointer to the object or NULL if something went wrong. - */ -static struct most_aim_obj *create_most_aim_obj(const char *name) -{ - struct most_aim_obj *most_aim; - int retval; - - most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL); - if (!most_aim) - return NULL; - most_aim->kobj.kset = most_aim_kset; - retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype, - NULL, "%s", name); - if (retval) { - kobject_put(&most_aim->kobj); - return NULL; - } - kobject_uevent(&most_aim->kobj, KOBJ_ADD); - return most_aim; -} - -/** - * destroy_most_aim_obj - AIM release function - * @p: pointer to AIM object - * - * This decrements the reference counter of the AIM object. If the - * reference count turns zero, its release function will be called. - */ -static void destroy_most_aim_obj(struct most_aim_obj *p) -{ - kobject_put(&p->kobj); -} - +static const struct attribute_group *aim_attr_groups[] = { + &aim_attr_group, + NULL, +}; /* ___ ___ * ___C O R E___ */ -/** - * Instantiation of the MOST bus - */ -static struct bus_type most_bus = { - .name = "most", -}; - -/** - * Instantiation of the core driver - */ -static struct device_driver mostcore = { - .name = "mostcore", - .bus = &most_bus, -}; - static inline void trash_mbo(struct mbo *mbo) { unsigned long flags; @@ -1334,37 +1015,10 @@ static void most_write_completion(struct mbo *mbo) arm_mbo(mbo); } -/** - * get_channel_by_iface - get pointer to channel object - * @iface: pointer to interface instance - * @id: channel ID - * - * This retrieves a pointer to a channel of the given interface and channel ID. - */ -static struct -most_c_obj *get_channel_by_iface(struct most_interface *iface, int id) -{ - struct most_inst_obj *i; - - if (unlikely(!iface)) { - pr_err("Bad interface\n"); - return NULL; - } - if (unlikely((id < 0) || (id >= iface->num_channels))) { - pr_err("Channel index (%d) out of range\n", id); - return NULL; - } - i = iface->priv; - if (unlikely(!i)) { - pr_err("interface is not registered\n"); - return NULL; - } - return i->channel[id]; -} - int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) { - struct most_c_obj *c = get_channel_by_iface(iface, id); + struct most_inst_obj *inst = iface->priv; + struct most_c_obj *c = inst->channel[id]; unsigned long flags; int empty; @@ -1396,10 +1050,11 @@ struct mbo *most_get_mbo(struct most_interface *iface, int id, { struct mbo *mbo; struct most_c_obj *c; + struct most_inst_obj *inst = iface->priv; unsigned long flags; int *num_buffers_ptr; - c = get_channel_by_iface(iface, id); + c = inst->channel[id]; if (unlikely(!c)) return NULL; @@ -1501,7 +1156,8 @@ int most_start_channel(struct most_interface *iface, int id, { int num_buffer; int ret; - struct most_c_obj *c = get_channel_by_iface(iface, id); + struct most_inst_obj *inst = iface->priv; + struct most_c_obj *c = inst->channel[id]; if (unlikely(!c)) return -EINVAL; @@ -1569,13 +1225,15 @@ int most_start_channel(struct most_interface *iface, int id, int most_stop_channel(struct most_interface *iface, int id, struct most_aim *aim) { + struct most_inst_obj *inst; struct most_c_obj *c; if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) { pr_err("Bad interface or index out of range\n"); return -EINVAL; } - c = get_channel_by_iface(iface, id); + inst = iface->priv; + c = inst->channel[id]; if (unlikely(!c)) return -EINVAL; @@ -1621,28 +1279,34 @@ int most_stop_channel(struct most_interface *iface, int id, } EXPORT_SYMBOL_GPL(most_stop_channel); +void release_aim(struct device *dev) +{ + pr_info("releasing aim %s\n", dev_name(dev)); +} + /** * most_register_aim - registers an AIM (driver) with the core * @aim: instance of AIM to be registered */ int most_register_aim(struct most_aim *aim) { - struct most_aim_obj *aim_obj; + int ret; if (!aim) { pr_err("Bad driver\n"); return -EINVAL; } - aim_obj = create_most_aim_obj(aim->name); - if (!aim_obj) { - pr_info("failed to alloc driver object\n"); - return -ENOMEM; + aim->dev.init_name = aim->name; + aim->dev.bus = &most_bus_type; + aim->dev.parent = &core_dev; + aim->dev.groups = aim_attr_groups; + aim->dev.release = release_aim; + ret = device_register(&aim->dev); + if (ret) { + pr_err("registering device %s failed\n", aim->name); + return ret; } - aim_obj->driver = aim; - aim->context = aim_obj; - pr_info("registered new application interfacing module %s\n", - aim->name); - list_add_tail(&aim_obj->list, &aim_list); + pr_info("registered new application interfacing module %s\n", aim->name); return 0; } EXPORT_SYMBOL_GPL(most_register_aim); @@ -1653,7 +1317,6 @@ int most_register_aim(struct most_aim *aim) */ int most_deregister_aim(struct most_aim *aim) { - struct most_aim_obj *aim_obj; struct most_c_obj *c, *tmp; struct most_inst_obj *i, *i_tmp; @@ -1662,11 +1325,6 @@ int most_deregister_aim(struct most_aim *aim) return -EINVAL; } - aim_obj = aim->context; - if (!aim_obj) { - pr_info("driver not registered.\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->aim0.ptr == aim || c->aim1.ptr == aim) @@ -1678,13 +1336,22 @@ int most_deregister_aim(struct most_aim *aim) c->aim1.ptr = NULL; } } - list_del(&aim_obj->list); - destroy_most_aim_obj(aim_obj); + device_unregister(&aim->dev); pr_info("deregistering application interfacing module %s\n", aim->name); return 0; } EXPORT_SYMBOL_GPL(most_deregister_aim); +static void release_interface(struct device *dev) +{ + pr_info("releasing interface dev %s...\n", dev_name(dev)); +} + +static void release_channel(struct device *dev) +{ + pr_info("releasing channel dev %s...\n", dev_name(dev)); +} + /** * most_register_interface - registers an interface with core * @iface: pointer to the instance of the interface description. @@ -1692,7 +1359,7 @@ int most_deregister_aim(struct most_aim *aim) * Allocates and initializes a new interface instance and all of its channels. * Returns a pointer to kobject or an error pointer. */ -struct kobject *most_register_interface(struct most_interface *iface) +int most_register_interface(struct most_interface *iface) { unsigned int i; int id; @@ -1704,21 +1371,20 @@ struct kobject *most_register_interface(struct most_interface *iface) if (!iface || !iface->enqueue || !iface->configure || !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) { pr_err("Bad interface or channel overflow\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); if (id < 0) { pr_info("Failed to alloc mdev ID\n"); - return ERR_PTR(id); + return id; } - snprintf(name, STRING_SIZE, "mdev%d", id); - inst = create_most_inst_obj(name); + inst = kzalloc(sizeof(*inst), GFP_KERNEL); if (!inst) { pr_info("Failed to allocate interface instance\n"); ida_simple_remove(&mdev_id, id); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } iface->priv = inst; @@ -1726,6 +1392,18 @@ struct kobject *most_register_interface(struct most_interface *iface) 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; + iface->dev.bus = &most_bus_type; + iface->dev.parent = &core_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); + ida_simple_remove(&mdev_id, id); + return -ENOMEM; + } for (i = 0; i < iface->num_channels; i++) { const char *name_suffix = iface->channel_vector[i].name_suffix; @@ -1736,9 +1414,18 @@ struct kobject *most_register_interface(struct most_interface *iface) snprintf(channel_name, STRING_SIZE, "%s", name_suffix); /* this increments the reference count of this instance */ - c = create_most_c_obj(channel_name, &inst->kobj); + c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) goto free_instance; + //snprintf(c->dev.init_name, STRING_SIZE, channel_name); + c->dev.init_name = channel_name; + c->dev.parent = &iface->dev; + c->dev.groups = channel_attr_groups; + c->dev.release = release_channel; + if (device_register(&c->dev)) { + pr_err("registering c->dev failed\n"); + goto free_instance; + } inst->channel[i] = c; c->is_starving = 0; c->iface = iface; @@ -1764,15 +1451,14 @@ struct kobject *most_register_interface(struct most_interface *iface) list_add_tail(&c->list, &inst->channel_list); } pr_info("registered new MOST device mdev%d (%s)\n", - inst->dev_id, iface->description); - return &inst->kobj; + id, iface->description); + return 0; free_instance: pr_info("Failed allocate channel(s)\n"); - list_del(&inst->list); + device_unregister(&iface->dev); ida_simple_remove(&mdev_id, id); - destroy_most_inst_obj(inst); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } EXPORT_SYMBOL_GPL(most_register_interface); @@ -1785,17 +1471,14 @@ struct kobject *most_register_interface(struct most_interface *iface) */ void most_deregister_interface(struct most_interface *iface) { - struct most_inst_obj *i = iface->priv; + int i; struct most_c_obj *c; + struct most_inst_obj *inst; - if (unlikely(!i)) { - pr_info("Bad Interface\n"); - return; - } - pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, - iface->description); - - list_for_each_entry(c, &i->channel_list, list) { + 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]; if (c->aim0.ptr) c->aim0.ptr->disconnect_channel(c->iface, c->channel_id); @@ -1804,11 +1487,14 @@ void most_deregister_interface(struct most_interface *iface) c->channel_id); c->aim0.ptr = NULL; c->aim1.ptr = NULL; + list_del(&c->list); + device_unregister(&c->dev); + kfree(c); } - ida_simple_remove(&mdev_id, i->dev_id); - list_del(&i->list); - destroy_most_inst_obj(i); + ida_simple_remove(&mdev_id, inst->dev_id); + kfree(inst); + device_unregister(&iface->dev); } EXPORT_SYMBOL_GPL(most_deregister_interface); @@ -1824,7 +1510,8 @@ void most_deregister_interface(struct most_interface *iface) */ void most_stop_enqueue(struct most_interface *iface, int id) { - struct most_c_obj *c = get_channel_by_iface(iface, id); + struct most_inst_obj *inst = iface->priv; + struct most_c_obj *c = inst->channel[id]; if (!c) return; @@ -1845,7 +1532,8 @@ void most_stop_enqueue(struct most_interface *iface, int id) */ void most_resume_enqueue(struct most_interface *iface, int id) { - struct most_c_obj *c = get_channel_by_iface(iface, id); + struct most_inst_obj *inst = iface->priv; + struct most_c_obj *c = inst->channel[id]; if (!c) return; @@ -1858,6 +1546,11 @@ void most_resume_enqueue(struct most_interface *iface, int id) } EXPORT_SYMBOL_GPL(most_resume_enqueue); +static void release_most_sub(struct device *dev) +{ + pr_info("releasing most_subsystem\n"); +} + static int __init most_init(void) { int err; @@ -1867,12 +1560,11 @@ static int __init most_init(void) INIT_LIST_HEAD(&aim_list); ida_init(&mdev_id); - err = bus_register(&most_bus); + err = bus_register(&most_bus_type); if (err) { pr_info("Cannot register most bus\n"); return err; } - most_class = class_create(THIS_MODULE, "most"); if (IS_ERR(most_class)) { pr_info("No udev support.\n"); @@ -1885,60 +1577,30 @@ static int __init most_init(void) pr_info("Cannot register core driver\n"); goto exit_class; } - - core_dev = device_create(most_class, NULL, 0, NULL, "mostcore"); - if (IS_ERR(core_dev)) { - err = PTR_ERR(core_dev); - goto exit_driver; - } - - most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj); - if (!most_aim_kset) { + core_dev.init_name = "most_bus"; + core_dev.release = release_most_sub; + if (device_register(&core_dev)) { err = -ENOMEM; - goto exit_class_container; - } - - most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj); - if (!most_inst_kset) { - err = -ENOMEM; - goto exit_driver_kset; + goto exit_driver; } - return 0; -exit_driver_kset: - kset_unregister(most_aim_kset); -exit_class_container: - device_destroy(most_class, 0); exit_driver: driver_unregister(&mostcore); exit_class: class_destroy(most_class); exit_bus: - bus_unregister(&most_bus); + bus_unregister(&most_bus_type); return err; } static void __exit most_exit(void) { - struct most_inst_obj *i, *i_tmp; - struct most_aim_obj *d, *d_tmp; - pr_info("exit core module\n"); - list_for_each_entry_safe(d, d_tmp, &aim_list, list) { - destroy_most_aim_obj(d); - } - - list_for_each_entry_safe(i, i_tmp, &instance_list, list) { - list_del(&i->list); - destroy_most_inst_obj(i); - } - kset_unregister(most_inst_kset); - kset_unregister(most_aim_kset); - device_destroy(most_class, 0); + device_unregister(&core_dev); driver_unregister(&mostcore); class_destroy(most_class); - bus_unregister(&most_bus); + bus_unregister(&most_bus_type); ida_destroy(&mdev_id); } diff --git a/drivers/staging/most/core.h b/drivers/staging/most/core.h index a6e618c..588aadb 100644 --- a/drivers/staging/most/core.h +++ b/drivers/staging/most/core.h @@ -238,6 +238,7 @@ struct mbo { * @priv Private field used by mostcore to store context information. */ struct most_interface { + struct device dev; struct module *mod; enum most_interface_type interface; const char *description; @@ -255,6 +256,7 @@ struct most_interface { void *priv; }; +#define to_most_interface(d) container_of(d, struct most_interface, dev) /** * struct most_aim - identifies MOST device driver to mostcore * @name: Driver name @@ -265,10 +267,10 @@ struct most_interface { * @context: context pointer to be used by mostcore */ struct most_aim { + struct device dev; const char *name; int (*probe_channel)(struct most_interface *iface, int channel_idx, - struct most_channel_config *cfg, - struct kobject *parent, char *name); + struct most_channel_config *cfg, char *name); int (*disconnect_channel)(struct most_interface *iface, int channel_idx); int (*rx_completion)(struct mbo *mbo); @@ -276,6 +278,7 @@ struct most_aim { void *context; }; +#define to_most_aim(d) container_of(d, struct most_aim, dev) /** * most_register_interface - Registers instance of the interface. * @iface: Pointer to the interface instance description. @@ -285,7 +288,7 @@ struct most_aim { * Note: HDM has to ensure that any reference held on the kobj is * released before deregistering the interface. */ -struct kobject *most_register_interface(struct most_interface *iface); +int most_register_interface(struct most_interface *iface); /** * Deregisters instance of the interface. diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c index cc8563f..309ef13 100644 --- a/drivers/staging/most/dim2/dim2.c +++ b/drivers/staging/most/dim2/dim2.c @@ -93,6 +93,7 @@ struct hdm_channel { * @atx_idx: index of async tx channel */ struct dim2_hdm { + struct device dev; struct hdm_channel hch[DMA_CHANNELS]; struct most_channel_capability capabilities[DMA_CHANNELS]; struct most_interface most_iface; @@ -744,7 +745,6 @@ static int dim2_probe(struct platform_device *pdev) struct dim2_hdm *dev; struct resource *res; int ret, i; - struct kobject *kobj; int irq; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); @@ -832,18 +832,20 @@ static int dim2_probe(struct platform_device *pdev) dev->most_iface.enqueue = enqueue; dev->most_iface.poison_channel = poison_channel; dev->most_iface.request_netinfo = request_netinfo; + dev->dev.init_name = "dim2_state"; + dev->dev.parent = &dev->most_iface.dev; - kobj = most_register_interface(&dev->most_iface); - if (IS_ERR(kobj)) { - ret = PTR_ERR(kobj); + ret = most_register_interface(&dev->most_iface); + if (ret) { dev_err(&pdev->dev, "failed to register MOST interface\n"); goto err_stop_thread; } - ret = dim2_sysfs_probe(&dev->bus, kobj); - if (ret) + ret = dim2_sysfs_probe(&dev->dev); + if (ret) { + dev_err(&pdev->dev, "failed to create sysfs attribute\n"); goto err_unreg_iface; - + } ret = startup_dim(pdev); if (ret) { dev_err(&pdev->dev, "failed to initialize DIM2\n"); @@ -853,7 +855,7 @@ static int dim2_probe(struct platform_device *pdev) return 0; err_destroy_bus: - dim2_sysfs_destroy(&dev->bus); + dim2_sysfs_destroy(&dev->dev); err_unreg_iface: most_deregister_interface(&dev->most_iface); err_stop_thread: @@ -881,7 +883,7 @@ static int dim2_remove(struct platform_device *pdev) if (pdata && pdata->destroy) pdata->destroy(pdata); - dim2_sysfs_destroy(&dev->bus); + dim2_sysfs_destroy(&dev->dev); most_deregister_interface(&dev->most_iface); kthread_stop(dev->netinfo_task); diff --git a/drivers/staging/most/dim2/sysfs.c b/drivers/staging/most/dim2/sysfs.c index 1331cf0..5ab0c02 100644 --- a/drivers/staging/most/dim2/sysfs.c +++ b/drivers/staging/most/dim2/sysfs.c @@ -17,99 +17,39 @@ #include <linux/kernel.h> #include "sysfs.h" +#include <linux/device.h> -struct bus_attr { - struct attribute attr; - ssize_t (*show)(struct medialb_bus *bus, char *buf); - ssize_t (*store)(struct medialb_bus *bus, const char *buf, - size_t count); -}; - -static ssize_t state_show(struct medialb_bus *bus, char *buf) +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) { bool state = dim2_sysfs_get_state_cb(); return sprintf(buf, "%s\n", state ? "locked" : ""); } -static struct bus_attr state_attr = __ATTR_RO(state); +DEVICE_ATTR_RO(state); -static struct attribute *bus_default_attrs[] = { - &state_attr.attr, +static struct attribute *dev_attrs[] = { + &dev_attr_state.attr, NULL, }; -static const struct attribute_group bus_attr_group = { - .attrs = bus_default_attrs, +static struct attribute_group dev_attr_group = { + .attrs = dev_attrs, }; -static void bus_kobj_release(struct kobject *kobj) -{ -} - -static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->show) - return -EIO; - - return xattr->show(bus, buf); -} - -static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - struct medialb_bus *bus = - container_of(kobj, struct medialb_bus, kobj_group); - struct bus_attr *xattr = container_of(attr, struct bus_attr, attr); - - if (!xattr->store) - return -EIO; - - return xattr->store(bus, buf, count); -} - -static struct sysfs_ops const bus_kobj_sysfs_ops = { - .show = bus_kobj_attr_show, - .store = bus_kobj_attr_store, -}; - -static struct kobj_type bus_ktype = { - .release = bus_kobj_release, - .sysfs_ops = &bus_kobj_sysfs_ops, +static const struct attribute_group *dev_attr_groups[] = { + &dev_attr_group, + NULL, }; -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj) +int dim2_sysfs_probe(struct device *dev) { - int err; - - kobject_init(&bus->kobj_group, &bus_ktype); - err = kobject_add(&bus->kobj_group, parent_kobj, "bus"); - if (err) { - pr_err("kobject_add() failed: %d\n", err); - goto err_kobject_add; - } - - err = sysfs_create_group(&bus->kobj_group, &bus_attr_group); - if (err) { - pr_err("sysfs_create_group() failed: %d\n", err); - goto err_create_group; - } - - return 0; - -err_create_group: - kobject_put(&bus->kobj_group); - -err_kobject_add: - return err; + dev->groups = dev_attr_groups; + return device_register(dev); } -void dim2_sysfs_destroy(struct medialb_bus *bus) +void dim2_sysfs_destroy(struct device *dev) { - kobject_put(&bus->kobj_group); + device_unregister(dev); } diff --git a/drivers/staging/most/dim2/sysfs.h b/drivers/staging/most/dim2/sysfs.h index 236de47..070a70c 100644 --- a/drivers/staging/most/dim2/sysfs.h +++ b/drivers/staging/most/dim2/sysfs.h @@ -22,10 +22,10 @@ struct medialb_bus { struct kobject kobj_group; }; -struct dim2_hdm; +struct device; -int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj); -void dim2_sysfs_destroy(struct medialb_bus *bus); +int dim2_sysfs_probe(struct device *dev); +void dim2_sysfs_destroy(struct device *dev); /* * callback, diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c index 0a3e858..587ac86 100644 --- a/drivers/staging/most/i2c/i2c.c +++ b/drivers/staging/most/i2c/i2c.c @@ -309,7 +309,6 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct hdm_i2c *dev; int ret, i; - struct kobject *kobj; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) @@ -347,11 +346,11 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) dev->client = client; i2c_set_clientdata(client, dev); - kobj = most_register_interface(&dev->most_iface); - if (IS_ERR(kobj)) { + ret = most_register_interface(&dev->most_iface); + if (ret) { pr_err("Failed to register i2c as a MOST interface\n"); kfree(dev); - return PTR_ERR(kobj); + return ret; } dev->polling_mode = polling_req || client->irq <= 0; diff --git a/drivers/staging/most/net/net.c b/drivers/staging/most/net/net.c index d43aad3..194fe63 100644 --- a/drivers/staging/most/net/net.c +++ b/drivers/staging/most/net/net.c @@ -298,7 +298,7 @@ static struct net_dev_context *get_net_dev_hold(struct most_interface *iface) static int aim_probe_channel(struct most_interface *iface, int channel_idx, struct most_channel_config *ccfg, - struct kobject *parent, char *name) + char *name) { struct net_dev_context *nd; struct net_dev_channel *ch; @@ -502,7 +502,7 @@ static int aim_rx_data(struct mbo *mbo) } static struct most_aim aim = { - .name = "networking", + .name = "aim_networking", .probe_channel = aim_probe_channel, .disconnect_channel = aim_disconnect_channel, .tx_completion = aim_resume_tx_channel, diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 72603ae..4c3397a 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -24,7 +24,7 @@ #include <linux/kthread.h> #include <most/core.h> -#define DRIVER_NAME "sound" +#define DRIVER_NAME "aim_sound" static struct list_head dev_list; static struct most_aim audio_aim; @@ -545,7 +545,6 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw, * @iface: pointer to interface instance * @channel_id: channel index/ID * @cfg: pointer to actual channel configuration - * @parent: pointer to kobject (needed for sysfs hook-up) * @arg_list: string that provides the name of the device to be created in /dev * plus the desired audio resolution * @@ -555,7 +554,7 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw, */ static int audio_probe_channel(struct most_interface *iface, int channel_id, struct most_channel_config *cfg, - struct kobject *parent, char *arg_list) + char *arg_list) { struct channel *channel; struct snd_card *card; diff --git a/drivers/staging/most/usb/usb.c b/drivers/staging/most/usb/usb.c index 2e4f237..9e2a270 100644 --- a/drivers/staging/most/usb/usb.c +++ b/drivers/staging/most/usb/usb.c @@ -70,12 +70,12 @@ * @reg_addr: register address for arbitrary DCI access */ struct most_dci_obj { - struct kobject kobj; + struct device dev; struct usb_device *usb_device; u16 reg_addr; }; -#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) +#define to_dci_obj(p) container_of(p, struct most_dci_obj, dev) struct most_dev; @@ -90,7 +90,6 @@ struct clear_hold_work { /** * struct most_dev - holds all usb interface specific stuff - * @parent: parent object in sysfs * @usb_device: pointer to usb device * @iface: hardware interface * @cap: channel capabilities @@ -108,7 +107,6 @@ struct clear_hold_work { * @poll_work_obj: work for polling link status */ struct most_dev { - struct kobject *parent; struct usb_device *usb_device; struct most_interface iface; struct most_channel_capability *cap; @@ -840,94 +838,6 @@ static void wq_clear_halt(struct work_struct *wq_obj) { } /* Terminating entry */ }; -#define MOST_DCI_RO_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0444, show_value, NULL) - -#define MOST_DCI_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0644, show_value, store_value) - -#define MOST_DCI_WO_ATTR(_name) \ - struct most_dci_attribute most_dci_attr_##_name = \ - __ATTR(_name, 0200, NULL, store_value) - -/** - * struct most_dci_attribute - to access the attributes of a dci object - * @attr: attributes of a dci object - * @show: pointer to the show function - * @store: pointer to the store function - */ -struct most_dci_attribute { - struct attribute attr; - ssize_t (*show)(struct most_dci_obj *d, - struct most_dci_attribute *attr, - char *buf); - ssize_t (*store)(struct most_dci_obj *d, - struct most_dci_attribute *attr, - const char *buf, - size_t count); -}; - -#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr) - -/** - * dci_attr_show - show function for dci object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - */ -static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr, - char *buf) -{ - struct most_dci_attribute *dci_attr = to_dci_attr(attr); - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - if (!dci_attr->show) - return -EIO; - - return dci_attr->show(dci_obj, dci_attr, buf); -} - -/** - * dci_attr_store - store function for dci object - * @kobj: pointer to kobject - * @attr: pointer to attribute struct - * @buf: buffer - * @len: length of buffer - */ -static ssize_t dci_attr_store(struct kobject *kobj, - struct attribute *attr, - const char *buf, - size_t len) -{ - struct most_dci_attribute *dci_attr = to_dci_attr(attr); - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - if (!dci_attr->store) - return -EIO; - - return dci_attr->store(dci_obj, dci_attr, buf, len); -} - -static const struct sysfs_ops most_dci_sysfs_ops = { - .show = dci_attr_show, - .store = dci_attr_store, -}; - -/** - * most_dci_release - release function for dci object - * @kobj: pointer to kobject - * - * This frees the memory allocated for the dci object - */ -static void most_dci_release(struct kobject *kobj) -{ - struct most_dci_obj *dci_obj = to_dci_obj(kobj); - - kfree(dci_obj); -} - struct regs { const char *name; u16 reg; @@ -968,10 +878,11 @@ static int get_stat_reg_addr(const struct regs *regs, int size, #define get_static_reg_addr(regs, name, reg_addr) \ get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr) -static ssize_t show_value(struct most_dci_obj *dci_obj, - struct most_dci_attribute *attr, char *buf) +static ssize_t value_show(struct device *dev, struct device_attribute *attr, + char *buf) { const char *name = attr->attr.name; + struct most_dci_obj *dci_obj = to_dci_obj(dev); u16 val; u16 reg_addr; int err; @@ -992,13 +903,13 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, return snprintf(buf, PAGE_SIZE, "%04x\n", val); } -static ssize_t store_value(struct most_dci_obj *dci_obj, - struct most_dci_attribute *attr, +static ssize_t value_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { u16 val; u16 reg_addr; const char *name = attr->attr.name; + struct most_dci_obj *dci_obj = to_dci_obj(dev); struct usb_device *usb_dev = dci_obj->usb_device; int err = kstrtou16(buf, 16, &val); @@ -1025,86 +936,49 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, return count; } -static MOST_DCI_RO_ATTR(ni_state); -static MOST_DCI_RO_ATTR(packet_bandwidth); -static MOST_DCI_RO_ATTR(node_address); -static MOST_DCI_RO_ATTR(node_position); -static MOST_DCI_WO_ATTR(sync_ep); -static MOST_DCI_ATTR(mep_filter); -static MOST_DCI_ATTR(mep_hash0); -static MOST_DCI_ATTR(mep_hash1); -static MOST_DCI_ATTR(mep_hash2); -static MOST_DCI_ATTR(mep_hash3); -static MOST_DCI_ATTR(mep_eui48_hi); -static MOST_DCI_ATTR(mep_eui48_mi); -static MOST_DCI_ATTR(mep_eui48_lo); -static MOST_DCI_ATTR(arb_address); -static MOST_DCI_ATTR(arb_value); - -/** - * most_dci_def_attrs - array of default attribute files of the dci object - */ -static struct attribute *most_dci_def_attrs[] = { - &most_dci_attr_ni_state.attr, - &most_dci_attr_packet_bandwidth.attr, - &most_dci_attr_node_address.attr, - &most_dci_attr_node_position.attr, - &most_dci_attr_sync_ep.attr, - &most_dci_attr_mep_filter.attr, - &most_dci_attr_mep_hash0.attr, - &most_dci_attr_mep_hash1.attr, - &most_dci_attr_mep_hash2.attr, - &most_dci_attr_mep_hash3.attr, - &most_dci_attr_mep_eui48_hi.attr, - &most_dci_attr_mep_eui48_mi.attr, - &most_dci_attr_mep_eui48_lo.attr, - &most_dci_attr_arb_address.attr, - &most_dci_attr_arb_value.attr, +DEVICE_ATTR(ni_state, 0444, value_show, NULL); +DEVICE_ATTR(packet_bandwidth, 0444, value_show, NULL); +DEVICE_ATTR(node_address, 0444, value_show, NULL); +DEVICE_ATTR(node_position, 0444, value_show, NULL); +DEVICE_ATTR(sync_ep, 0200, NULL, value_store); +DEVICE_ATTR(mep_filter, 0644, value_show, value_store); +DEVICE_ATTR(mep_hash0, 0644, value_show, value_store); +DEVICE_ATTR(mep_hash1, 0644, value_show, value_store); +DEVICE_ATTR(mep_hash2, 0644, value_show, value_store); +DEVICE_ATTR(mep_hash3, 0644, value_show, value_store); +DEVICE_ATTR(mep_eui48_hi, 0644, value_show, value_store); +DEVICE_ATTR(mep_eui48_mi, 0644, value_show, value_store); +DEVICE_ATTR(mep_eui48_lo, 0644, value_show, value_store); +DEVICE_ATTR(arb_address, 0644, value_show, value_store); +DEVICE_ATTR(arb_value, 0644, value_show, value_store); + +static struct attribute *dci_attrs[] = { + &dev_attr_ni_state.attr, + &dev_attr_packet_bandwidth.attr, + &dev_attr_node_address.attr, + &dev_attr_node_position.attr, + &dev_attr_sync_ep.attr, + &dev_attr_mep_filter.attr, + &dev_attr_mep_hash0.attr, + &dev_attr_mep_hash1.attr, + &dev_attr_mep_hash2.attr, + &dev_attr_mep_hash3.attr, + &dev_attr_mep_eui48_hi.attr, + &dev_attr_mep_eui48_mi.attr, + &dev_attr_mep_eui48_lo.attr, + &dev_attr_arb_address.attr, + &dev_attr_arb_value.attr, NULL, }; -/** - * DCI ktype - */ -static struct kobj_type most_dci_ktype = { - .sysfs_ops = &most_dci_sysfs_ops, - .release = most_dci_release, - .default_attrs = most_dci_def_attrs, +static struct attribute_group dci_attr_group = { + .attrs = dci_attrs, }; -/** - * create_most_dci_obj - allocates a dci object - * @parent: parent kobject - * - * This creates a dci object and registers it with sysfs. - * Returns a pointer to the object or NULL when something went wrong. - */ -static struct -most_dci_obj *create_most_dci_obj(struct kobject *parent) -{ - struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL); - int retval; - - if (!most_dci) - return NULL; - - retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent, - "dci"); - if (retval) { - kobject_put(&most_dci->kobj); - return NULL; - } - return most_dci; -} - -/** - * destroy_most_dci_obj - DCI object release function - * @p: pointer to dci object - */ -static void destroy_most_dci_obj(struct most_dci_obj *p) -{ - kobject_put(&p->kobj); -} +static const struct attribute_group *dci_attr_groups[] = { + &dci_attr_group, + NULL, +}; /** * hdm_probe - probe function of USB device driver @@ -1218,33 +1092,36 @@ static void destroy_most_dci_obj(struct most_dci_obj *p) usb_dev->config->desc.bConfigurationValue, usb_iface_desc->desc.bInterfaceNumber); - mdev->parent = most_register_interface(&mdev->iface); - if (IS_ERR(mdev->parent)) { - ret = PTR_ERR(mdev->parent); + ret = most_register_interface(&mdev->iface); + if (ret) goto exit_free4; - } mutex_lock(&mdev->io_mutex); if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 || le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 || le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) { - /* this increments the reference count of the instance - * object of the core - */ - mdev->dci = create_most_dci_obj(mdev->parent); + mdev->dci = kzalloc(sizeof(*mdev->dci), GFP_KERNEL); if (!mdev->dci) { mutex_unlock(&mdev->io_mutex); most_deregister_interface(&mdev->iface); ret = -ENOMEM; goto exit_free4; } - - kobject_uevent(&mdev->dci->kobj, KOBJ_ADD); + mdev->dci->dev.init_name = "dci"; + mdev->dci->dev.parent = &mdev->iface.dev; + mdev->dci->dev.groups = dci_attr_groups; + if (device_register(&mdev->dci->dev)) { + mutex_unlock(&mdev->io_mutex); + most_deregister_interface(&mdev->iface); + ret = -ENOMEM; + goto exit_free5; + } mdev->dci->usb_device = mdev->usb_device; } mutex_unlock(&mdev->io_mutex); return 0; - +exit_free5: + kfree(mdev->dci); exit_free4: kfree(mdev->busy_urbs); exit_free3: @@ -1284,7 +1161,8 @@ static void hdm_disconnect(struct usb_interface *interface) del_timer_sync(&mdev->link_stat_timer); cancel_work_sync(&mdev->poll_work_obj); - destroy_most_dci_obj(mdev->dci); + device_unregister(&mdev->dci->dev); + kfree(mdev->dci); most_deregister_interface(&mdev->iface); kfree(mdev->busy_urbs); diff --git a/drivers/staging/most/video/video.c b/drivers/staging/most/video/video.c index eed9046..5b704d9 100644 --- a/drivers/staging/most/video/video.c +++ b/drivers/staging/most/video/video.c @@ -487,7 +487,7 @@ static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) static int aim_probe_channel(struct most_interface *iface, int channel_idx, struct most_channel_config *ccfg, - struct kobject *parent, char *name) + char *name) { int ret; struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); @@ -570,7 +570,7 @@ static int aim_disconnect_channel(struct most_interface *iface, } static struct most_aim aim_info = { - .name = "v4l", + .name = "aim_v4l", .probe_channel = aim_probe_channel, .disconnect_channel = aim_disconnect_channel, .rx_completion = aim_rx_data, -- 1.9.1 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel