summaryrefslogtreecommitdiffstats
path: root/driver/mostcore
diff options
context:
space:
mode:
Diffstat (limited to 'driver/mostcore')
-rw-r--r--driver/mostcore/Makefile18
-rw-r--r--driver/mostcore/core.c260
2 files changed, 130 insertions, 148 deletions
diff --git a/driver/mostcore/Makefile b/driver/mostcore/Makefile
deleted file mode 100644
index cffcd8e..0000000
--- a/driver/mostcore/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# Makefile
-#
-
-SRC := $(shell pwd)
-
-obj-m := mostcore.o
-mostcore-y := core.o
-CFLAGS_core.o := -I$(src)/../include/
-
-all:
- $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules
-
-modules_install:
- $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
-
-clean:
- $(MAKE) -C $(KERNEL_SRC) M=$(SRC) clean
-
diff --git a/driver/mostcore/core.c b/driver/mostcore/core.c
index 4c580d1..4d51441 100644
--- a/driver/mostcore/core.c
+++ b/driver/mostcore/core.c
@@ -82,7 +82,7 @@ struct most_inst_obj {
static const struct {
int most_ch_data_type;
- char *name;
+ const char *name;
} ch_data_type[] = {
{ MOST_CH_CONTROL, "control\n" },
{ MOST_CH_ASYNC, "async\n" },
@@ -127,10 +127,6 @@ struct most_c_attr {
#define to_channel_attr(a) container_of(a, struct most_c_attr, attr)
-#define MOST_CHNL_ATTR(_name, _mode, _show, _store) \
- struct most_c_attr most_chnl_attr_##_name = \
- __ATTR(_name, _mode, _show, _store)
-
/**
* channel_attr_show - show function of channel object
* @kobj: pointer to its kobject
@@ -184,8 +180,10 @@ static void most_free_mbo_coherent(struct mbo *mbo)
struct most_c_obj *c = mbo->context;
u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
- dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address,
- mbo->bus_address);
+ if (c->iface->dma_free)
+ c->iface->dma_free(mbo, coherent_buf_size);
+ else
+ kfree(mbo->virt_address);
kfree(mbo);
if (atomic_sub_and_test(1, &c->mbo_ref))
complete(&c->cleanup);
@@ -256,7 +254,7 @@ static void most_channel_release(struct kobject *kobj)
kfree(c);
}
-static ssize_t show_available_directions(struct most_c_obj *c,
+static ssize_t available_directions_show(struct most_c_obj *c,
struct most_c_attr *attr,
char *buf)
{
@@ -271,7 +269,7 @@ static ssize_t show_available_directions(struct most_c_obj *c,
return strlen(buf);
}
-static ssize_t show_available_datatypes(struct most_c_obj *c,
+static ssize_t available_datatypes_show(struct most_c_obj *c,
struct most_c_attr *attr,
char *buf)
{
@@ -290,10 +288,9 @@ static ssize_t show_available_datatypes(struct most_c_obj *c,
return strlen(buf);
}
-static
-ssize_t show_number_of_packet_buffers(struct most_c_obj *c,
- struct most_c_attr *attr,
- char *buf)
+static ssize_t number_of_packet_buffers_show(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
{
unsigned int i = c->channel_id;
@@ -301,10 +298,9 @@ ssize_t show_number_of_packet_buffers(struct most_c_obj *c,
c->iface->channel_vector[i].num_buffers_packet);
}
-static
-ssize_t show_number_of_stream_buffers(struct most_c_obj *c,
- struct most_c_attr *attr,
- char *buf)
+static ssize_t number_of_stream_buffers_show(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
{
unsigned int i = c->channel_id;
@@ -312,10 +308,9 @@ ssize_t show_number_of_stream_buffers(struct most_c_obj *c,
c->iface->channel_vector[i].num_buffers_streaming);
}
-static
-ssize_t show_size_of_packet_buffer(struct most_c_obj *c,
- struct most_c_attr *attr,
- char *buf)
+static ssize_t size_of_packet_buffer_show(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
{
unsigned int i = c->channel_id;
@@ -323,10 +318,9 @@ ssize_t show_size_of_packet_buffer(struct most_c_obj *c,
c->iface->channel_vector[i].buffer_size_packet);
}
-static
-ssize_t show_size_of_stream_buffer(struct most_c_obj *c,
- struct most_c_attr *attr,
- char *buf)
+static ssize_t size_of_stream_buffer_show(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
{
unsigned int i = c->channel_id;
@@ -334,32 +328,21 @@ ssize_t show_size_of_stream_buffer(struct most_c_obj *c,
c->iface->channel_vector[i].buffer_size_streaming);
}
-static ssize_t show_channel_starving(struct most_c_obj *c,
+static ssize_t channel_starving_show(struct most_c_obj *c,
struct most_c_attr *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
}
-#define create_show_channel_attribute(val) \
- static MOST_CHNL_ATTR(val, S_IRUGO, show_##val, NULL)
-
-create_show_channel_attribute(available_directions);
-create_show_channel_attribute(available_datatypes);
-create_show_channel_attribute(number_of_packet_buffers);
-create_show_channel_attribute(number_of_stream_buffers);
-create_show_channel_attribute(size_of_stream_buffer);
-create_show_channel_attribute(size_of_packet_buffer);
-create_show_channel_attribute(channel_starving);
-
-static ssize_t show_set_number_of_buffers(struct most_c_obj *c,
+static ssize_t set_number_of_buffers_show(struct most_c_obj *c,
struct most_c_attr *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
}
-static ssize_t store_set_number_of_buffers(struct most_c_obj *c,
+static ssize_t set_number_of_buffers_store(struct most_c_obj *c,
struct most_c_attr *attr,
const char *buf,
size_t count)
@@ -371,14 +354,14 @@ static ssize_t store_set_number_of_buffers(struct most_c_obj *c,
return count;
}
-static ssize_t show_set_buffer_size(struct most_c_obj *c,
+static ssize_t set_buffer_size_show(struct most_c_obj *c,
struct most_c_attr *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
}
-static ssize_t store_set_buffer_size(struct most_c_obj *c,
+static ssize_t set_buffer_size_store(struct most_c_obj *c,
struct most_c_attr *attr,
const char *buf,
size_t count)
@@ -390,7 +373,7 @@ static ssize_t store_set_buffer_size(struct most_c_obj *c,
return count;
}
-static ssize_t show_set_direction(struct most_c_obj *c,
+static ssize_t set_direction_show(struct most_c_obj *c,
struct most_c_attr *attr,
char *buf)
{
@@ -401,7 +384,7 @@ static ssize_t show_set_direction(struct most_c_obj *c,
return snprintf(buf, PAGE_SIZE, "unconfigured\n");
}
-static ssize_t store_set_direction(struct most_c_obj *c,
+static ssize_t set_direction_store(struct most_c_obj *c,
struct most_c_attr *attr,
const char *buf,
size_t count)
@@ -421,7 +404,7 @@ static ssize_t store_set_direction(struct most_c_obj *c,
return count;
}
-static ssize_t show_set_datatype(struct most_c_obj *c,
+static ssize_t set_datatype_show(struct most_c_obj *c,
struct most_c_attr *attr,
char *buf)
{
@@ -434,7 +417,7 @@ static ssize_t show_set_datatype(struct most_c_obj *c,
return snprintf(buf, PAGE_SIZE, "unconfigured\n");
}
-static ssize_t store_set_datatype(struct most_c_obj *c,
+static ssize_t set_datatype_store(struct most_c_obj *c,
struct most_c_attr *attr,
const char *buf,
size_t count)
@@ -455,14 +438,14 @@ static ssize_t store_set_datatype(struct most_c_obj *c,
return count;
}
-static ssize_t show_set_subbuffer_size(struct most_c_obj *c,
+static ssize_t set_subbuffer_size_show(struct most_c_obj *c,
struct most_c_attr *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
}
-static ssize_t store_set_subbuffer_size(struct most_c_obj *c,
+static ssize_t set_subbuffer_size_store(struct most_c_obj *c,
struct most_c_attr *attr,
const char *buf,
size_t count)
@@ -474,14 +457,14 @@ static ssize_t store_set_subbuffer_size(struct most_c_obj *c,
return count;
}
-static ssize_t show_set_packets_per_xact(struct most_c_obj *c,
+static ssize_t set_packets_per_xact_show(struct most_c_obj *c,
struct most_c_attr *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact);
}
-static ssize_t store_set_packets_per_xact(struct most_c_obj *c,
+static ssize_t set_packets_per_xact_store(struct most_c_obj *c,
struct most_c_attr *attr,
const char *buf,
size_t count)
@@ -493,45 +476,41 @@ static ssize_t store_set_packets_per_xact(struct most_c_obj *c,
return count;
}
-#define create_channel_attribute(value) \
- static MOST_CHNL_ATTR(value, S_IRUGO | S_IWUSR, \
- show_##value, \
- store_##value)
+static ssize_t set_dbr_size_show(struct most_c_obj *c,
+ struct most_c_attr *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.dbr_size);
+}
-create_channel_attribute(set_buffer_size);
-create_channel_attribute(set_number_of_buffers);
-create_channel_attribute(set_direction);
-create_channel_attribute(set_datatype);
-create_channel_attribute(set_subbuffer_size);
-create_channel_attribute(set_packets_per_xact);
+static ssize_t set_dbr_size_store(struct most_c_obj *c,
+ struct most_c_attr *attr, const char *buf,
+ size_t count)
+{
+ int ret = kstrtou16(buf, 0, &c->cfg.dbr_size);
-/**
- * most_channel_def_attrs - array of default attributes of channel object
- */
-static struct attribute *most_channel_def_attrs[] = {
- &most_chnl_attr_available_directions.attr,
- &most_chnl_attr_available_datatypes.attr,
- &most_chnl_attr_number_of_packet_buffers.attr,
- &most_chnl_attr_number_of_stream_buffers.attr,
- &most_chnl_attr_size_of_packet_buffer.attr,
- &most_chnl_attr_size_of_stream_buffer.attr,
- &most_chnl_attr_set_number_of_buffers.attr,
- &most_chnl_attr_set_buffer_size.attr,
- &most_chnl_attr_set_direction.attr,
- &most_chnl_attr_set_datatype.attr,
- &most_chnl_attr_set_subbuffer_size.attr,
- &most_chnl_attr_set_packets_per_xact.attr,
- &most_chnl_attr_channel_starving.attr,
- NULL,
-};
+ if (ret)
+ return ret;
+ return count;
+}
-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 most_c_attr common_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),
};
-static struct kset *most_channel_kset;
+static struct most_c_attr xact_c_attr = __ATTR_RW(set_packets_per_xact);
+
+static struct most_c_attr dbr_c_attr = __ATTR_RW(set_dbr_size);
/**
* create_most_c_obj - allocates a channel object
@@ -541,8 +520,8 @@ static struct kset *most_channel_kset;
* 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)
+static struct most_c_obj *create_most_c_obj(
+ struct kobj_type *ktype, const char *name, struct kobject *parent)
{
struct most_c_obj *c;
int retval;
@@ -550,9 +529,7 @@ create_most_c_obj(const char *name, struct kobject *parent)
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);
+ retval = kobject_init_and_add(&c->kobj, ktype, parent, "%s", name);
if (retval) {
kobject_put(&c->kobj);
return NULL;
@@ -564,9 +541,6 @@ create_most_c_obj(const char *name, struct kobject *parent)
/* ___ ___
* ___I N S T A N C E___
*/
-#define MOST_INST_ATTR(_name, _mode, _show, _store) \
- struct most_inst_attribute most_inst_attr_##_name = \
- __ATTR(_name, _mode, _show, _store)
static struct list_head instance_list;
@@ -654,7 +628,7 @@ static void most_inst_release(struct kobject *kobj)
kfree(inst);
}
-static ssize_t show_description(struct most_inst_obj *instance_obj,
+static ssize_t description_show(struct most_inst_obj *instance_obj,
struct most_inst_attribute *attr,
char *buf)
{
@@ -662,7 +636,7 @@ static ssize_t show_description(struct most_inst_obj *instance_obj,
instance_obj->iface->description);
}
-static ssize_t show_interface(struct most_inst_obj *instance_obj,
+static ssize_t interface_show(struct most_inst_obj *instance_obj,
struct most_inst_attribute *attr,
char *buf)
{
@@ -689,11 +663,11 @@ static ssize_t show_interface(struct most_inst_obj *instance_obj,
return snprintf(buf, PAGE_SIZE, "unknown\n");
}
-#define create_inst_attribute(value) \
- static MOST_INST_ATTR(value, S_IRUGO, show_##value, NULL)
+static struct most_inst_attribute most_inst_attr_description =
+ __ATTR_RO(description);
-create_inst_attribute(description);
-create_inst_attribute(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,
@@ -849,9 +823,9 @@ static void most_aim_release(struct kobject *kobj)
kfree(aim_obj);
}
-static ssize_t show_add_link(struct most_aim_obj *aim_obj,
- struct most_aim_attribute *attr,
- char *buf)
+static ssize_t links_show(struct most_aim_obj *aim_obj,
+ struct most_aim_attribute *attr,
+ char *buf)
{
struct most_c_obj *c;
struct most_inst_obj *i;
@@ -945,7 +919,7 @@ most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
}
/**
- * store_add_link - store() function for add_link attribute
+ * add_link_store - store() function for add_link attribute
* @aim_obj: pointer to AIM object
* @attr: its attributes
* @buf: buffer
@@ -966,7 +940,7 @@ 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 store_add_link(struct most_aim_obj *aim_obj,
+static ssize_t add_link_store(struct most_aim_obj *aim_obj,
struct most_aim_attribute *attr,
const char *buf,
size_t len)
@@ -1015,11 +989,8 @@ static ssize_t store_add_link(struct most_aim_obj *aim_obj,
return len;
}
-static struct most_aim_attribute most_aim_attr_add_link =
- __ATTR(add_link, S_IRUGO | S_IWUSR, show_add_link, store_add_link);
-
/**
- * store_remove_link - store function for remove_link attribute
+ * remove_link_store - store function for remove_link attribute
* @aim_obj: pointer to AIM object
* @attr: its attributes
* @buf: buffer
@@ -1028,7 +999,7 @@ static struct most_aim_attribute most_aim_attr_add_link =
* Example:
* echo "mdev0:ep81" >remove_link
*/
-static ssize_t store_remove_link(struct most_aim_obj *aim_obj,
+static ssize_t remove_link_store(struct most_aim_obj *aim_obj,
struct most_aim_attribute *attr,
const char *buf,
size_t len)
@@ -1058,12 +1029,16 @@ static ssize_t store_remove_link(struct most_aim_obj *aim_obj,
return len;
}
-static struct most_aim_attribute most_aim_attr_remove_link =
- __ATTR(remove_link, S_IWUSR, NULL, store_remove_link);
+static struct most_aim_attribute most_aim_attrs[] = {
+ __ATTR_RO(links),
+ __ATTR_WO(add_link),
+ __ATTR_WO(remove_link),
+};
static struct attribute *most_aim_def_attrs[] = {
- &most_aim_attr_add_link.attr,
- &most_aim_attr_remove_link.attr,
+ &most_aim_attrs[0].attr,
+ &most_aim_attrs[1].attr,
+ &most_aim_attrs[2].attr,
NULL,
};
@@ -1274,45 +1249,49 @@ static int arm_mbo_chain(struct most_c_obj *c, int dir,
void (*compl)(struct mbo *))
{
unsigned int i;
- int retval;
struct mbo *mbo;
+ unsigned long flags;
u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
atomic_set(&c->mbo_nq_level, 0);
for (i = 0; i < c->cfg.num_buffers; i++) {
mbo = kzalloc(sizeof(*mbo), GFP_KERNEL);
- if (!mbo) {
- retval = i;
- goto _exit;
- }
+ if (!mbo)
+ goto flush_fifos;
+
mbo->context = c;
mbo->ifp = c->iface;
mbo->hdm_channel_id = c->channel_id;
- mbo->virt_address = dma_alloc_coherent(NULL,
- coherent_buf_size,
- &mbo->bus_address,
- GFP_KERNEL);
- if (!mbo->virt_address) {
- pr_info("WARN: No DMA coherent buffer.\n");
- retval = i;
- goto _error1;
+ if (c->iface->dma_alloc) {
+ mbo->virt_address =
+ c->iface->dma_alloc(mbo, coherent_buf_size);
+ } else {
+ mbo->virt_address =
+ kzalloc(coherent_buf_size, GFP_KERNEL);
}
+ if (!mbo->virt_address)
+ goto release_mbo;
+
mbo->complete = compl;
mbo->num_buffers_ptr = &dummy_num_buffers;
if (dir == MOST_CH_RX) {
nq_hdm_mbo(mbo);
atomic_inc(&c->mbo_nq_level);
} else {
- arm_mbo(mbo);
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ list_add_tail(&mbo->list, &c->fifo);
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
}
}
- return i;
+ return c->cfg.num_buffers;
-_error1:
+release_mbo:
kfree(mbo);
-_exit:
- return retval;
+
+flush_fifos:
+ flush_channel_fifos(c);
+ return 0;
}
/**
@@ -1739,6 +1718,27 @@ struct kobject *most_register_interface(struct most_interface *iface)
}
iface->priv = inst;
+ iface->ktype.sysfs_ops = &most_channel_sysfs_ops,
+ iface->ktype.release = most_channel_release,
+ iface->ktype.default_attrs = iface->attrs;
+
+ BUILD_BUG_ON(ARRAY_SIZE(iface->attrs) < ARRAY_SIZE(common_c_attrs) + 2);
+ for (i = 0; i < ARRAY_SIZE(common_c_attrs); i++)
+ iface->attrs[i] = &common_c_attrs[i].attr;
+ switch (iface->extra_attrs) {
+ case XACT_ATTRS:
+ iface->attrs[i] = &xact_c_attr.attr;
+ i++;
+ break;
+ case DBR_ATTRS:
+ iface->attrs[i] = &dbr_c_attr.attr;
+ i++;
+ break;
+ default:
+ break;
+ }
+ iface->attrs[i] = NULL;
+
INIT_LIST_HEAD(&inst->channel_list);
inst->iface = iface;
inst->dev_id = id;
@@ -1753,7 +1753,7 @@ 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 = create_most_c_obj(&iface->ktype, channel_name, &inst->kobj);
if (!c)
goto free_instance;
inst->channel[i] = c;