Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

greybus: Merge branch 'master' into svc

parents 03cb4fa9 782c3b73
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -366,7 +366,8 @@ static int gb_gpio_request_recv(u8 type, struct gb_operation *op)
	request = op->request;

	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;
	}

+1 −0
Original line number Diff line number Diff line
@@ -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,
					 u8 interface_id);
void gb_interface_destroy(struct gb_interface *intf);
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_interfaces_remove(struct greybus_host_device *hd);
+8 −0
Original line number Diff line number Diff line
@@ -57,6 +57,14 @@
#define U16_MAX	((u16)(~0U))
#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
 * explicit requirements of catching the return value for kernels older than
+52 −39
Original line number Diff line number Diff line
@@ -23,11 +23,10 @@
#include "greybus.h"

struct gb_loopback_stats {
	u64 min;
	u64 max;
	u64 avg;
	u32 min;
	u32 max;
	u64 sum;
	u64 count;
	u32 count;
};

struct gb_loopback {
@@ -78,15 +77,14 @@ module_param(kfifo_depth, uint, 0444);
define_get_version(gb_loopback, LOOPBACK);

/* interface sysfs attributes */
#define gb_loopback_ro_attr(field, type)				\
#define gb_loopback_ro_attr(field)					\
static ssize_t field##_show(struct device *dev,				\
			    struct device_attribute *attr,		\
			    char *buf)					\
{									\
	struct gb_connection *connection = to_gb_connection(dev);	\
	struct gb_loopback *gb =					\
		(struct gb_loopback *)connection->private;		\
	return sprintf(buf, "%"#type"\n", gb->field);			\
	struct gb_loopback *gb = connection->private;			\
	return sprintf(buf, "%u\n", gb->field);				\
}									\
static DEVICE_ATTR_RO(field)

@@ -96,16 +94,30 @@ static ssize_t name##_##field##_show(struct device *dev, \
			    char *buf)					\
{									\
	struct gb_connection *connection = to_gb_connection(dev);	\
	struct gb_loopback *gb =					\
		(struct gb_loopback *)connection->private;		\
	struct gb_loopback *gb = connection->private;			\
	return sprintf(buf, "%"#type"\n", gb->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)					\
	gb_loopback_ro_stats_attr(field, min, llu);			\
	gb_loopback_ro_stats_attr(field, max, llu);			\
	gb_loopback_ro_stats_attr(field, avg, llu);
	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,				\
@@ -113,8 +125,7 @@ static ssize_t field##_show(struct device *dev, \
			    char *buf)					\
{									\
	struct gb_connection *connection = to_gb_connection(dev);	\
	struct gb_loopback *gb =					\
		(struct gb_loopback *)connection->private;		\
	struct gb_loopback *gb = connection->private;			\
	return sprintf(buf, "%"#type"\n", gb->field);			\
}									\
static ssize_t field##_store(struct device *dev,			\
@@ -124,8 +135,7 @@ static ssize_t field##_store(struct device *dev, \
{									\
	int ret;							\
	struct gb_connection *connection = to_gb_connection(dev);	\
	struct gb_loopback *gb =					\
		(struct gb_loopback *)connection->private;		\
	struct gb_loopback *gb = connection->private;			\
	mutex_lock(&gb->mutex);						\
	ret = sscanf(buf, "%"#type, &gb->field);			\
	if (ret != 1)							\
@@ -175,15 +185,15 @@ gb_loopback_stats_attrs(requests_per_second);
/* Quantity of data sent and received on this cport */
gb_loopback_stats_attrs(throughput);
/* 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 */
gb_loopback_ro_attr(iteration_count, u);
gb_loopback_ro_attr(iteration_count);

/*
 * Type of loopback message to send based on protocol type definitions
 * 0 => Don't send message
 * 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)
 * 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)
static void gb_loopback_reset_stats(struct gb_loopback *gb)
{
	struct gb_loopback_stats reset = {
		.min = 0xffffffff,
		.min = U32_MAX,
	};
	memcpy(&gb->latency, &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)
	       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)
		stats->min = val;
@@ -360,8 +370,6 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u64 val)
		stats->max = val;
	stats->sum += val;
	stats->count++;
	stats->avg = stats->sum;
	do_div(stats->avg, stats->count);
}

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)
	do_div(tmp, NSEC_PER_USEC);
	lat = tmp;

	/* Log latency stastic */
	/* Log latency statistic */
	gb_loopback_update_stats(&gb->latency, lat);
	kfifo_in(&gb->kfifo, (unsigned char *)&lat, sizeof(lat));

@@ -423,7 +431,7 @@ static int gb_loopback_fn(void *data)
{
	int error = 0;
	int ms_wait;
	struct gb_loopback *gb = (struct gb_loopback *)data;
	struct gb_loopback *gb = data;

	while (1) {
		if (!gb->type)
@@ -482,19 +490,19 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
	minor = ida_simple_get(&minors, 0, 0, GFP_KERNEL);
	if (minor < 0) {
		retval = minor;
		goto out_free;
		goto out_sysfs;
	}

	/* Check the version */
	retval = get_version(gb);
	if (retval)
		goto out_get_ver;
		goto out_minor;

	/* Calculate maximum payload */
	gb->size_max = gb_operation_get_payload_size_max(connection);
	if (gb->size_max <= sizeof(struct gb_loopback_transfer_request)) {
		retval = -EINVAL;
		goto out_get_ver;
		goto out_minor;
	}
	gb->size_max -= sizeof(struct gb_loopback_transfer_request);

@@ -502,7 +510,7 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
	if (kfifo_alloc(&gb->kfifo, kfifo_depth * sizeof(u32),
			  GFP_KERNEL)) {
		retval = -ENOMEM;
		goto out_get_ver;
		goto out_minor;
	}

	/* Create device entry */
@@ -510,13 +518,13 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
	cdev_init(&gb->cdev, &loopback_fops);
	retval = cdev_add(&gb->cdev, gb->dev, 1);
	if (retval)
		goto out_cdev;
		goto out_kfifo;

	gb->device = device_create(loopback_class, &connection->dev, gb->dev,
				   gb, "gb!loopback%d", minor);
	if (IS_ERR(gb->device)) {
		retval = PTR_ERR(gb->device);
		goto out_device;
		goto out_cdev;
	}

	/* Fork worker thread */
@@ -525,21 +533,25 @@ static int gb_loopback_connection_init(struct gb_connection *connection)
	gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback");
	if (IS_ERR(gb->task)) {
		retval = PTR_ERR(gb->task);
		goto out_kfifo;
		goto out_device;
	}

	return 0;

out_device:
	cdev_del(&gb->cdev);
	device_del(gb->device);
out_cdev:
	ida_simple_remove(&minors, minor);
	cdev_del(&gb->cdev);
out_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);
out_free:
	connection->private = NULL;
	kfree(gb);

	return retval;
}

@@ -547,13 +559,14 @@ static void gb_loopback_connection_exit(struct gb_connection *connection)
{
	struct gb_loopback *gb = connection->private;

	connection->private = NULL;
	if (!IS_ERR_OR_NULL(gb->task))
		kthread_stop(gb->task);

	cdev_del(&gb->cdev);
	ida_simple_remove(&minors, MINOR(gb->dev));
	device_del(gb->device);
	cdev_del(&gb->cdev);
	kfifo_free(&gb->kfifo);
	ida_simple_remove(&minors, MINOR(gb->dev));
	sysfs_remove_groups(&connection->dev.kobj, loopback_groups);
	kfree(gb);
}
+2 −1
Original line number Diff line number Diff line
@@ -121,7 +121,8 @@ static int gb_raw_receive(u8 type, struct gb_operation *op)

	/* Verify size of payload */
	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;
	}
	receive = op->request->payload;