]> git.karo-electronics.de Git - linux-beck.git/commitdiff
greybus: timesync: Do not hold mutex on cancel_delayed_work_sync
authorBryan O'Donoghue <bryan.odonoghue@linaro.org>
Thu, 16 Jun 2016 12:42:14 +0000 (13:42 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 16 Jun 2016 16:07:41 +0000 (09:07 -0700)
There is a scenario where gb_timesync_svc_remove() can run, attain a mutex
and call cancel_delayed_work_sync(). In the meantime a worker may already
be running and trying to attain the same mutex but will never do so as the
gb_timesync_svc_remove() path is holding the mutex and waiting on the
delayed_work_sync() to complete - leading to deadlock. This patch addresses
by calling the cancel_delayed_work_sync() before locking the relevant
mutex.

Reported-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org>
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Tested-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/timesync.c

index a029fa085af6e54a13052d82d9116859d6f527be..a9b62026a201f659c519f30de6fea868c14c918b 100644 (file)
@@ -1065,6 +1065,8 @@ void gb_timesync_svc_remove(struct gb_svc *svc)
        if (!timesync_svc)
                goto done;
 
+       cancel_delayed_work_sync(&timesync_svc->delayed_work);
+
        mutex_lock(&timesync_svc->mutex);
 
        gb_timesync_teardown(timesync_svc);
@@ -1079,7 +1081,6 @@ void gb_timesync_svc_remove(struct gb_svc *svc)
        gb_timesync_set_state_atomic(timesync_svc, GB_TIMESYNC_STATE_INVALID);
        debugfs_remove(timesync_svc->frame_ktime_dentry);
        debugfs_remove(timesync_svc->frame_time_dentry);
-       cancel_delayed_work_sync(&timesync_svc->delayed_work);
        destroy_workqueue(timesync_svc->work_queue);
        list_del(&timesync_svc->list);