diff options
author | Bryan O'Donoghue <bryan.odonoghue@linaro.org> | 2015-12-11 13:46:53 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2015-12-11 16:18:40 -0800 |
commit | 8e3fba55d379bb67732c878988cf9859bfea2812 (patch) | |
tree | 5a3bc6baec533513ae616e4493fc45b90d05e455 /drivers | |
parent | 36f241fff4720f205e36bda5900d4ef7b6662bd7 (diff) |
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: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/greybus/loopback.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index 4814f948eea3..c35d22733a36 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -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; |