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

Commit 8e3fba55 authored by Bryan O'Donoghue's avatar Bryan O'Donoghue Committed by Greg Kroah-Hartman
Browse files

greybus: loopback: Add asynchronous backoff



A specific request from the firmware people is the ability to back-off from
sending more asynchronous operations once a specific number of operations
are in-flight.

This patch adds that ability - with a new sysfs parameter
'outstanding_operations_max' which controls the maximum number of
operations that can be outstanding/in-flight at any time.

When outstanding_operations_max contains a non-zero value and asynchronous
operations are being used - we will back-off until the completion counter
is < outstanding_operations_max. Tested in both synchronous and
asynchronous mode and with gb_loopback_connection_exit() interrupting
in-flight operations.

Suggested-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 36f241ff
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ struct gb_loopback {
	u32 jiffy_timeout;
	u32 timeout_min;
	u32 timeout_max;
	u32 outstanding_operations_max;
	u32 lbid;
	u64 elapsed_nsecs;
	u32 apbridge_latency_ts;
@@ -311,6 +312,8 @@ gb_dev_loopback_ro_attr(iteration_count, false);
gb_dev_loopback_rw_attr(async, u);
/* Timeout of an individual asynchronous request */
gb_dev_loopback_rw_attr(timeout, u);
/* Maximum number of in-flight operations before back-off */
gb_dev_loopback_rw_attr(outstanding_operations_max, u);

static struct attribute *loopback_attrs[] = {
	&dev_attr_latency_min.attr,
@@ -338,6 +341,7 @@ static struct attribute *loopback_attrs[] = {
	&dev_attr_requests_completed.attr,
	&dev_attr_requests_timedout.attr,
	&dev_attr_timeout.attr,
	&dev_attr_outstanding_operations_max.attr,
	&dev_attr_timeout_min.attr,
	&dev_attr_timeout_max.attr,
	NULL,
@@ -911,6 +915,16 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb)
				 gb->gpbridge_latency_ts);
}

static void gb_loopback_async_wait_to_send(struct gb_loopback *gb)
{
	if (!(gb->async && gb->outstanding_operations_max))
		return;
	wait_event_interruptible(gb->wq_completion,
				 (atomic_read(&gb->outstanding_operations) <
				  gb->outstanding_operations_max) ||
				  kthread_should_stop());
}

static int gb_loopback_fn(void *data)
{
	int error = 0;
@@ -924,7 +938,11 @@ static int gb_loopback_fn(void *data)
		if (!gb->type)
			wait_event_interruptible(gb->wq, gb->type ||
						 kthread_should_stop());
		if (kthread_should_stop())
			break;

		/* Limit the maximum number of in-flight async operations */
		gb_loopback_async_wait_to_send(gb);
		if (kthread_should_stop())
			break;