Commit 76ecf73e authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

greybus: Merge branch 'master' into svc

Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parents 03cb4fa9 782c3b73
...@@ -366,7 +366,8 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op) ...@@ -366,7 +366,8 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op)
request = op->request; request = op->request;
if (request->payload_size < sizeof(*event)) { if (request->payload_size < sizeof(*event)) {
dev_err(ggc->chip.dev, "short event received\n"); dev_err(ggc->chip.dev, "short event received (%zu < %zu)\n",
request->payload_size, sizeof(*event));
return -EINVAL; return -EINVAL;
} }
......
...@@ -51,6 +51,7 @@ struct gb_interface *gb_interface_find(struct greybus_host_device *hd, ...@@ -51,6 +51,7 @@ struct gb_interface *gb_interface_find(struct greybus_host_device *hd,
struct gb_interface *gb_interface_create(struct greybus_host_device *hd, struct gb_interface *gb_interface_create(struct greybus_host_device *hd,
u8 interface_id); u8 interface_id);
void gb_interface_destroy(struct gb_interface *intf);
int gb_interface_init(struct gb_interface *intf, u8 device_id); int gb_interface_init(struct gb_interface *intf, u8 device_id);
void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id); void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id);
void gb_interfaces_remove(struct greybus_host_device *hd); void gb_interfaces_remove(struct greybus_host_device *hd);
......
...@@ -57,6 +57,14 @@ ...@@ -57,6 +57,14 @@
#define U16_MAX ((u16)(~0U)) #define U16_MAX ((u16)(~0U))
#endif /* !U16_MAX */ #endif /* !U16_MAX */
#ifndef U32_MAX
#define U32_MAX ((u32)(~0U))
#endif /* !U32_MAX */
#ifndef U64_MAX
#define U64_MAX ((u64)(~0U))
#endif /* !U64_MAX */
/* /*
* The GPIO api sucks rocks in places, like removal, so work around their * The GPIO api sucks rocks in places, like removal, so work around their
* explicit requirements of catching the return value for kernels older than * explicit requirements of catching the return value for kernels older than
......
...@@ -23,11 +23,10 @@ ...@@ -23,11 +23,10 @@
#include "greybus.h" #include "greybus.h"
struct gb_loopback_stats { struct gb_loopback_stats {
u64 min; u32 min;
u64 max; u32 max;
u64 avg;
u64 sum; u64 sum;
u64 count; u32 count;
}; };
struct gb_loopback { struct gb_loopback {
...@@ -78,15 +77,14 @@ module_param(kfifo_depth, uint, 0444); ...@@ -78,15 +77,14 @@ module_param(kfifo_depth, uint, 0444);
define_get_version(gb_loopback, LOOPBACK); define_get_version(gb_loopback, LOOPBACK);
/* interface sysfs attributes */ /* interface sysfs attributes */
#define gb_loopback_ro_attr(field, type) \ #define gb_loopback_ro_attr(field) \
static ssize_t field##_show(struct device *dev, \ static ssize_t field##_show(struct device *dev, \
struct device_attribute *attr, \ struct device_attribute *attr, \
char *buf) \ char *buf) \
{ \ { \
struct gb_connection *connection = to_gb_connection(dev); \ struct gb_connection *connection = to_gb_connection(dev); \
struct gb_loopback *gb = \ struct gb_loopback *gb = connection->private; \
(struct gb_loopback *)connection->private; \ return sprintf(buf, "%u\n", gb->field); \
return sprintf(buf, "%"#type"\n", gb->field); \
} \ } \
static DEVICE_ATTR_RO(field) static DEVICE_ATTR_RO(field)
...@@ -96,16 +94,30 @@ static ssize_t name##_##field##_show(struct device *dev, \ ...@@ -96,16 +94,30 @@ static ssize_t name##_##field##_show(struct device *dev, \
char *buf) \ char *buf) \
{ \ { \
struct gb_connection *connection = to_gb_connection(dev); \ struct gb_connection *connection = to_gb_connection(dev); \
struct gb_loopback *gb = \ struct gb_loopback *gb = connection->private; \
(struct gb_loopback *)connection->private; \
return sprintf(buf, "%"#type"\n", gb->name.field); \ return sprintf(buf, "%"#type"\n", gb->name.field); \
} \ } \
static DEVICE_ATTR_RO(name##_##field) static DEVICE_ATTR_RO(name##_##field)
#define gb_loopback_ro_avg_attr(name) \
static ssize_t name##_avg_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct gb_connection *connection = to_gb_connection(dev); \
struct gb_loopback *gb = connection->private; \
struct gb_loopback_stats *stats = &gb->name; \
u32 count = stats->count ? stats->count : 1; \
u64 avg = stats->sum + count / 2; /* round closest */ \
u32 rem = do_div(avg, count); \
return sprintf(buf, "%llu.%06u\n", avg, 1000000 * rem / count); \
} \
static DEVICE_ATTR_RO(name##_avg)
#define gb_loopback_stats_attrs(field) \ #define gb_loopback_stats_attrs(field) \
gb_loopback_ro_stats_attr(field, min, llu); \ gb_loopback_ro_stats_attr(field, min, u); \
gb_loopback_ro_stats_attr(field, max, llu); \ gb_loopback_ro_stats_attr(field, max, u); \
gb_loopback_ro_stats_attr(field, avg, llu); gb_loopback_ro_avg_attr(field);
#define gb_loopback_attr(field, type) \ #define gb_loopback_attr(field, type) \
static ssize_t field##_show(struct device *dev, \ static ssize_t field##_show(struct device *dev, \
...@@ -113,8 +125,7 @@ static ssize_t field##_show(struct device *dev, \ ...@@ -113,8 +125,7 @@ static ssize_t field##_show(struct device *dev, \
char *buf) \ char *buf) \
{ \ { \
struct gb_connection *connection = to_gb_connection(dev); \ struct gb_connection *connection = to_gb_connection(dev); \
struct gb_loopback *gb = \ struct gb_loopback *gb = connection->private; \
(struct gb_loopback *)connection->private; \
return sprintf(buf, "%"#type"\n", gb->field); \ return sprintf(buf, "%"#type"\n", gb->field); \
} \ } \
static ssize_t field##_store(struct device *dev, \ static ssize_t field##_store(struct device *dev, \
...@@ -124,8 +135,7 @@ static ssize_t field##_store(struct device *dev, \ ...@@ -124,8 +135,7 @@ static ssize_t field##_store(struct device *dev, \
{ \ { \
int ret; \ int ret; \
struct gb_connection *connection = to_gb_connection(dev); \ struct gb_connection *connection = to_gb_connection(dev); \
struct gb_loopback *gb = \ struct gb_loopback *gb = connection->private; \
(struct gb_loopback *)connection->private; \
mutex_lock(&gb->mutex); \ mutex_lock(&gb->mutex); \
ret = sscanf(buf, "%"#type, &gb->field); \ ret = sscanf(buf, "%"#type, &gb->field); \
if (ret != 1) \ if (ret != 1) \
...@@ -175,15 +185,15 @@ gb_loopback_stats_attrs(requests_per_second); ...@@ -175,15 +185,15 @@ gb_loopback_stats_attrs(requests_per_second);
/* Quantity of data sent and received on this cport */ /* Quantity of data sent and received on this cport */
gb_loopback_stats_attrs(throughput); gb_loopback_stats_attrs(throughput);
/* Number of errors encountered during loop */ /* Number of errors encountered during loop */
gb_loopback_ro_attr(error, d); gb_loopback_ro_attr(error);
/* The current index of the for (i = 0; i < iteration_max; i++) loop */ /* The current index of the for (i = 0; i < iteration_max; i++) loop */
gb_loopback_ro_attr(iteration_count, u); gb_loopback_ro_attr(iteration_count);
/* /*
* Type of loopback message to send based on protocol type definitions * Type of loopback message to send based on protocol type definitions
* 0 => Don't send message * 0 => Don't send message
* 2 => Send ping message continuously (message without payload) * 2 => Send ping message continuously (message without payload)
* 3 => Send transer message continuously (message with payload, * 3 => Send transfer message continuously (message with payload,
* payload returned in response) * payload returned in response)
* 4 => Send a sink message (message with payload, no payload in response) * 4 => Send a sink message (message with payload, no payload in response)
*/ */
...@@ -344,7 +354,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation) ...@@ -344,7 +354,7 @@ static int gb_loopback_request_recv(u8 type, struct gb_operation *operation)
static void gb_loopback_reset_stats(struct gb_loopback *gb) static void gb_loopback_reset_stats(struct gb_loopback *gb)
{ {
struct gb_loopback_stats reset = { struct gb_loopback_stats reset = {
.min = 0xffffffff, .min = U32_MAX,
}; };
memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->latency, &reset, sizeof(struct gb_loopback_stats));
memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats)); memcpy(&gb->throughput, &reset, sizeof(struct gb_loopback_stats));
...@@ -352,7 +362,7 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) ...@@ -352,7 +362,7 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb)
sizeof(struct gb_loopback_stats)); sizeof(struct gb_loopback_stats));
} }
static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u64 val) static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val)
{ {
if (stats->min > val) if (stats->min > val)
stats->min = val; stats->min = val;
...@@ -360,8 +370,6 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u64 val) ...@@ -360,8 +370,6 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u64 val)
stats->max = val; stats->max = val;
stats->sum += val; stats->sum += val;
stats->count++; stats->count++;
stats->avg = stats->sum;
do_div(stats->avg, stats->count);
} }
static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency)
...@@ -410,7 +418,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) ...@@ -410,7 +418,7 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb)
do_div(tmp, NSEC_PER_USEC); do_div(tmp, NSEC_PER_USEC);
lat = tmp; lat = tmp;
/* Log latency stastic */ /* Log latency statistic */
gb_loopback_update_stats(&gb->latency, lat); gb_loopback_update_stats(&gb->latency, lat);
kfifo_in(&gb->kfifo, (unsigned char *)&lat, sizeof(lat)); kfifo_in(&gb->kfifo, (unsigned char *)&lat, sizeof(lat));
...@@ -423,7 +431,7 @@ static int gb_loopback_fn(void *data) ...@@ -423,7 +431,7 @@ static int gb_loopback_fn(void *data)
{ {
int error = 0; int error = 0;
int ms_wait; int ms_wait;
struct gb_loopback *gb = (struct gb_loopback *)data; struct gb_loopback *gb = data;
while (1) { while (1) {
if (!gb->type) if (!gb->type)
...@@ -482,19 +490,19 @@ static int gb_loopback_connection_init(struct gb_connection *connection) ...@@ -482,19 +490,19 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL); minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
if (minor < 0) { if (minor < 0) {
retval = minor; retval = minor;
goto out_free; goto out_sysfs;
} }
/* Check the version */ /* Check the version */
retval = get_version(gb); retval = get_version(gb);
if (retval) if (retval)
goto out_get_ver; goto out_minor;
/* Calculate maximum payload */ /* Calculate maximum payload */
gb->size_max = gb_operation_get_payload_size_max(connection); gb->size_max = gb_operation_get_payload_size_max(connection);
if (gb->size_max <= sizeof(struct gb_loopback_transfer_request)) { if (gb->size_max <= sizeof(struct gb_loopback_transfer_request)) {
retval = -EINVAL; retval = -EINVAL;
goto out_get_ver; goto out_minor;
} }
gb->size_max -= sizeof(struct gb_loopback_transfer_request); gb->size_max -= sizeof(struct gb_loopback_transfer_request);
...@@ -502,7 +510,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection) ...@@ -502,7 +510,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
if (kfifo_alloc(&gb->kfifo, kfifo_depth * sizeof(u32), if (kfifo_alloc(&gb->kfifo, kfifo_depth * sizeof(u32),
GFP_KERNEL)) { GFP_KERNEL)) {
retval = -ENOMEM; retval = -ENOMEM;
goto out_get_ver; goto out_minor;
} }
/* Create device entry */ /* Create device entry */
...@@ -510,13 +518,13 @@ static int gb_loopback_connection_init(struct gb_connection *connection) ...@@ -510,13 +518,13 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
cdev_init(&gb->cdev, &loopback_fops); cdev_init(&gb->cdev, &loopback_fops);
retval = cdev_add(&gb->cdev, gb->dev, 1); retval = cdev_add(&gb->cdev, gb->dev, 1);
if (retval) if (retval)
goto out_cdev; goto out_kfifo;
gb->device = device_create(loopback_class, &connection->dev, gb->dev, gb->device = device_create(loopback_class, &connection->dev, gb->dev,
gb, "gb!loopback%d", minor); gb, "gb!loopback%d", minor);
if (IS_ERR(gb->device)) { if (IS_ERR(gb->device)) {
retval = PTR_ERR(gb->device); retval = PTR_ERR(gb->device);
goto out_device; goto out_cdev;
} }
/* Fork worker thread */ /* Fork worker thread */
...@@ -525,21 +533,25 @@ static int gb_loopback_connection_init(struct gb_connection *connection) ...@@ -525,21 +533,25 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback");
if (IS_ERR(gb->task)) { if (IS_ERR(gb->task)) {
retval = PTR_ERR(gb->task); retval = PTR_ERR(gb->task);
goto out_kfifo; goto out_device;
} }
return 0; return 0;
out_device: out_device:
cdev_del(&gb->cdev); device_del(gb->device);
out_cdev: out_cdev:
ida_simple_remove(&minors, minor); cdev_del(&gb->cdev);
out_kfifo: out_kfifo:
kfifo_free(&gb->kfifo); kfifo_free(&gb->kfifo);
out_get_ver: out_minor:
ida_simple_remove(&minors, minor);
out_sysfs:
sysfs_remove_groups(&connection->dev.kobj, loopback_groups); sysfs_remove_groups(&connection->dev.kobj, loopback_groups);
out_free: out_free:
connection->private = NULL;
kfree(gb); kfree(gb);
return retval; return retval;
} }
...@@ -547,13 +559,14 @@ static void gb_loopback_connection_exit(struct gb_connection *connection) ...@@ -547,13 +559,14 @@ static void gb_loopback_connection_exit(struct gb_connection *connection)
{ {
struct gb_loopback *gb = connection->private; struct gb_loopback *gb = connection->private;
connection->private = NULL;
if (!IS_ERR_OR_NULL(gb->task)) if (!IS_ERR_OR_NULL(gb->task))
kthread_stop(gb->task); kthread_stop(gb->task);
cdev_del(&gb->cdev);
ida_simple_remove(&minors, MINOR(gb->dev));
device_del(gb->device); device_del(gb->device);
cdev_del(&gb->cdev);
kfifo_free(&gb->kfifo); kfifo_free(&gb->kfifo);
ida_simple_remove(&minors, MINOR(gb->dev));
sysfs_remove_groups(&connection->dev.kobj, loopback_groups); sysfs_remove_groups(&connection->dev.kobj, loopback_groups);
kfree(gb); kfree(gb);
} }
...@@ -584,7 +597,7 @@ static ssize_t loopback_read(struct file *file, char __user *buf, size_t count, ...@@ -584,7 +597,7 @@ static ssize_t loopback_read(struct file *file, char __user *buf, size_t count,
size_t fifo_len; size_t fifo_len;
int retval; int retval;
if (!count || count%sizeof(u32)) if (!count || count % sizeof(u32))
return -EINVAL; return -EINVAL;
mutex_lock(&gb->mutex); mutex_lock(&gb->mutex);
......
...@@ -121,7 +121,8 @@ static int gb_raw_receive(u8 type, struct gb_operation *op) ...@@ -121,7 +121,8 @@ static int gb_raw_receive(u8 type, struct gb_operation *op)
/* Verify size of payload */ /* Verify size of payload */
if (op->request->payload_size < sizeof(*receive)) { if (op->request->payload_size < sizeof(*receive)) {
dev_err(raw->device, "raw receive request too small\n"); dev_err(raw->device, "raw receive request too small (%zu < %zu)\n",
op->request->payload_size, sizeof(*receive));
return -EINVAL; return -EINVAL;
} }
receive = op->request->payload; receive = op->request->payload;
......
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