summaryrefslogtreecommitdiff
path: root/drivers/staging/greybus/loopback.c
diff options
context:
space:
mode:
authorAxel Haslam <ahaslam@baylibre.com>2015-12-11 11:49:45 +0100
committerGreg Kroah-Hartman <gregkh@google.com>2015-12-11 16:04:40 -0800
commit079fa32ba53a205a745e75b045361beeffdfeaba (patch)
tree93ddbe39f46547c9206c408b0fa5a735bc3a116c /drivers/staging/greybus/loopback.c
parent3647a313de367e98840c4dfab491dfbeaf2cf9a4 (diff)
greybus: loopback: register a struct device.
Instead of having the loopback attributes in the bundle device, Add a struct device to the gb_loopback struct and register it on connection_init, deregister it at connection_exit, and move the loopback attribute group over to the new device. Use device_create_with_groups to create sysfs attributes together with device. Suggested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Suggested-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/loopback.c')
-rw-r--r--drivers/staging/greybus/loopback.c95
1 files changed, 58 insertions, 37 deletions
diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c
index 6a5eee35e9c0..68372918f653 100644
--- a/drivers/staging/greybus/loopback.c
+++ b/drivers/staging/greybus/loopback.c
@@ -71,6 +71,7 @@ struct gb_loopback {
struct mutex mutex;
struct task_struct *task;
struct list_head entry;
+ struct device *dev;
wait_queue_head_t wq;
/* Per connection stats */
@@ -82,6 +83,7 @@ struct gb_loopback {
int type;
int async;
+ int id;
u32 size;
u32 iteration_max;
u32 iteration_count;
@@ -99,6 +101,12 @@ struct gb_loopback {
u32 gpbridge_latency_ts;
};
+static struct class loopback_class = {
+ .name = "gb_loopback",
+ .owner = THIS_MODULE,
+};
+static DEFINE_IDA(loopback_ida);
+
/* Min/max values in jiffies */
#define GB_LOOPBACK_TIMEOUT_MIN 1
#define GB_LOOPBACK_TIMEOUT_MAX 10000
@@ -119,10 +127,7 @@ static ssize_t field##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
- struct gb_bundle *bundle; \
- struct gb_loopback *gb; \
- bundle = to_gb_bundle(dev); \
- gb = bundle->private; \
+ struct gb_loopback *gb = dev_get_drvdata(dev); \
return sprintf(buf, "%u\n", gb->field); \
} \
static DEVICE_ATTR_RO(field)
@@ -132,10 +137,7 @@ static ssize_t name##_##field##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
- struct gb_bundle *bundle; \
- struct gb_loopback *gb; \
- bundle = to_gb_bundle(dev); \
- gb = bundle->private; \
+ struct gb_loopback *gb = dev_get_drvdata(dev); \
return sprintf(buf, "%"#type"\n", gb->name.field); \
} \
static DEVICE_ATTR_RO(name##_##field)
@@ -146,12 +148,10 @@ static ssize_t name##_avg_show(struct device *dev, \
char *buf) \
{ \
struct gb_loopback_stats *stats; \
- struct gb_bundle *bundle; \
struct gb_loopback *gb; \
u64 avg; \
u32 count, rem; \
- bundle = to_gb_bundle(dev); \
- gb = bundle->private; \
+ gb = dev_get_drvdata(dev); \
stats = &gb->name; \
count = stats->count ? stats->count : 1; \
avg = stats->sum + count / 2; /* round closest */ \
@@ -170,8 +170,7 @@ static ssize_t field##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
- struct gb_bundle *bundle = to_gb_bundle(dev); \
- struct gb_loopback *gb = bundle->private; \
+ struct gb_loopback *gb = dev_get_drvdata(dev); \
return sprintf(buf, "%"#type"\n", gb->field); \
} \
static ssize_t field##_store(struct device *dev, \
@@ -180,8 +179,7 @@ static ssize_t field##_store(struct device *dev, \
size_t len) \
{ \
int ret; \
- struct gb_bundle *bundle = to_gb_bundle(dev); \
- struct gb_loopback *gb = bundle->private; \
+ struct gb_loopback *gb = dev_get_drvdata(dev); \
mutex_lock(&gb->mutex); \
ret = sscanf(buf, "%"#type, &gb->field); \
if (ret != 1) \
@@ -198,8 +196,7 @@ static ssize_t field##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
- struct gb_bundle *bundle = to_gb_bundle(dev); \
- struct gb_loopback *gb = bundle->private; \
+ struct gb_loopback *gb = dev_get_drvdata(dev); \
return sprintf(buf, "%u\n", gb->field); \
} \
static DEVICE_ATTR_RO(field)
@@ -209,8 +206,7 @@ static ssize_t field##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
- struct gb_bundle *bundle = to_gb_bundle(dev); \
- struct gb_loopback *gb = bundle->private; \
+ struct gb_loopback *gb = dev_get_drvdata(dev); \
return sprintf(buf, "%"#type"\n", gb->field); \
} \
static ssize_t field##_store(struct device *dev, \
@@ -219,22 +215,20 @@ static ssize_t field##_store(struct device *dev, \
size_t len) \
{ \
int ret; \
- struct gb_bundle *bundle = to_gb_bundle(dev); \
- struct gb_loopback *gb = bundle->private; \
+ struct gb_loopback *gb = dev_get_drvdata(dev); \
mutex_lock(&gb->mutex); \
ret = sscanf(buf, "%"#type, &gb->field); \
if (ret != 1) \
len = -EINVAL; \
else \
- gb_loopback_check_attr(gb, bundle); \
+ gb_loopback_check_attr(gb); \
mutex_unlock(&gb->mutex); \
return len; \
} \
static DEVICE_ATTR_RW(field)
static void gb_loopback_reset_stats(struct gb_loopback *gb);
-static void gb_loopback_check_attr(struct gb_loopback *gb,
- struct gb_bundle *bundle)
+static void gb_loopback_check_attr(struct gb_loopback *gb)
{
if (gb->us_wait > GB_LOOPBACK_US_WAIT_MAX)
gb->us_wait = GB_LOOPBACK_US_WAIT_MAX;
@@ -246,7 +240,7 @@ static void gb_loopback_check_attr(struct gb_loopback *gb,
gb->error = 0;
if (kfifo_depth < gb->iteration_max) {
- dev_warn(&bundle->dev,
+ dev_warn(gb->dev,
"cannot log bytes %u kfifo_depth %u\n",
gb->iteration_max, kfifo_depth);
}
@@ -1062,6 +1056,7 @@ static void gb_loopback_insert_id(struct gb_loopback *gb)
static int gb_loopback_connection_init(struct gb_connection *connection)
{
struct gb_loopback *gb;
+ struct device *dev;
int retval;
char name[DEBUGFS_NAMELEN];
unsigned long flags;
@@ -1095,16 +1090,28 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
&gb_loopback_debugfs_latency_ops);
gb->connection = connection;
connection->bundle->private = gb;
- retval = sysfs_create_groups(&connection->bundle->dev.kobj,
- loopback_groups);
- if (retval)
- goto out_sysfs;
+
+ gb->id = ida_simple_get(&loopback_ida, 0, 0, GFP_KERNEL);
+ if (gb->id < 0) {
+ retval = gb->id;
+ goto out_ida;
+ }
+
+ dev = device_create_with_groups(&loopback_class,
+ &connection->bundle->dev,
+ MKDEV(0, 0), gb, loopback_groups,
+ "gb_loopback%d", gb->id);
+ if (IS_ERR(dev)) {
+ retval = PTR_ERR(dev);
+ goto out_dev;
+ }
+ gb->dev = dev;
/* Allocate kfifo */
if (kfifo_alloc(&gb->kfifo_lat, kfifo_depth * sizeof(u32),
GFP_KERNEL)) {
retval = -ENOMEM;
- goto out_sysfs_conn;
+ goto out_conn;
}
if (kfifo_alloc(&gb->kfifo_ts, kfifo_depth * sizeof(struct timeval) * 2,
GFP_KERNEL)) {
@@ -1132,9 +1139,11 @@ out_kfifo1:
kfifo_free(&gb->kfifo_ts);
out_kfifo0:
kfifo_free(&gb->kfifo_lat);
-out_sysfs_conn:
- sysfs_remove_groups(&connection->bundle->dev.kobj, loopback_groups);
-out_sysfs:
+out_conn:
+ device_unregister(dev);
+out_dev:
+ ida_simple_remove(&loopback_ida, gb->id);
+out_ida:
debugfs_remove(gb->file);
connection->bundle->private = NULL;
out_kzalloc:
@@ -1155,8 +1164,6 @@ static void gb_loopback_connection_exit(struct gb_connection *connection)
kfifo_free(&gb->kfifo_lat);
kfifo_free(&gb->kfifo_ts);
gb_connection_latency_tag_disable(connection);
- sysfs_remove_groups(&connection->bundle->dev.kobj,
- loopback_groups);
debugfs_remove(gb->file);
spin_lock_irqsave(&gb_dev.lock, flags);
@@ -1164,6 +1171,9 @@ static void gb_loopback_connection_exit(struct gb_connection *connection)
list_del(&gb->entry);
spin_unlock_irqrestore(&gb_dev.lock, flags);
+ device_unregister(gb->dev);
+ ida_simple_remove(&loopback_ida, gb->id);
+
kfree(gb);
}
@@ -1186,10 +1196,19 @@ static int loopback_init(void)
spin_lock_init(&gb_dev.lock);
gb_dev.root = debugfs_create_dir("gb_loopback", NULL);
+ retval = class_register(&loopback_class);
+ if (retval)
+ goto err;
+
retval = gb_protocol_register(&loopback_protocol);
- if (!retval)
- return retval;
+ if (retval)
+ goto err_unregister;
+
+ return 0;
+err_unregister:
+ class_unregister(&loopback_class);
+err:
debugfs_remove_recursive(gb_dev.root);
return retval;
}
@@ -1199,6 +1218,8 @@ static void __exit loopback_exit(void)
{
debugfs_remove_recursive(gb_dev.root);
gb_protocol_deregister(&loopback_protocol);
+ class_unregister(&loopback_class);
+ ida_destroy(&loopback_ida);
}
module_exit(loopback_exit);