summaryrefslogtreecommitdiff
path: root/drivers/staging/greybus/loopback.c
diff options
context:
space:
mode:
authorBryan O'Donoghue <bryan.odonoghue@linaro.org>2016-03-16 11:29:59 +0000
committerGreg Kroah-Hartman <gregkh@google.com>2016-03-16 21:49:31 -0700
commitfece9c87cb80aceec7dd0205a77c37ff7ba831fe (patch)
tree32c098bd6755ded2c95b096b88250b3a678d34d0 /drivers/staging/greybus/loopback.c
parent1dc8d3d7c568d9a80fa20570a764da57677f1050 (diff)
greybus: Ensure gb->mutex is held when adding timer
Currently in loopback on the async path we issue an operation and then add a timer to time-out that operation should it fail to complete. Looking at a backtrace given in its feasible op_async->pending can be true and del_timer() can run before add_timer() has run. In the callback handler we already hold gb->mutex. This patch fixes that potential race by ensuring we hold gb->mutex both when we are adding and when we are removing the relevant timer. Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> Reported-and-tested-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/loopback.c')
-rw-r--r--drivers/staging/greybus/loopback.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c
index 9b732a866455..5e009e1955ab 100644
--- a/drivers/staging/greybus/loopback.c
+++ b/drivers/staging/greybus/loopback.c
@@ -626,6 +626,7 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type,
do_gettimeofday(&op_async->ts);
op_async->pending = true;
atomic_inc(&gb->outstanding_operations);
+ mutex_lock(&gb->mutex);
ret = gb_operation_request_send(operation,
gb_loopback_async_operation_callback,
GFP_KERNEL);
@@ -637,9 +638,11 @@ static int gb_loopback_async_operation(struct gb_loopback *gb, int type,
op_async->timer.data = (unsigned long)operation->id;
add_timer(&op_async->timer);
- return ret;
+ goto done;
error:
gb_loopback_async_operation_put(op_async);
+done:
+ mutex_unlock(&gb->mutex);
return ret;
}