diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index c1943f2b83fb..8524ce128738 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -36,29 +36,11 @@ struct gb_loopback_stats { struct gb_loopback_device { struct dentry *root; - struct dentry *file; u32 count; + size_t size_max; - struct kfifo kfifo; struct mutex mutex; struct list_head list; - wait_queue_head_t wq; - - int type; - u32 mask; - u32 size; - u32 iteration_max; - u32 iteration_count; - size_t size_max; - int ms_wait; - u32 error; - - /* Overall stats */ - struct gb_loopback_stats latency; - struct gb_loopback_stats throughput; - struct gb_loopback_stats requests_per_second; - struct gb_loopback_stats apbridge_unipro_latency; - struct gb_loopback_stats gpbridge_firmware_latency; }; static struct gb_loopback_device gb_dev; @@ -72,6 +54,7 @@ struct gb_loopback { struct mutex mutex; struct task_struct *task; struct list_head entry; + wait_queue_head_t wq; /* Per connection stats */ struct gb_loopback_stats latency; @@ -80,10 +63,15 @@ struct gb_loopback { struct gb_loopback_stats apbridge_unipro_latency; struct gb_loopback_stats gpbridge_firmware_latency; - u32 lbid; + int type; + u32 mask; + u32 size; + u32 iteration_max; u32 iteration_count; - u64 elapsed_nsecs; + int ms_wait; u32 error; + u32 lbid; + u64 elapsed_nsecs; u32 apbridge_latency_ts; u32 gpbridge_latency_ts; }; @@ -99,42 +87,34 @@ module_param(kfifo_depth, uint, 0444); #define GB_LOOPBACK_MS_WAIT_MAX 1000 /* interface sysfs attributes */ -#define gb_loopback_ro_attr(field, pfx, conn) \ -static ssize_t field##_##pfx##_show(struct device *dev, \ +#define gb_loopback_ro_attr(field) \ +static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ struct gb_bundle *bundle; \ struct gb_loopback *gb; \ - if (conn) { \ - bundle = to_gb_bundle(dev); \ - gb = bundle->private; \ - return sprintf(buf, "%u\n", gb->field); \ - } else { \ - return sprintf(buf, "%u\n", gb_dev.field); \ - } \ + bundle = to_gb_bundle(dev); \ + gb = bundle->private; \ + return sprintf(buf, "%u\n", gb->field); \ } \ -static DEVICE_ATTR_RO(field##_##pfx) +static DEVICE_ATTR_RO(field) -#define gb_loopback_ro_stats_attr(name, field, type, pfx, conn) \ -static ssize_t name##_##field##_##pfx##_show(struct device *dev, \ +#define gb_loopback_ro_stats_attr(name, field, type) \ +static ssize_t name##_##field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ struct gb_bundle *bundle; \ struct gb_loopback *gb; \ - if (conn) { \ - bundle = to_gb_bundle(dev); \ - gb = bundle->private; \ - return sprintf(buf, "%"#type"\n", gb->name.field); \ - } else { \ - return sprintf(buf, "%"#type"\n", gb_dev.name.field); \ - } \ + bundle = to_gb_bundle(dev); \ + gb = bundle->private; \ + return sprintf(buf, "%"#type"\n", gb->name.field); \ } \ -static DEVICE_ATTR_RO(name##_##field##_##pfx) +static DEVICE_ATTR_RO(name##_##field) -#define gb_loopback_ro_avg_attr(name, pfx, conn) \ -static ssize_t name##_avg_##pfx##_show(struct device *dev, \ +#define gb_loopback_ro_avg_attr(name) \ +static ssize_t name##_avg_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ @@ -143,24 +123,20 @@ static ssize_t name##_avg_##pfx##_show(struct device *dev, \ struct gb_loopback *gb; \ u64 avg; \ u32 count, rem; \ - if (conn) { \ - bundle = to_gb_bundle(dev); \ - gb = bundle->private; \ - stats = &gb->name; \ - } else { \ - stats = &gb_dev.name; \ - } \ + bundle = to_gb_bundle(dev); \ + gb = bundle->private; \ + stats = &gb->name; \ count = stats->count ? stats->count : 1; \ avg = stats->sum + count / 2; /* round closest */ \ rem = do_div(avg, count); \ return sprintf(buf, "%llu.%06u\n", avg, 1000000 * rem / count); \ } \ -static DEVICE_ATTR_RO(name##_avg_##pfx) +static DEVICE_ATTR_RO(name##_avg) -#define gb_loopback_stats_attrs(field, pfx, conn) \ - gb_loopback_ro_stats_attr(field, min, u, pfx, conn); \ - gb_loopback_ro_stats_attr(field, max, u, pfx, conn); \ - gb_loopback_ro_avg_attr(field, pfx, conn) +#define gb_loopback_stats_attrs(field) \ + gb_loopback_ro_stats_attr(field, min, u); \ + gb_loopback_ro_stats_attr(field, max, u); \ + gb_loopback_ro_avg_attr(field) #define gb_loopback_attr(field, type) \ static ssize_t field##_show(struct device *dev, \ @@ -178,13 +154,14 @@ static ssize_t field##_store(struct device *dev, \ { \ int ret; \ struct gb_bundle *bundle = to_gb_bundle(dev); \ - mutex_lock(&gb_dev.mutex); \ + struct gb_loopback *gb = bundle->private; \ + mutex_lock(&gb->mutex); \ ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ len = -EINVAL; \ else \ - gb_loopback_check_attr(&gb_dev, bundle); \ - mutex_unlock(&gb_dev.mutex); \ + gb_loopback_check_attr(gb, bundle); \ + mutex_unlock(&gb->mutex); \ return len; \ } \ static DEVICE_ATTR_RW(field) @@ -194,7 +171,9 @@ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - return sprintf(buf, "%u\n", gb_dev.field); \ + struct gb_bundle *bundle = to_gb_bundle(dev); \ + struct gb_loopback *gb = bundle->private; \ + return sprintf(buf, "%u\n", gb->field); \ } \ static DEVICE_ATTR_RO(field) @@ -203,7 +182,9 @@ static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - return sprintf(buf, "%"#type"\n", gb_dev.field); \ + struct gb_bundle *bundle = to_gb_bundle(dev); \ + struct gb_loopback *gb = bundle->private; \ + return sprintf(buf, "%"#type"\n", gb->field); \ } \ static ssize_t field##_store(struct device *dev, \ struct device_attribute *attr, \ @@ -212,76 +193,63 @@ static ssize_t field##_store(struct device *dev, \ { \ int ret; \ struct gb_bundle *bundle = to_gb_bundle(dev); \ - mutex_lock(&gb_dev.mutex); \ - ret = sscanf(buf, "%"#type, &gb_dev.field); \ + struct gb_loopback *gb = bundle->private; \ + mutex_lock(&gb->mutex); \ + ret = sscanf(buf, "%"#type, &gb->field); \ if (ret != 1) \ len = -EINVAL; \ else \ - gb_loopback_check_attr(&gb_dev, bundle); \ - mutex_unlock(&gb_dev.mutex); \ + gb_loopback_check_attr(gb, bundle); \ + mutex_unlock(&gb->mutex); \ return len; \ } \ static DEVICE_ATTR_RW(field) -static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev); -static void gb_loopback_check_attr(struct gb_loopback_device *gb_dev, +static void gb_loopback_reset_stats(struct gb_loopback *gb); +static void gb_loopback_check_attr(struct gb_loopback *gb, struct gb_bundle *bundle) { - struct gb_loopback *gb; + if (gb->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) + gb->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; + if (gb->size > gb_dev.size_max) + gb->size = gb_dev.size_max; + gb->iteration_count = 0; + gb->error = 0; - if (gb_dev->ms_wait > GB_LOOPBACK_MS_WAIT_MAX) - gb_dev->ms_wait = GB_LOOPBACK_MS_WAIT_MAX; - if (gb_dev->size > gb_dev->size_max) - gb_dev->size = gb_dev->size_max; - gb_dev->iteration_count = 0; - gb_dev->error = 0; - - list_for_each_entry(gb, &gb_dev->list, entry) { - mutex_lock(&gb->mutex); - gb->iteration_count = 0; - gb->error = 0; - if (kfifo_depth < gb_dev->iteration_max) { - dev_warn(&bundle->dev, - "cannot log bytes %u kfifo_depth %u\n", - gb_dev->iteration_max, kfifo_depth); - } - kfifo_reset_out(&gb->kfifo_lat); - kfifo_reset_out(&gb->kfifo_ts); - mutex_unlock(&gb->mutex); + if (kfifo_depth < gb->iteration_max) { + dev_warn(&bundle->dev, + "cannot log bytes %u kfifo_depth %u\n", + gb->iteration_max, kfifo_depth); } + kfifo_reset_out(&gb->kfifo_lat); + kfifo_reset_out(&gb->kfifo_ts); - switch (gb_dev->type) { + switch (gb->type) { case GB_LOOPBACK_TYPE_PING: case GB_LOOPBACK_TYPE_TRANSFER: case GB_LOOPBACK_TYPE_SINK: - kfifo_reset_out(&gb_dev->kfifo); - gb_loopback_reset_stats(gb_dev); - wake_up(&gb_dev->wq); + gb_loopback_reset_stats(gb); + wake_up(&gb->wq); break; default: - gb_dev->type = 0; + gb->type = 0; break; } } /* Time to send and receive one message */ -gb_loopback_stats_attrs(latency, dev, false); -gb_loopback_stats_attrs(latency, con, true); +gb_loopback_stats_attrs(latency); /* Number of requests sent per second on this cport */ -gb_loopback_stats_attrs(requests_per_second, dev, false); -gb_loopback_stats_attrs(requests_per_second, con, true); +gb_loopback_stats_attrs(requests_per_second); /* Quantity of data sent and received on this cport */ -gb_loopback_stats_attrs(throughput, dev, false); -gb_loopback_stats_attrs(throughput, con, true); +gb_loopback_stats_attrs(throughput); /* Latency across the UniPro link from APBridge's perspective */ -gb_loopback_stats_attrs(apbridge_unipro_latency, dev, false); -gb_loopback_stats_attrs(apbridge_unipro_latency, con, true); +gb_loopback_stats_attrs(apbridge_unipro_latency); /* Firmware induced overhead in the GPBridge */ -gb_loopback_stats_attrs(gpbridge_firmware_latency, dev, false); -gb_loopback_stats_attrs(gpbridge_firmware_latency, con, true); +gb_loopback_stats_attrs(gpbridge_firmware_latency); + /* Number of errors encountered during loop */ -gb_loopback_ro_attr(error, dev, false); -gb_loopback_ro_attr(error, con, true); +gb_loopback_ro_attr(error); /* * Type of loopback message to send based on protocol type definitions @@ -303,53 +271,32 @@ gb_dev_loopback_ro_attr(iteration_count, false); /* A bit-mask of destination connecitons to include in the test run */ gb_dev_loopback_rw_attr(mask, u); -static struct attribute *loopback_dev_attrs[] = { - &dev_attr_latency_min_dev.attr, - &dev_attr_latency_max_dev.attr, - &dev_attr_latency_avg_dev.attr, - &dev_attr_requests_per_second_min_dev.attr, - &dev_attr_requests_per_second_max_dev.attr, - &dev_attr_requests_per_second_avg_dev.attr, - &dev_attr_throughput_min_dev.attr, - &dev_attr_throughput_max_dev.attr, - &dev_attr_throughput_avg_dev.attr, - &dev_attr_apbridge_unipro_latency_min_dev.attr, - &dev_attr_apbridge_unipro_latency_max_dev.attr, - &dev_attr_apbridge_unipro_latency_avg_dev.attr, - &dev_attr_gpbridge_firmware_latency_min_dev.attr, - &dev_attr_gpbridge_firmware_latency_max_dev.attr, - &dev_attr_gpbridge_firmware_latency_avg_dev.attr, +static struct attribute *loopback_attrs[] = { + &dev_attr_latency_min.attr, + &dev_attr_latency_max.attr, + &dev_attr_latency_avg.attr, + &dev_attr_requests_per_second_min.attr, + &dev_attr_requests_per_second_max.attr, + &dev_attr_requests_per_second_avg.attr, + &dev_attr_throughput_min.attr, + &dev_attr_throughput_max.attr, + &dev_attr_throughput_avg.attr, + &dev_attr_apbridge_unipro_latency_min.attr, + &dev_attr_apbridge_unipro_latency_max.attr, + &dev_attr_apbridge_unipro_latency_avg.attr, + &dev_attr_gpbridge_firmware_latency_min.attr, + &dev_attr_gpbridge_firmware_latency_max.attr, + &dev_attr_gpbridge_firmware_latency_avg.attr, &dev_attr_type.attr, &dev_attr_size.attr, &dev_attr_ms_wait.attr, &dev_attr_iteration_count.attr, &dev_attr_iteration_max.attr, &dev_attr_mask.attr, - &dev_attr_error_dev.attr, + &dev_attr_error.attr, NULL, }; -ATTRIBUTE_GROUPS(loopback_dev); - -static struct attribute *loopback_con_attrs[] = { - &dev_attr_latency_min_con.attr, - &dev_attr_latency_max_con.attr, - &dev_attr_latency_avg_con.attr, - &dev_attr_requests_per_second_min_con.attr, - &dev_attr_requests_per_second_max_con.attr, - &dev_attr_requests_per_second_avg_con.attr, - &dev_attr_throughput_min_con.attr, - &dev_attr_throughput_max_con.attr, - &dev_attr_throughput_avg_con.attr, - &dev_attr_apbridge_unipro_latency_min_con.attr, - &dev_attr_apbridge_unipro_latency_max_con.attr, - &dev_attr_apbridge_unipro_latency_avg_con.attr, - &dev_attr_gpbridge_firmware_latency_min_con.attr, - &dev_attr_gpbridge_firmware_latency_max_con.attr, - &dev_attr_gpbridge_firmware_latency_avg_con.attr, - &dev_attr_error_con.attr, - NULL, -}; -ATTRIBUTE_GROUPS(loopback_con); +ATTRIBUTE_GROUPS(loopback); static u32 gb_loopback_nsec_to_usec_latency(u64 elapsed_nsecs) { @@ -385,11 +332,6 @@ static void gb_loopback_push_latency_ts(struct gb_loopback *gb, kfifo_in(&gb->kfifo_ts, (unsigned char *)te, sizeof(*te)); } -static int gb_loopback_active(struct gb_loopback *gb) -{ - return (gb_dev.mask == 0 || (gb_dev.mask & gb->lbid)); -} - static int gb_loopback_operation_sync(struct gb_loopback *gb, int type, void *request, int request_size, void *response, int response_size) @@ -550,37 +492,32 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) } } -static void gb_loopback_reset_stats(struct gb_loopback_device *gb_dev) +static void gb_loopback_reset_stats(struct gb_loopback *gb) { struct gb_loopback_stats reset = { .min = U32_MAX, }; - struct gb_loopback *gb; /* Reset per-connection stats */ - list_for_each_entry(gb, &gb_dev->list, entry) { - mutex_lock(&gb->mutex); - memcpy(&gb->latency, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->throughput, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->requests_per_second, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->apbridge_unipro_latency, &reset, - sizeof(struct gb_loopback_stats)); - memcpy(&gb->gpbridge_firmware_latency, &reset, - sizeof(struct gb_loopback_stats)); - mutex_unlock(&gb->mutex); - } + memcpy(&gb->latency, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->throughput, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->requests_per_second, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->apbridge_unipro_latency, &reset, + sizeof(struct gb_loopback_stats)); + memcpy(&gb->gpbridge_firmware_latency, &reset, + sizeof(struct gb_loopback_stats)); /* Reset aggregate stats */ - memcpy(&gb_dev->latency, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb_dev->throughput, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb_dev->requests_per_second, &reset, + memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); + memcpy(&gb->requests_per_second, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb_dev->apbridge_unipro_latency, &reset, + memcpy(&gb->apbridge_unipro_latency, &reset, sizeof(struct gb_loopback_stats)); - memcpy(&gb_dev->gpbridge_firmware_latency, &reset, + memcpy(&gb->gpbridge_firmware_latency, &reset, sizeof(struct gb_loopback_stats)); } @@ -599,7 +536,6 @@ static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) u32 req = USEC_PER_SEC; do_div(req, latency); - gb_loopback_update_stats(&gb_dev.requests_per_second, req); gb_loopback_update_stats(&gb->requests_per_second, req); } @@ -608,17 +544,17 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) u32 throughput; u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; - switch (gb_dev.type) { + switch (gb->type) { case GB_LOOPBACK_TYPE_PING: break; case GB_LOOPBACK_TYPE_SINK: aggregate_size += sizeof(struct gb_loopback_transfer_request) + - gb_dev.size; + gb->size; break; case GB_LOOPBACK_TYPE_TRANSFER: aggregate_size += sizeof(struct gb_loopback_transfer_request) + sizeof(struct gb_loopback_transfer_response) + - gb_dev.size * 2; + gb->size * 2; break; default: return; @@ -628,65 +564,9 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) throughput = USEC_PER_SEC; do_div(throughput, latency); throughput *= aggregate_size; - gb_loopback_update_stats(&gb_dev.throughput, throughput); gb_loopback_update_stats(&gb->throughput, throughput); } -static int gb_loopback_calculate_aggregate_stats(void) -{ - struct gb_loopback *gb; - struct timeval ts; - struct timeval te; - u64 t1, t2; - u64 ts_min; - u64 te_max; - u64 elapsed_nsecs; - u32 lat; - int i, latched; - int rollover = 0; - - for (i = 0; i < gb_dev.iteration_max; i++) { - latched = 0; - ts_min = 0; - te_max = 0; - list_for_each_entry(gb, &gb_dev.list, entry) { - if (!gb_loopback_active(gb)) - continue; - if (kfifo_out(&gb->kfifo_ts, &ts, sizeof(ts)) < sizeof(ts)) - goto error; - if (kfifo_out(&gb->kfifo_ts, &te, sizeof(te)) < sizeof(te)) - goto error; - t1 = timeval_to_ns(&ts); - t2 = timeval_to_ns(&te); - - /* minimum timestamp is always what we want */ - if (latched == 0 || t1 < ts_min) - ts_min = t1; - - /* maximum timestamp needs to handle rollover */ - if (t2 > t1) { - if (latched == 0 || t2 > te_max) - te_max = t2; - } else { - if (latched == 0 || rollover == 0) - te_max = t2; - if (rollover == 1 && t2 > te_max) - te_max = t2; - rollover = 1; - } - latched = 1; - } - /* Calculate the aggregate timestamp */ - elapsed_nsecs = __gb_loopback_calc_latency(ts_min, te_max); - lat = gb_loopback_nsec_to_usec_latency(elapsed_nsecs); - kfifo_in(&gb_dev.kfifo, (unsigned char *)&lat, sizeof(lat)); - } - return 0; -error: - kfifo_reset_out(&gb_dev.kfifo); - return -ENOMEM; -} - static void gb_loopback_calculate_stats(struct gb_loopback *gb) { u32 lat; @@ -695,7 +575,6 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) lat = gb_loopback_nsec_to_usec_latency(gb->elapsed_nsecs); /* Log latency stastic */ - gb_loopback_update_stats(&gb_dev.latency, lat); gb_loopback_update_stats(&gb->latency, lat); /* Raw latency log on a per thread basis */ @@ -706,12 +585,8 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) gb_loopback_requests_update(gb, lat); /* Log the firmware supplied latency values */ - gb_loopback_update_stats(&gb_dev.apbridge_unipro_latency, - gb->apbridge_latency_ts); gb_loopback_update_stats(&gb->apbridge_unipro_latency, gb->apbridge_latency_ts); - gb_loopback_update_stats(&gb_dev.gpbridge_firmware_latency, - gb->gpbridge_latency_ts); gb_loopback_update_stats(&gb->gpbridge_firmware_latency, gb->gpbridge_latency_ts); } @@ -722,56 +597,29 @@ static int gb_loopback_fn(void *data) int ms_wait = 0; int type; u32 size; - u32 low_count; struct gb_loopback *gb = data; - struct gb_loopback *gb_list; while (1) { - if (!gb_dev.type) - wait_event_interruptible(gb_dev.wq, gb_dev.type || + if (!gb->type) + wait_event_interruptible(gb->wq, gb->type || kthread_should_stop()); if (kthread_should_stop()) break; - mutex_lock(&gb_dev.mutex); - if (!gb_loopback_active(gb)) { - ms_wait = 100; - goto unlock_continue; - } - if (gb_dev.iteration_max) { - /* Determine overall lowest count */ - low_count = gb->iteration_count; - list_for_each_entry(gb_list, &gb_dev.list, entry) { - if (!gb_loopback_active(gb_list)) - continue; - if (gb_list->iteration_count < low_count) - low_count = gb_list->iteration_count; - } - /* All threads achieved at least low_count iterations */ - if (gb_dev.iteration_count < low_count) { - gb_dev.iteration_count = low_count; - sysfs_notify(&gb->connection->bundle->dev.kobj, - NULL, "iteration_count"); - } - /* Optionally terminate */ - if (gb_dev.iteration_count == gb_dev.iteration_max) { - gb_loopback_calculate_aggregate_stats(); - gb_dev.type = 0; - goto unlock_continue; - } - } - size = gb_dev.size; - ms_wait = gb_dev.ms_wait; - type = gb_dev.type; - mutex_unlock(&gb_dev.mutex); - mutex_lock(&gb->mutex); - if (gb->iteration_count >= gb_dev.iteration_max) { - /* If this thread finished before siblings then sleep */ - ms_wait = 1; + + sysfs_notify(&gb->connection->bundle->dev.kobj, + NULL, "iteration_count"); + + /* Optionally terminate */ + if (gb->iteration_count == gb->iteration_max) { + gb->type = 0; mutex_unlock(&gb->mutex); - goto sleep; + continue; } + size = gb->size; + ms_wait = gb->ms_wait; + type = gb->type; mutex_unlock(&gb->mutex); /* Else operations to perform */ @@ -782,20 +630,12 @@ static int gb_loopback_fn(void *data) else if (type == GB_LOOPBACK_TYPE_SINK) error = gb_loopback_sink(gb, size); - mutex_lock(&gb_dev.mutex); - mutex_lock(&gb->mutex); - - if (error) { - gb_dev.error++; + if (error) gb->error++; - } + gb_loopback_calculate_stats(gb); gb->iteration_count++; - mutex_unlock(&gb->mutex); -unlock_continue: - mutex_unlock(&gb_dev.mutex); -sleep: if (ms_wait) msleep(ms_wait); } @@ -846,27 +686,6 @@ static const struct file_operations gb_loopback_debugfs_latency_ops = { .release = single_release, }; -static int gb_loopback_dbgfs_dev_latency_show(struct seq_file *s, void *unused) -{ - struct gb_loopback_device *gb_dev = s->private; - - return gb_loopback_dbgfs_latency_show_common(s, &gb_dev->kfifo, - &gb_dev->mutex); -} - -static int gb_loopback_dev_latency_open(struct inode *inode, struct file *file) -{ - return single_open(file, gb_loopback_dbgfs_dev_latency_show, - inode->i_private); -} - -static const struct file_operations gb_loopback_debugfs_dev_latency_ops = { - .open = gb_loopback_dev_latency_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - static int gb_loopback_bus_id_compare(void *priv, struct list_head *lha, struct list_head *lhb) { @@ -912,31 +731,22 @@ static int gb_loopback_connection_init(struct gb_connection *connection) struct gb_loopback *gb; int retval; char name[DEBUGFS_NAMELEN]; - struct kobject *kobj = &connection->bundle->dev.kobj; gb = kzalloc(sizeof(*gb), GFP_KERNEL); if (!gb) return -ENOMEM; - gb_loopback_reset_stats(&gb_dev); - /* If this is the first connection - create a per-bus entry */ + init_waitqueue_head(&gb->wq); + gb_loopback_reset_stats(gb); + mutex_lock(&gb_dev.mutex); if (!gb_dev.count) { - snprintf(name, sizeof(name), "raw_latency_%d", - connection->bundle->intf->hd->bus_id); - gb_dev.file = debugfs_create_file(name, S_IFREG | S_IRUGO, - gb_dev.root, &gb_dev, - &gb_loopback_debugfs_dev_latency_ops); - retval = sysfs_create_groups(kobj, loopback_dev_groups); - if (retval) - goto out_sysfs; - /* Calculate maximum payload */ gb_dev.size_max = gb_operation_get_payload_size_max(connection); if (gb_dev.size_max <= sizeof(struct gb_loopback_transfer_request)) { retval = -EINVAL; - goto out_sysfs_dev; + goto out_sysfs; } gb_dev.size_max -= sizeof(struct gb_loopback_transfer_request); } @@ -949,9 +759,9 @@ static int gb_loopback_connection_init(struct gb_connection *connection) gb->connection = connection; connection->bundle->private = gb; retval = sysfs_create_groups(&connection->bundle->dev.kobj, - loopback_con_groups); + loopback_groups); if (retval) - goto out_sysfs_dev; + goto out_sysfs; /* Allocate kfifo */ if (kfifo_alloc(&gb->kfifo_lat, kfifo_depth * sizeof(u32), @@ -984,15 +794,10 @@ out_kfifo1: out_kfifo0: kfifo_free(&gb->kfifo_lat); out_sysfs_conn: - sysfs_remove_groups(&connection->bundle->dev.kobj, loopback_con_groups); -out_sysfs_dev: - if (!gb_dev.count) { - sysfs_remove_groups(kobj, loopback_dev_groups); - debugfs_remove(gb_dev.file); - } + sysfs_remove_groups(&connection->bundle->dev.kobj, loopback_groups); +out_sysfs: debugfs_remove(gb->file); connection->bundle->private = NULL; -out_sysfs: mutex_unlock(&gb_dev.mutex); kfree(gb); @@ -1002,7 +807,6 @@ out_sysfs: static void gb_loopback_connection_exit(struct gb_connection *connection) { struct gb_loopback *gb = connection->bundle->private; - struct kobject *kobj = &connection->bundle->dev.kobj; if (!IS_ERR_OR_NULL(gb->task)) kthread_stop(gb->task); @@ -1014,12 +818,8 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) kfifo_free(&gb->kfifo_ts); gb_connection_latency_tag_disable(connection); gb_dev.count--; - if (!gb_dev.count) { - sysfs_remove_groups(kobj, loopback_dev_groups); - debugfs_remove(gb_dev.file); - } sysfs_remove_groups(&connection->bundle->dev.kobj, - loopback_con_groups); + loopback_groups); debugfs_remove(gb->file); list_del(&gb->entry); mutex_unlock(&gb_dev.mutex); @@ -1040,21 +840,14 @@ static int loopback_init(void) { int retval; - init_waitqueue_head(&gb_dev.wq); INIT_LIST_HEAD(&gb_dev.list); mutex_init(&gb_dev.mutex); gb_dev.root = debugfs_create_dir("gb_loopback", NULL); - if (kfifo_alloc(&gb_dev.kfifo, kfifo_depth * sizeof(u32), GFP_KERNEL)) { - retval = -ENOMEM; - goto error_debugfs; - } - retval = gb_protocol_register(&loopback_protocol); if (!retval) return retval; -error_debugfs: debugfs_remove_recursive(gb_dev.root); return retval; } @@ -1063,7 +856,6 @@ module_init(loopback_init); static void __exit loopback_exit(void) { debugfs_remove_recursive(gb_dev.root); - kfifo_free(&gb_dev.kfifo); gb_protocol_deregister(&loopback_protocol); } module_exit(loopback_exit);