Commit 4d5f022f authored by Christian Gromm's avatar Christian Gromm Committed by Greg Kroah-Hartman

staging: most: remove proprietary kobjects

This patch removes the proprietary kobjects used by the driver modules and
replaces them with device structs. The patch is needed to have the driver
being integrated into the kernel's device model.
Signed-off-by: default avatarChristian Gromm <christian.gromm@microchip.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2c22cdfb
...@@ -412,7 +412,6 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) ...@@ -412,7 +412,6 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id)
* @iface: pointer to interface instance * @iface: pointer to interface instance
* @channel_id: channel index/ID * @channel_id: channel index/ID
* @cfg: pointer to actual channel configuration * @cfg: pointer to actual channel configuration
* @parent: pointer to kobject (needed for sysfs hook-up)
* @name: name of the device to be created * @name: name of the device to be created
* *
* This allocates achannel object and creates the device node in /dev * This allocates achannel object and creates the device node in /dev
...@@ -420,15 +419,14 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) ...@@ -420,15 +419,14 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id)
* Returns 0 on success or error code otherwise. * Returns 0 on success or error code otherwise.
*/ */
static int aim_probe(struct most_interface *iface, int channel_id, static int aim_probe(struct most_interface *iface, int channel_id,
struct most_channel_config *cfg, struct most_channel_config *cfg, char *name)
struct kobject *parent, char *name)
{ {
struct aim_channel *c; struct aim_channel *c;
unsigned long cl_flags; unsigned long cl_flags;
int retval; int retval;
int current_minor; int current_minor;
if ((!iface) || (!cfg) || (!parent) || (!name)) { if ((!iface) || (!cfg) || (!name)) {
pr_info("Probing AIM with bad arguments"); pr_info("Probing AIM with bad arguments");
return -EINVAL; return -EINVAL;
} }
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#define STRING_SIZE 80 #define STRING_SIZE 80
static struct class *most_class; static struct class *most_class;
static struct device *core_dev; static struct device core_dev;
static struct ida mdev_id; static struct ida mdev_id;
static int dummy_num_buffers; static int dummy_num_buffers;
...@@ -38,7 +38,7 @@ struct most_c_aim_obj { ...@@ -38,7 +38,7 @@ struct most_c_aim_obj {
}; };
struct most_c_obj { struct most_c_obj {
struct kobject kobj; struct device dev;
struct completion cleanup; struct completion cleanup;
atomic_t mbo_ref; atomic_t mbo_ref;
atomic_t mbo_nq_level; atomic_t mbo_nq_level;
...@@ -63,14 +63,13 @@ struct most_c_obj { ...@@ -63,14 +63,13 @@ struct most_c_obj {
wait_queue_head_t hdm_fifo_wq; 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 { struct most_inst_obj {
int dev_id; int dev_id;
struct most_interface *iface; struct most_interface *iface;
struct list_head channel_list; struct list_head channel_list;
struct most_c_obj *channel[MAX_CHANNELS]; struct most_c_obj *channel[MAX_CHANNELS];
struct kobject kobj;
struct list_head list; struct list_head list;
}; };
...@@ -85,8 +84,6 @@ static const struct { ...@@ -85,8 +84,6 @@ static const struct {
{ MOST_CH_ISOC, "isoc_avp\n"}, { MOST_CH_ISOC, "isoc_avp\n"},
}; };
#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
/** /**
* list_pop_mbo - retrieves the first MBO of the list and removes it * list_pop_mbo - retrieves the first MBO of the list and removes it
* @ptr: the list head to grab the MBO from. * @ptr: the list head to grab the MBO from.
...@@ -102,68 +99,6 @@ static const struct { ...@@ -102,68 +99,6 @@ static const struct {
* ___C H A N N E L___ * ___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 * most_free_mbo_coherent - free an MBO and its coherent buffer
* @mbo: buffer to be released * @mbo: buffer to be released
...@@ -235,21 +170,11 @@ static int flush_trash_fifo(struct most_c_obj *c) ...@@ -235,21 +170,11 @@ static int flush_trash_fifo(struct most_c_obj *c)
return 0; return 0;
} }
/** static ssize_t available_directions_show(struct device *dev,
* most_channel_release - release function of channel object struct device_attribute *attr,
* @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,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
unsigned int i = c->channel_id; unsigned int i = c->channel_id;
strcpy(buf, ""); strcpy(buf, "");
...@@ -261,10 +186,11 @@ static ssize_t available_directions_show(struct most_c_obj *c, ...@@ -261,10 +186,11 @@ static ssize_t available_directions_show(struct most_c_obj *c,
return strlen(buf); return strlen(buf);
} }
static ssize_t available_datatypes_show(struct most_c_obj *c, static ssize_t available_datatypes_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
unsigned int i = c->channel_id; unsigned int i = c->channel_id;
strcpy(buf, ""); strcpy(buf, "");
...@@ -280,65 +206,75 @@ static ssize_t available_datatypes_show(struct most_c_obj *c, ...@@ -280,65 +206,75 @@ static ssize_t available_datatypes_show(struct most_c_obj *c,
return strlen(buf); return strlen(buf);
} }
static ssize_t number_of_packet_buffers_show(struct most_c_obj *c, static ssize_t number_of_packet_buffers_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
unsigned int i = c->channel_id; unsigned int i = c->channel_id;
return snprintf(buf, PAGE_SIZE, "%d\n", return snprintf(buf, PAGE_SIZE, "%d\n",
c->iface->channel_vector[i].num_buffers_packet); c->iface->channel_vector[i].num_buffers_packet);
} }
static ssize_t number_of_stream_buffers_show(struct most_c_obj *c, static ssize_t number_of_stream_buffers_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
unsigned int i = c->channel_id; unsigned int i = c->channel_id;
return snprintf(buf, PAGE_SIZE, "%d\n", return snprintf(buf, PAGE_SIZE, "%d\n",
c->iface->channel_vector[i].num_buffers_streaming); c->iface->channel_vector[i].num_buffers_streaming);
} }
static ssize_t size_of_packet_buffer_show(struct most_c_obj *c, static ssize_t size_of_packet_buffer_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
unsigned int i = c->channel_id; unsigned int i = c->channel_id;
return snprintf(buf, PAGE_SIZE, "%d\n", return snprintf(buf, PAGE_SIZE, "%d\n",
c->iface->channel_vector[i].buffer_size_packet); c->iface->channel_vector[i].buffer_size_packet);
} }
static ssize_t size_of_stream_buffer_show(struct most_c_obj *c, static ssize_t size_of_stream_buffer_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
unsigned int i = c->channel_id; unsigned int i = c->channel_id;
return snprintf(buf, PAGE_SIZE, "%d\n", return snprintf(buf, PAGE_SIZE, "%d\n",
c->iface->channel_vector[i].buffer_size_streaming); c->iface->channel_vector[i].buffer_size_streaming);
} }
static ssize_t channel_starving_show(struct most_c_obj *c, static ssize_t channel_starving_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving); return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
} }
static ssize_t set_number_of_buffers_show(struct most_c_obj *c, static ssize_t set_number_of_buffers_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers); return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
} }
static ssize_t set_number_of_buffers_store(struct most_c_obj *c, static ssize_t set_number_of_buffers_store(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t count) size_t count)
{ {
struct most_c_obj *c = to_c_obj(dev);
int ret = kstrtou16(buf, 0, &c->cfg.num_buffers); int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
if (ret) if (ret)
...@@ -346,18 +282,21 @@ static ssize_t set_number_of_buffers_store(struct most_c_obj *c, ...@@ -346,18 +282,21 @@ static ssize_t set_number_of_buffers_store(struct most_c_obj *c,
return count; return count;
} }
static ssize_t set_buffer_size_show(struct most_c_obj *c, static ssize_t set_buffer_size_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size); return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
} }
static ssize_t set_buffer_size_store(struct most_c_obj *c, static ssize_t set_buffer_size_store(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t count) size_t count)
{ {
struct most_c_obj *c = to_c_obj(dev);
int ret = kstrtou16(buf, 0, &c->cfg.buffer_size); int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
if (ret) if (ret)
...@@ -365,10 +304,12 @@ static ssize_t set_buffer_size_store(struct most_c_obj *c, ...@@ -365,10 +304,12 @@ static ssize_t set_buffer_size_store(struct most_c_obj *c,
return count; return count;
} }
static ssize_t set_direction_show(struct most_c_obj *c, static ssize_t set_direction_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
if (c->cfg.direction & MOST_CH_TX) if (c->cfg.direction & MOST_CH_TX)
return snprintf(buf, PAGE_SIZE, "tx\n"); return snprintf(buf, PAGE_SIZE, "tx\n");
else if (c->cfg.direction & MOST_CH_RX) else if (c->cfg.direction & MOST_CH_RX)
...@@ -376,11 +317,13 @@ static ssize_t set_direction_show(struct most_c_obj *c, ...@@ -376,11 +317,13 @@ static ssize_t set_direction_show(struct most_c_obj *c,
return snprintf(buf, PAGE_SIZE, "unconfigured\n"); return snprintf(buf, PAGE_SIZE, "unconfigured\n");
} }
static ssize_t set_direction_store(struct most_c_obj *c, static ssize_t set_direction_store(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t count) size_t count)
{ {
struct most_c_obj *c = to_c_obj(dev);
if (!strcmp(buf, "dir_rx\n")) { if (!strcmp(buf, "dir_rx\n")) {
c->cfg.direction = MOST_CH_RX; c->cfg.direction = MOST_CH_RX;
} else if (!strcmp(buf, "rx\n")) { } else if (!strcmp(buf, "rx\n")) {
...@@ -396,11 +339,12 @@ static ssize_t set_direction_store(struct most_c_obj *c, ...@@ -396,11 +339,12 @@ static ssize_t set_direction_store(struct most_c_obj *c,
return count; return count;
} }
static ssize_t set_datatype_show(struct most_c_obj *c, static ssize_t set_datatype_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
int i; int i;
struct most_c_obj *c = to_c_obj(dev);
for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
...@@ -409,12 +353,13 @@ static ssize_t set_datatype_show(struct most_c_obj *c, ...@@ -409,12 +353,13 @@ static ssize_t set_datatype_show(struct most_c_obj *c,
return snprintf(buf, PAGE_SIZE, "unconfigured\n"); return snprintf(buf, PAGE_SIZE, "unconfigured\n");
} }
static ssize_t set_datatype_store(struct most_c_obj *c, static ssize_t set_datatype_store(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t count) size_t count)
{ {
int i; int i;
struct most_c_obj *c = to_c_obj(dev);
for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
if (!strcmp(buf, ch_data_type[i].name)) { if (!strcmp(buf, ch_data_type[i].name)) {
...@@ -430,18 +375,21 @@ static ssize_t set_datatype_store(struct most_c_obj *c, ...@@ -430,18 +375,21 @@ static ssize_t set_datatype_store(struct most_c_obj *c,
return count; return count;
} }
static ssize_t set_subbuffer_size_show(struct most_c_obj *c, static ssize_t set_subbuffer_size_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size); return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
} }
static ssize_t set_subbuffer_size_store(struct most_c_obj *c, static ssize_t set_subbuffer_size_store(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t count) size_t count)
{ {
struct most_c_obj *c = to_c_obj(dev);
int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size); int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
if (ret) if (ret)
...@@ -449,18 +397,21 @@ static ssize_t set_subbuffer_size_store(struct most_c_obj *c, ...@@ -449,18 +397,21 @@ static ssize_t set_subbuffer_size_store(struct most_c_obj *c,
return count; return count;
} }
static ssize_t set_packets_per_xact_show(struct most_c_obj *c, static ssize_t set_packets_per_xact_show(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct most_c_obj *c = to_c_obj(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact); 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, static ssize_t set_packets_per_xact_store(struct device *dev,
struct most_c_attr *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t count) size_t count)
{ {
struct most_c_obj *c = to_c_obj(dev);
int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact); int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
if (ret) if (ret)
...@@ -468,77 +419,47 @@ static ssize_t set_packets_per_xact_store(struct most_c_obj *c, ...@@ -468,77 +419,47 @@ static ssize_t set_packets_per_xact_store(struct most_c_obj *c,
return count; return count;
} }
static struct most_c_attr most_c_attrs[] = { #define DEV_ATTR(_name) (&dev_attr_##_name.attr)
__ATTR_RO(available_directions),
__ATTR_RO(available_datatypes), static DEVICE_ATTR_RO(available_directions);
__ATTR_RO(number_of_packet_buffers), static DEVICE_ATTR_RO(available_datatypes);
__ATTR_RO(number_of_stream_buffers), static DEVICE_ATTR_RO(number_of_packet_buffers);
__ATTR_RO(size_of_stream_buffer), static DEVICE_ATTR_RO(number_of_stream_buffers);
__ATTR_RO(size_of_packet_buffer), static DEVICE_ATTR_RO(size_of_stream_buffer);
__ATTR_RO(channel_starving), static DEVICE_ATTR_RO(size_of_packet_buffer);
__ATTR_RW(set_buffer_size), static DEVICE_ATTR_RO(channel_starving);
__ATTR_RW(set_number_of_buffers), static DEVICE_ATTR_RW(set_buffer_size);
__ATTR_RW(set_direction), static DEVICE_ATTR_RW(set_number_of_buffers);
__ATTR_RW(set_datatype), static DEVICE_ATTR_RW(set_direction);
__ATTR_RW(set_subbuffer_size), static DEVICE_ATTR_RW(set_datatype);
__ATTR_RW(set_packets_per_xact), static DEVICE_ATTR_RW(set_subbuffer_size);
}; static DEVICE_ATTR_RW(set_packets_per_xact);
/** static struct attribute *channel_attrs[] = {
* most_channel_def_attrs - array of default attributes of channel object DEV_ATTR(available_directions),
*/ DEV_ATTR(available_datatypes),
static struct attribute *most_channel_def_attrs[] = { DEV_ATTR(number_of_packet_buffers),
&most_c_attrs[0].attr, DEV_ATTR(number_of_stream_buffers),
&most_c_attrs[1].attr, DEV_ATTR(size_of_stream_buffer),
&most_c_attrs[2].attr, DEV_ATTR(size_of_packet_buffer),
&most_c_attrs[3].attr, DEV_ATTR(channel_starving),
&most_c_attrs[4].attr, DEV_ATTR(set_buffer_size),
&most_c_attrs[5].attr, DEV_ATTR(set_number_of_buffers),
&most_c_attrs[6].attr, DEV_ATTR(set_direction),
&most_c_attrs[7].attr, DEV_ATTR(set_datatype),
&most_c_attrs[8].attr, DEV_ATTR(set_subbuffer_size),
&most_c_attrs[9].attr, DEV_ATTR(set_packets_per_xact),
&most_c_attrs[10].attr,
&most_c_attrs[11].attr,
&most_c_attrs[12].attr,
NULL, NULL,
}; };
static struct kobj_type most_channel_ktype = { static struct attribute_group channel_attr_group = {
.sysfs_ops = &most_channel_sysfs_ops, .attrs = channel_attrs,
.release = most_channel_release,
.default_attrs = most_channel_def_attrs,
}; };
static struct kset *most_channel_kset; static const struct attribute_group *channel_attr_groups[] = {
&channel_attr_group,
/** NULL,
* 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;
}
/* ___ ___ /* ___ ___
* ___I N S T A N C E___ * ___I N S T A N C E___
...@@ -546,103 +467,22 @@ create_most_c_obj(const char *name, struct kobject *parent) ...@@ -546,103 +467,22 @@ create_most_c_obj(const char *name, struct kobject *parent)
static struct list_head instance_list; static struct list_head instance_list;
/** static ssize_t description_show(struct device *dev,
* struct most_inst_attribute - to access the attributes of instance object struct device_attribute *attr,
* @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,
char *buf) char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%s\n", struct most_interface *iface = to_most_interface(dev);
instance_obj->iface->description);
return snprintf(buf, PAGE_SIZE, "%s\n", iface->description);
} }
static ssize_t interface_show(struct most_inst_obj *instance_obj, static ssize_t interface_show(struct device *dev,
struct most_inst_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
switch (instance_obj->iface->interface) { struct most_interface *iface = to_most_interface(dev);
switch (iface->interface) {
case ITYPE_LOOPBACK: case ITYPE_LOOPBACK:
return snprintf(buf, PAGE_SIZE, "loopback\n"); return snprintf(buf, PAGE_SIZE, "loopback\n");
case ITYPE_I2C: case ITYPE_I2C:
...@@ -665,182 +505,42 @@ static ssize_t interface_show(struct most_inst_obj *instance_obj, ...@@ -665,182 +505,42 @@ static ssize_t interface_show(struct most_inst_obj *instance_obj,
return snprintf(buf, PAGE_SIZE, "unknown\n"); return snprintf(buf, PAGE_SIZE, "unknown\n");
} }
static struct most_inst_attribute most_inst_attr_description = static DEVICE_ATTR_RO(description);
__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[] = { static struct attribute *interface_attrs[] = {
&most_inst_attr_description.attr, DEV_ATTR(description),
&most_inst_attr_interface.attr, DEV_ATTR(interface),
NULL, NULL,
}; };
static struct kobj_type most_inst_ktype = { static struct attribute_group interface_attr_group = {
.sysfs_ops = &most_inst_sysfs_ops, .attrs = interface_attrs,
.release = most_inst_release,
.default_attrs = most_inst_def_attrs,
}; };
static struct kset *most_inst_kset; static const struct attribute_group *interface_attr_groups[] = {
&interface_attr_group,
/** NULL,
* 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;
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___ * ___A I M___
*/ */
struct most_aim_obj { static ssize_t links_show(struct device *dev, struct device_attribute *attr,
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,
char *buf) char *buf)
{ {
struct most_c_obj *c; struct most_c_obj *c;
struct most_inst_obj *i; struct most_inst_obj *i;
struct most_aim *aim = to_most_aim(dev);
int offs = 0; int offs = 0;
list_for_each_entry(i, &instance_list, list) { list_for_each_entry(i, &instance_list, list) {
list_for_each_entry(c, &i->channel_list, list) { list_for_each_entry(c, &i->channel_list, list) {
if (c->aim0.ptr == aim_obj->driver || if (c->aim0.ptr == aim || c->aim1.ptr == aim) {
c->aim1.ptr == aim_obj->driver) {
offs += snprintf(buf + offs, PAGE_SIZE - offs, offs += snprintf(buf + offs, PAGE_SIZE - offs,
"%s:%s\n", "%s:%s\n",
kobject_name(&i->kobj), dev_name(&i->iface->dev),
kobject_name(&c->kobj)); dev_name(&c->dev));
} }
} }
} }
...@@ -901,7 +601,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) ...@@ -901,7 +601,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
int found = 0; int found = 0;
list_for_each_entry_safe(i, i_tmp, &instance_list, list) { 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++; found++;
break; break;
} }
...@@ -910,7 +610,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) ...@@ -910,7 +610,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
return ERR_PTR(-EIO); return ERR_PTR(-EIO);
list_for_each_entry_safe(c, tmp, &i->channel_list, list) { 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++; found++;
break; break;
} }
...@@ -942,13 +642,14 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch) ...@@ -942,13 +642,14 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
* (1) would create the device node /dev/my_rxchannel * (1) would create the device node /dev/my_rxchannel
* (2) would create the device node /dev/mdev1-ep81 * (2) would create the device node /dev/mdev1-ep81
*/ */
static ssize_t add_link_store(struct most_aim_obj *aim_obj, static ssize_t add_link_store(struct device *dev,
struct most_aim_attribute *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t len) size_t len)
{ {
struct most_c_obj *c; struct most_c_obj *c;
struct most_aim **aim_ptr; struct most_aim **aim_ptr;
struct most_aim *aim = to_most_aim(dev);
char buffer[STRING_SIZE]; char buffer[STRING_SIZE];
char *mdev; char *mdev;
char *mdev_ch; char *mdev_ch;
...@@ -980,9 +681,8 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj, ...@@ -980,9 +681,8 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj,
else else
return -ENOSPC; return -ENOSPC;
*aim_ptr = aim_obj->driver; *aim_ptr = aim;
ret = aim_obj->driver->probe_channel(c->iface, c->channel_id, ret = aim->probe_channel(c->iface, c->channel_id, &c->cfg, mdev_devnod);
&c->cfg, &c->kobj, mdev_devnod);
if (ret) { if (ret) {
*aim_ptr = NULL; *aim_ptr = NULL;
return ret; return ret;
...@@ -1001,12 +701,13 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj, ...@@ -1001,12 +701,13 @@ static ssize_t add_link_store(struct most_aim_obj *aim_obj,
* Example: * Example:
* echo "mdev0:ep81" >remove_link * echo "mdev0:ep81" >remove_link
*/ */
static ssize_t remove_link_store(struct most_aim_obj *aim_obj, static ssize_t remove_link_store(struct device *dev,
struct most_aim_attribute *attr, struct device_attribute *attr,
const char *buf, const char *buf,
size_t len) size_t len)
{ {
struct most_c_obj *c; struct most_c_obj *c;
struct most_aim *aim = to_most_aim(dev);
char buffer[STRING_SIZE]; char buffer[STRING_SIZE];
char *mdev; char *mdev;
char *mdev_ch; char *mdev_ch;
...@@ -1022,74 +723,34 @@ static ssize_t remove_link_store(struct most_aim_obj *aim_obj, ...@@ -1022,74 +723,34 @@ static ssize_t remove_link_store(struct most_aim_obj *aim_obj,
if (IS_ERR(c)) if (IS_ERR(c))
return -ENODEV; return -ENODEV;
if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) if (aim->disconnect_channel(c->iface, c->channel_id))
return -EIO; return -EIO;
if (c->aim0.ptr == aim_obj->driver) if (c->aim0.ptr == aim)
c->aim0.ptr = NULL; c->aim0.ptr = NULL;
if (c->aim1.ptr == aim_obj->driver) if (c->aim1.ptr == aim)
c->aim1.ptr = NULL; c->aim1.ptr = NULL;
return len; return len;
} }
static struct most_aim_attribute most_aim_attrs[] = { static DEVICE_ATTR_RO(links);
__ATTR_RO(links), static DEVICE_ATTR_WO(add_link);
__ATTR_WO(add_link), static DEVICE_ATTR_WO(remove_link);
__ATTR_WO(remove_link),
};
static struct attribute *most_aim_def_attrs[] = { static struct attribute *aim_attrs[] = {
&most_aim_attrs[0].attr, DEV_ATTR(links),
&most_aim_attrs[1].attr, DEV_ATTR(add_link),
&most_aim_attrs[2].attr, DEV_ATTR(remove_link),
NULL, NULL,
}; };
static struct kobj_type most_aim_ktype = { static struct attribute_group aim_attr_group = {
.sysfs_ops = &most_aim_sysfs_ops, .attrs = aim_attrs,
.release = most_aim_release,
.default_attrs = most_aim_def_attrs,
}; };
static struct kset *most_aim_kset; static const struct attribute_group *aim_attr_groups[] = {
&aim_attr_group,
/** NULL,
* 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);
}
/* ___ ___ /* ___ ___
* ___C O R E___ * ___C O R E___
...@@ -1615,28 +1276,35 @@ int most_stop_channel(struct most_interface *iface, int id, ...@@ -1615,28 +1276,35 @@ int most_stop_channel(struct most_interface *iface, int id,
} }
EXPORT_SYMBOL_GPL(most_stop_channel); 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 * most_register_aim - registers an AIM (driver) with the core
* @aim: instance of AIM to be registered * @aim: instance of AIM to be registered
*/ */
int most_register_aim(struct most_aim *aim) int most_register_aim(struct most_aim *aim)
{ {
struct most_aim_obj *aim_obj; int ret;
if (!aim) { if (!aim) {
pr_err("Bad driver\n"); pr_err("Bad driver\n");
return -EINVAL; return -EINVAL;
} }
aim_obj = create_most_aim_obj(aim->name); aim->dev.init_name = aim->name;
if (!aim_obj) { aim->dev.bus = &most_bus;
pr_info("failed to alloc driver object\n"); aim->dev.parent = &core_dev;
return -ENOMEM; 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", pr_info("registered new application interfacing module %s\n",
aim->name); aim->name);
list_add_tail(&aim_obj->list, &aim_list);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(most_register_aim); EXPORT_SYMBOL_GPL(most_register_aim);
...@@ -1647,7 +1315,6 @@ EXPORT_SYMBOL_GPL(most_register_aim); ...@@ -1647,7 +1315,6 @@ EXPORT_SYMBOL_GPL(most_register_aim);
*/ */
int most_deregister_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_c_obj *c, *tmp;
struct most_inst_obj *i, *i_tmp; struct most_inst_obj *i, *i_tmp;
...@@ -1656,11 +1323,6 @@ int most_deregister_aim(struct most_aim *aim) ...@@ -1656,11 +1323,6 @@ int most_deregister_aim(struct most_aim *aim)
return -EINVAL; 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(i, i_tmp, &instance_list, list) {
list_for_each_entry_safe(c, tmp, &i->channel_list, list) { list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
if (c->aim0.ptr == aim || c->aim1.ptr == aim) if (c->aim0.ptr == aim || c->aim1.ptr == aim)
...@@ -1672,13 +1334,22 @@ int most_deregister_aim(struct most_aim *aim) ...@@ -1672,13 +1334,22 @@ int most_deregister_aim(struct most_aim *aim)
c->aim1.ptr = NULL; c->aim1.ptr = NULL;
} }
} }
list_del(&aim_obj->list); device_unregister(&aim->dev);
destroy_most_aim_obj(aim_obj);
pr_info("deregistering application interfacing module %s\n", aim->name); pr_info("deregistering application interfacing module %s\n", aim->name);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(most_deregister_aim); 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 * most_register_interface - registers an interface with core
* @iface: pointer to the instance of the interface description. * @iface: pointer to the instance of the interface description.
...@@ -1686,7 +1357,7 @@ EXPORT_SYMBOL_GPL(most_deregister_aim); ...@@ -1686,7 +1357,7 @@ EXPORT_SYMBOL_GPL(most_deregister_aim);
* Allocates and initializes a new interface instance and all of its channels. * Allocates and initializes a new interface instance and all of its channels.
* Returns a pointer to kobject or an error pointer. * 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; unsigned int i;
int id; int id;
...@@ -1698,21 +1369,20 @@ struct kobject *most_register_interface(struct most_interface *iface) ...@@ -1698,21 +1369,20 @@ struct kobject *most_register_interface(struct most_interface *iface)
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)) {
pr_err("Bad interface or channel overflow\n"); pr_err("Bad interface or channel overflow\n");
return ERR_PTR(-EINVAL); return -EINVAL;
} }
id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL); id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL);
if (id < 0) { if (id < 0) {
pr_info("Failed to alloc mdev ID\n"); 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) { if (!inst) {
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 ERR_PTR(-ENOMEM); return -ENOMEM;
} }
iface->priv = inst; iface->priv = inst;
...@@ -1720,6 +1390,18 @@ struct kobject *most_register_interface(struct most_interface *iface) ...@@ -1720,6 +1390,18 @@ struct kobject *most_register_interface(struct most_interface *iface)
inst->iface = iface; inst->iface = iface;
inst->dev_id = id; inst->dev_id = id;
list_add_tail(&inst->list, &instance_list); list_add_tail(&inst->list, &instance_list);
snprintf(name, STRING_SIZE, "mdev%d", id);
iface->dev.init_name = name;
iface->dev.bus = &most_bus;
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++) { for (i = 0; i < iface->num_channels; i++) {
const char *name_suffix = iface->channel_vector[i].name_suffix; const char *name_suffix = iface->channel_vector[i].name_suffix;
...@@ -1730,9 +1412,17 @@ struct kobject *most_register_interface(struct most_interface *iface) ...@@ -1730,9 +1412,17 @@ struct kobject *most_register_interface(struct most_interface *iface)
snprintf(channel_name, STRING_SIZE, "%s", name_suffix); snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
/* this increments the reference count of this instance */ /* 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) if (!c)
goto free_instance; goto free_instance;
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; inst->channel[i] = c;
c->is_starving = 0; c->is_starving = 0;
c->iface = iface; c->iface = iface;
...@@ -1758,15 +1448,14 @@ struct kobject *most_register_interface(struct most_interface *iface) ...@@ -1758,15 +1448,14 @@ struct kobject *most_register_interface(struct most_interface *iface)
list_add_tail(&c->list, &inst->channel_list); list_add_tail(&c->list, &inst->channel_list);
} }
pr_info("registered new MOST device mdev%d (%s)\n", pr_info("registered new MOST device mdev%d (%s)\n",
inst->dev_id, iface->description); id, iface->description);
return &inst->kobj; return 0;
free_instance: free_instance:
pr_info("Failed allocate channel(s)\n"); pr_info("Failed allocate channel(s)\n");
list_del(&inst->list); device_unregister(&iface->dev);
ida_simple_remove(&mdev_id, id); ida_simple_remove(&mdev_id, id);
destroy_most_inst_obj(inst); return -ENOMEM;
return ERR_PTR(-ENOMEM);
} }
EXPORT_SYMBOL_GPL(most_register_interface); EXPORT_SYMBOL_GPL(most_register_interface);
...@@ -1779,17 +1468,14 @@ EXPORT_SYMBOL_GPL(most_register_interface); ...@@ -1779,17 +1468,14 @@ EXPORT_SYMBOL_GPL(most_register_interface);
*/ */
void most_deregister_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_c_obj *c;
struct most_inst_obj *inst;
if (unlikely(!i)) { pr_info("deregistering MOST device %s (%s)\n", dev_name(&iface->dev), iface->description);
pr_info("Bad Interface\n"); inst = iface->priv;
return; for (i = 0; i < iface->num_channels; i++) {
} c = inst->channel[i];
pr_info("deregistering MOST device %s (%s)\n", i->kobj.name,
iface->description);
list_for_each_entry(c, &i->channel_list, list) {
if (c->aim0.ptr) if (c->aim0.ptr)
c->aim0.ptr->disconnect_channel(c->iface, c->aim0.ptr->disconnect_channel(c->iface,
c->channel_id); c->channel_id);
...@@ -1798,11 +1484,14 @@ void most_deregister_interface(struct most_interface *iface) ...@@ -1798,11 +1484,14 @@ void most_deregister_interface(struct most_interface *iface)
c->channel_id); c->channel_id);
c->aim0.ptr = NULL; c->aim0.ptr = NULL;
c->aim1.ptr = NULL; c->aim1.ptr = NULL;
list_del(&c->list);
device_unregister(&c->dev);
kfree(c);
} }
ida_simple_remove(&mdev_id, i->dev_id); ida_simple_remove(&mdev_id, inst->dev_id);
list_del(&i->list); kfree(inst);
destroy_most_inst_obj(i); device_unregister(&iface->dev);
} }
EXPORT_SYMBOL_GPL(most_deregister_interface); EXPORT_SYMBOL_GPL(most_deregister_interface);
...@@ -1852,13 +1541,17 @@ void most_resume_enqueue(struct most_interface *iface, int id) ...@@ -1852,13 +1541,17 @@ void most_resume_enqueue(struct most_interface *iface, int id)
} }
EXPORT_SYMBOL_GPL(most_resume_enqueue); 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) 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(&instance_list);
INIT_LIST_HEAD(&aim_list);
ida_init(&mdev_id); ida_init(&mdev_id);
err = bus_register(&most_bus); err = bus_register(&most_bus);
...@@ -1880,30 +1573,15 @@ static int __init most_init(void) ...@@ -1880,30 +1573,15 @@ static int __init most_init(void)
goto exit_class; goto exit_class;
} }
core_dev = device_create(most_class, NULL, 0, NULL, "mostcore"); core_dev.init_name = "most_bus";
if (IS_ERR(core_dev)) { core_dev.release = release_most_sub;
err = PTR_ERR(core_dev); if (device_register(&core_dev)) {
goto exit_driver;
}
most_aim_kset = kset_create_and_add("aims", NULL, &core_dev->kobj);
if (!most_aim_kset) {
err = -ENOMEM;
goto exit_class_container;
}
most_inst_kset = kset_create_and_add("devices", NULL, &core_dev->kobj);
if (!most_inst_kset) {
err = -ENOMEM; err = -ENOMEM;
goto exit_driver_kset; goto exit_driver;
} }
return 0; return 0;
exit_driver_kset:
kset_unregister(most_aim_kset);
exit_class_container:
device_destroy(most_class, 0);
exit_driver: exit_driver:
driver_unregister(&mostcore); driver_unregister(&mostcore);
exit_class: exit_class:
...@@ -1915,21 +1593,8 @@ static int __init most_init(void) ...@@ -1915,21 +1593,8 @@ static int __init most_init(void)
static void __exit most_exit(void) 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"); pr_info("exit core module\n");
list_for_each_entry_safe(d, d_tmp, &aim_list, list) { device_unregister(&core_dev);
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);
driver_unregister(&mostcore); driver_unregister(&mostcore);
class_destroy(most_class); class_destroy(most_class);
bus_unregister(&most_bus); bus_unregister(&most_bus);
......
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
#define __MOST_CORE_H__ #define __MOST_CORE_H__
#include <linux/types.h> #include <linux/types.h>
#include <linux/device.h>
struct kobject;
struct module; struct module;
/** /**
...@@ -232,6 +232,7 @@ struct mbo { ...@@ -232,6 +232,7 @@ struct mbo {
* @priv Private field used by mostcore to store context information. * @priv Private field used by mostcore to store context information.
*/ */
struct most_interface { struct most_interface {
struct device dev;
struct module *mod; struct module *mod;
enum most_interface_type interface; enum most_interface_type interface;
const char *description; const char *description;
...@@ -249,6 +250,8 @@ struct most_interface { ...@@ -249,6 +250,8 @@ struct most_interface {
void *priv; void *priv;
}; };
#define to_most_interface(d) container_of(d, struct most_interface, dev)
/** /**
* struct most_aim - identifies MOST device driver to mostcore * struct most_aim - identifies MOST device driver to mostcore
* @name: Driver name * @name: Driver name
...@@ -259,10 +262,10 @@ struct most_interface { ...@@ -259,10 +262,10 @@ struct most_interface {
* @context: context pointer to be used by mostcore * @context: context pointer to be used by mostcore
*/ */
struct most_aim { struct most_aim {
struct device dev;
const char *name; const char *name;
int (*probe_channel)(struct most_interface *iface, int channel_idx, int (*probe_channel)(struct most_interface *iface, int channel_idx,
struct most_channel_config *cfg, struct most_channel_config *cfg, char *name);
struct kobject *parent, char *name);
int (*disconnect_channel)(struct most_interface *iface, int (*disconnect_channel)(struct most_interface *iface,
int channel_idx); int channel_idx);
int (*rx_completion)(struct mbo *mbo); int (*rx_completion)(struct mbo *mbo);
...@@ -270,6 +273,8 @@ struct most_aim { ...@@ -270,6 +273,8 @@ struct most_aim {
void *context; void *context;
}; };
#define to_most_aim(d) container_of(d, struct most_aim, dev)
/** /**
* most_register_interface - Registers instance of the interface. * most_register_interface - Registers instance of the interface.
* @iface: Pointer to the interface instance description. * @iface: Pointer to the interface instance description.
...@@ -279,7 +284,7 @@ struct most_aim { ...@@ -279,7 +284,7 @@ struct most_aim {
* Note: HDM has to ensure that any reference held on the kobj is * Note: HDM has to ensure that any reference held on the kobj is
* released before deregistering the interface. * 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. * Deregisters instance of the interface.
......
...@@ -87,6 +87,7 @@ struct hdm_channel { ...@@ -87,6 +87,7 @@ struct hdm_channel {
* @atx_idx: index of async tx channel * @atx_idx: index of async tx channel
*/ */
struct dim2_hdm { struct dim2_hdm {
struct device dev;
struct hdm_channel hch[DMA_CHANNELS]; struct hdm_channel hch[DMA_CHANNELS];
struct most_channel_capability capabilities[DMA_CHANNELS]; struct most_channel_capability capabilities[DMA_CHANNELS];
struct most_interface most_iface; struct most_interface most_iface;
...@@ -738,7 +739,6 @@ static int dim2_probe(struct platform_device *pdev) ...@@ -738,7 +739,6 @@ static int dim2_probe(struct platform_device *pdev)
struct dim2_hdm *dev; struct dim2_hdm *dev;
struct resource *res; struct resource *res;
int ret, i; int ret, i;
struct kobject *kobj;
int irq; int irq;
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
...@@ -826,17 +826,20 @@ static int dim2_probe(struct platform_device *pdev) ...@@ -826,17 +826,20 @@ static int dim2_probe(struct platform_device *pdev)
dev->most_iface.enqueue = enqueue; dev->most_iface.enqueue = enqueue;
dev->most_iface.poison_channel = poison_channel; dev->most_iface.poison_channel = poison_channel;
dev->most_iface.request_netinfo = request_netinfo; 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); ret = most_register_interface(&dev->most_iface);
if (IS_ERR(kobj)) { if (ret) {
ret = PTR_ERR(kobj);
dev_err(&pdev->dev, "failed to register MOST interface\n"); dev_err(&pdev->dev, "failed to register MOST interface\n");
goto err_stop_thread; goto err_stop_thread;
} }
ret = dim2_sysfs_probe(&dev->bus, kobj); ret = dim2_sysfs_probe(&dev->dev);
if (ret) if (ret) {
dev_err(&pdev->dev, "failed to create sysfs attribute\n");
goto err_unreg_iface; goto err_unreg_iface;
}
ret = startup_dim(pdev); ret = startup_dim(pdev);
if (ret) { if (ret) {
...@@ -847,7 +850,7 @@ static int dim2_probe(struct platform_device *pdev) ...@@ -847,7 +850,7 @@ static int dim2_probe(struct platform_device *pdev)
return 0; return 0;
err_destroy_bus: err_destroy_bus:
dim2_sysfs_destroy(&dev->bus); dim2_sysfs_destroy(&dev->dev);
err_unreg_iface: err_unreg_iface:
most_deregister_interface(&dev->most_iface); most_deregister_interface(&dev->most_iface);
err_stop_thread: err_stop_thread:
...@@ -875,7 +878,7 @@ static int dim2_remove(struct platform_device *pdev) ...@@ -875,7 +878,7 @@ static int dim2_remove(struct platform_device *pdev)
if (pdata && pdata->destroy) if (pdata && pdata->destroy)
pdata->destroy(pdata); pdata->destroy(pdata);
dim2_sysfs_destroy(&dev->bus); dim2_sysfs_destroy(&dev->dev);
most_deregister_interface(&dev->most_iface); most_deregister_interface(&dev->most_iface);
kthread_stop(dev->netinfo_task); kthread_stop(dev->netinfo_task);
......
...@@ -11,99 +11,39 @@ ...@@ -11,99 +11,39 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include "sysfs.h" #include "sysfs.h"
#include <linux/device.h>
struct bus_attr { static ssize_t state_show(struct device *dev, struct device_attribute *attr,
struct attribute attr; char *buf)
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)
{ {
bool state = dim2_sysfs_get_state_cb(); bool state = dim2_sysfs_get_state_cb();
return sprintf(buf, "%s\n", state ? "locked" : ""); 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[] = { static struct attribute *dev_attrs[] = {
&state_attr.attr, &dev_attr_state.attr,
NULL, NULL,
}; };
static const struct attribute_group bus_attr_group = { static struct attribute_group dev_attr_group = {
.attrs = bus_default_attrs, .attrs = dev_attrs,
}; };
static void bus_kobj_release(struct kobject *kobj) static const struct attribute_group *dev_attr_groups[] = {
{ &dev_attr_group,
} NULL,
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,
}; };
int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj) int dim2_sysfs_probe(struct device *dev)
{ {
int err; dev->groups = dev_attr_groups;
return device_register(dev);
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;
} }
void dim2_sysfs_destroy(struct medialb_bus *bus) void dim2_sysfs_destroy(struct device *dev)
{ {
kobject_put(&bus->kobj_group); device_unregister(dev);
} }
...@@ -16,10 +16,10 @@ struct medialb_bus { ...@@ -16,10 +16,10 @@ struct medialb_bus {
struct kobject kobj_group; struct kobject kobj_group;
}; };
struct dim2_hdm; struct device;
int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj); int dim2_sysfs_probe(struct device *dev);
void dim2_sysfs_destroy(struct medialb_bus *bus); void dim2_sysfs_destroy(struct device *dev);
/* /*
* callback, * callback,
......
...@@ -303,7 +303,6 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -303,7 +303,6 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{ {
struct hdm_i2c *dev; struct hdm_i2c *dev;
int ret, i; int ret, i;
struct kobject *kobj;
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) if (!dev)
...@@ -341,11 +340,11 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -341,11 +340,11 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev->client = client; dev->client = client;
i2c_set_clientdata(client, dev); i2c_set_clientdata(client, dev);
kobj = most_register_interface(&dev->most_iface); ret = most_register_interface(&dev->most_iface);
if (IS_ERR(kobj)) { if (ret) {
pr_err("Failed to register i2c as a MOST interface\n"); pr_err("Failed to register i2c as a MOST interface\n");
kfree(dev); kfree(dev);
return PTR_ERR(kobj); return ret;
} }
dev->polling_mode = polling_req || client->irq <= 0; dev->polling_mode = polling_req || client->irq <= 0;
......
...@@ -291,8 +291,7 @@ static struct net_dev_context *get_net_dev_hold(struct most_interface *iface) ...@@ -291,8 +291,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, static int aim_probe_channel(struct most_interface *iface, int channel_idx,
struct most_channel_config *ccfg, struct most_channel_config *ccfg, char *name)
struct kobject *parent, char *name)
{ {
struct net_dev_context *nd; struct net_dev_context *nd;
struct net_dev_channel *ch; struct net_dev_channel *ch;
......
...@@ -539,7 +539,6 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw, ...@@ -539,7 +539,6 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw,
* @iface: pointer to interface instance * @iface: pointer to interface instance
* @channel_id: channel index/ID * @channel_id: channel index/ID
* @cfg: pointer to actual channel configuration * @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 * @arg_list: string that provides the name of the device to be created in /dev
* plus the desired audio resolution * plus the desired audio resolution
* *
...@@ -549,7 +548,7 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw, ...@@ -549,7 +548,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, static int audio_probe_channel(struct most_interface *iface, int channel_id,
struct most_channel_config *cfg, struct most_channel_config *cfg,
struct kobject *parent, char *arg_list) char *arg_list)
{ {
struct channel *channel; struct channel *channel;
struct snd_card *card; struct snd_card *card;
......
...@@ -64,12 +64,12 @@ ...@@ -64,12 +64,12 @@
* @reg_addr: register address for arbitrary DCI access * @reg_addr: register address for arbitrary DCI access
*/ */
struct most_dci_obj { struct most_dci_obj {
struct kobject kobj; struct device dev;
struct usb_device *usb_device; struct usb_device *usb_device;
u16 reg_addr; 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; struct most_dev;
...@@ -84,7 +84,6 @@ struct clear_hold_work { ...@@ -84,7 +84,6 @@ struct clear_hold_work {
/** /**
* struct most_dev - holds all usb interface specific stuff * struct most_dev - holds all usb interface specific stuff
* @parent: parent object in sysfs
* @usb_device: pointer to usb device * @usb_device: pointer to usb device
* @iface: hardware interface * @iface: hardware interface
* @cap: channel capabilities * @cap: channel capabilities
...@@ -102,7 +101,6 @@ struct clear_hold_work { ...@@ -102,7 +101,6 @@ struct clear_hold_work {
* @poll_work_obj: work for polling link status * @poll_work_obj: work for polling link status
*/ */
struct most_dev { struct most_dev {
struct kobject *parent;
struct usb_device *usb_device; struct usb_device *usb_device;
struct most_interface iface; struct most_interface iface;
struct most_channel_capability *cap; struct most_channel_capability *cap;
...@@ -834,94 +832,6 @@ static const struct usb_device_id usbid[] = { ...@@ -834,94 +832,6 @@ static const struct usb_device_id usbid[] = {
{ } /* Terminating entry */ { } /* 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 { struct regs {
const char *name; const char *name;
u16 reg; u16 reg;
...@@ -962,10 +872,11 @@ static int get_stat_reg_addr(const struct regs *regs, int size, ...@@ -962,10 +872,11 @@ static int get_stat_reg_addr(const struct regs *regs, int size,
#define get_static_reg_addr(regs, name, reg_addr) \ #define get_static_reg_addr(regs, name, reg_addr) \
get_stat_reg_addr(regs, ARRAY_SIZE(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, static ssize_t show_value(struct device *dev, struct device_attribute *attr,
struct most_dci_attribute *attr, char *buf) char *buf)
{ {
const char *name = attr->attr.name; const char *name = attr->attr.name;
struct most_dci_obj *dci_obj = to_dci_obj(dev);
u16 val; u16 val;
u16 reg_addr; u16 reg_addr;
int err; int err;
...@@ -986,13 +897,13 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, ...@@ -986,13 +897,13 @@ static ssize_t show_value(struct most_dci_obj *dci_obj,
return snprintf(buf, PAGE_SIZE, "%04x\n", val); return snprintf(buf, PAGE_SIZE, "%04x\n", val);
} }
static ssize_t store_value(struct most_dci_obj *dci_obj, static ssize_t store_value(struct device *dev, struct device_attribute *attr,
struct most_dci_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
u16 val; u16 val;
u16 reg_addr; u16 reg_addr;
const char *name = attr->attr.name; 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; struct usb_device *usb_dev = dci_obj->usb_device;
int err = kstrtou16(buf, 16, &val); int err = kstrtou16(buf, 16, &val);
...@@ -1019,86 +930,49 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, ...@@ -1019,86 +930,49 @@ static ssize_t store_value(struct most_dci_obj *dci_obj,
return count; return count;
} }
static MOST_DCI_RO_ATTR(ni_state); DEVICE_ATTR(ni_state, 0444, show_value, NULL);
static MOST_DCI_RO_ATTR(packet_bandwidth); DEVICE_ATTR(packet_bandwidth, 0444, show_value, NULL);
static MOST_DCI_RO_ATTR(node_address); DEVICE_ATTR(node_address, 0444, show_value, NULL);
static MOST_DCI_RO_ATTR(node_position); DEVICE_ATTR(node_position, 0444, show_value, NULL);
static MOST_DCI_WO_ATTR(sync_ep); DEVICE_ATTR(sync_ep, 0200, NULL, store_value);
static MOST_DCI_ATTR(mep_filter); DEVICE_ATTR(mep_filter, 0644, show_value, store_value);
static MOST_DCI_ATTR(mep_hash0); DEVICE_ATTR(mep_hash0, 0644, show_value, store_value);
static MOST_DCI_ATTR(mep_hash1); DEVICE_ATTR(mep_hash1, 0644, show_value, store_value);
static MOST_DCI_ATTR(mep_hash2); DEVICE_ATTR(mep_hash2, 0644, show_value, store_value);
static MOST_DCI_ATTR(mep_hash3); DEVICE_ATTR(mep_hash3, 0644, show_value, store_value);
static MOST_DCI_ATTR(mep_eui48_hi); DEVICE_ATTR(mep_eui48_hi, 0644, show_value, store_value);
static MOST_DCI_ATTR(mep_eui48_mi); DEVICE_ATTR(mep_eui48_mi, 0644, show_value, store_value);
static MOST_DCI_ATTR(mep_eui48_lo); DEVICE_ATTR(mep_eui48_lo, 0644, show_value, store_value);
static MOST_DCI_ATTR(arb_address); DEVICE_ATTR(arb_address, 0644, show_value, store_value);
static MOST_DCI_ATTR(arb_value); DEVICE_ATTR(arb_value, 0644, show_value, store_value);
/** static struct attribute *dci_attrs[] = {
* most_dci_def_attrs - array of default attribute files of the dci object &dev_attr_ni_state.attr,
*/ &dev_attr_packet_bandwidth.attr,
static struct attribute *most_dci_def_attrs[] = { &dev_attr_node_address.attr,
&most_dci_attr_ni_state.attr, &dev_attr_node_position.attr,
&most_dci_attr_packet_bandwidth.attr, &dev_attr_sync_ep.attr,
&most_dci_attr_node_address.attr, &dev_attr_mep_filter.attr,
&most_dci_attr_node_position.attr, &dev_attr_mep_hash0.attr,
&most_dci_attr_sync_ep.attr, &dev_attr_mep_hash1.attr,
&most_dci_attr_mep_filter.attr, &dev_attr_mep_hash2.attr,
&most_dci_attr_mep_hash0.attr, &dev_attr_mep_hash3.attr,
&most_dci_attr_mep_hash1.attr, &dev_attr_mep_eui48_hi.attr,
&most_dci_attr_mep_hash2.attr, &dev_attr_mep_eui48_mi.attr,
&most_dci_attr_mep_hash3.attr, &dev_attr_mep_eui48_lo.attr,
&most_dci_attr_mep_eui48_hi.attr, &dev_attr_arb_address.attr,
&most_dci_attr_mep_eui48_mi.attr, &dev_attr_arb_value.attr,
&most_dci_attr_mep_eui48_lo.attr,
&most_dci_attr_arb_address.attr,
&most_dci_attr_arb_value.attr,
NULL, NULL,
}; };
/** static struct attribute_group dci_attr_group = {
* DCI ktype .attrs = dci_attrs,
*/
static struct kobj_type most_dci_ktype = {
.sysfs_ops = &most_dci_sysfs_ops,
.release = most_dci_release,
.default_attrs = most_dci_def_attrs,
}; };
/** static const struct attribute_group *dci_attr_groups[] = {
* create_most_dci_obj - allocates a dci object &dci_attr_group,
* @parent: parent kobject NULL,
* };
* 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);
}
/** /**
* hdm_probe - probe function of USB device driver * hdm_probe - probe function of USB device driver
...@@ -1211,20 +1085,15 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) ...@@ -1211,20 +1085,15 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
usb_dev->config->desc.bConfigurationValue, usb_dev->config->desc.bConfigurationValue,
usb_iface_desc->desc.bInterfaceNumber); usb_iface_desc->desc.bInterfaceNumber);
mdev->parent = most_register_interface(&mdev->iface); ret = most_register_interface(&mdev->iface);
if (IS_ERR(mdev->parent)) { if (ret)
ret = PTR_ERR(mdev->parent);
goto exit_free4; goto exit_free4;
}
mutex_lock(&mdev->io_mutex); mutex_lock(&mdev->io_mutex);
if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 || 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_OS81119 ||
le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) { le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) {
/* this increments the reference count of the instance mdev->dci = kzalloc(sizeof(*mdev->dci), GFP_KERNEL);
* object of the core
*/
mdev->dci = create_most_dci_obj(mdev->parent);
if (!mdev->dci) { if (!mdev->dci) {
mutex_unlock(&mdev->io_mutex); mutex_unlock(&mdev->io_mutex);
most_deregister_interface(&mdev->iface); most_deregister_interface(&mdev->iface);
...@@ -1232,12 +1101,21 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) ...@@ -1232,12 +1101,21 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
goto exit_free4; 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; mdev->dci->usb_device = mdev->usb_device;
} }
mutex_unlock(&mdev->io_mutex); mutex_unlock(&mdev->io_mutex);
return 0; return 0;
exit_free5:
kfree(mdev->dci);
exit_free4: exit_free4:
kfree(mdev->busy_urbs); kfree(mdev->busy_urbs);
exit_free3: exit_free3:
...@@ -1277,7 +1155,8 @@ static void hdm_disconnect(struct usb_interface *interface) ...@@ -1277,7 +1155,8 @@ static void hdm_disconnect(struct usb_interface *interface)
del_timer_sync(&mdev->link_stat_timer); del_timer_sync(&mdev->link_stat_timer);
cancel_work_sync(&mdev->poll_work_obj); 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); most_deregister_interface(&mdev->iface);
kfree(mdev->busy_urbs); kfree(mdev->busy_urbs);
......
...@@ -480,8 +480,7 @@ static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev) ...@@ -480,8 +480,7 @@ static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
} }
static int aim_probe_channel(struct most_interface *iface, int channel_idx, static int aim_probe_channel(struct most_interface *iface, int channel_idx,
struct most_channel_config *ccfg, struct most_channel_config *ccfg, char *name)
struct kobject *parent, char *name)
{ {
int ret; int ret;
struct most_video_dev *mdev = get_aim_dev(iface, channel_idx); struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment