From: Bryan O'Donoghue Date: Thu, 16 Jun 2016 12:42:14 +0000 (+0100) Subject: greybus: timesync: Do not hold mutex on cancel_delayed_work_sync X-Git-Tag: v4.9-rc1~119^2~378^2~21^2~241 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=c9e8f893eeef4f0e2d10333aed2d175e50a56dab;p=karo-tx-linux.git greybus: timesync: Do not hold mutex on cancel_delayed_work_sync 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 Signed-off-by: Bryan O'Donoghue Reviewed-by: Vaibhav Hiremath Tested-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c index a029fa085af6..a9b62026a201 100644 --- a/drivers/staging/greybus/timesync.c +++ b/drivers/staging/greybus/timesync.c @@ -1065,6 +1065,8 @@ void gb_timesync_svc_remove(struct gb_svc *svc) if (!timesync_svc) goto done; + cancel_delayed_work_sync(×ync_svc->delayed_work); + mutex_lock(×ync_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(×ync_svc->delayed_work); destroy_workqueue(timesync_svc->work_queue); list_del(×ync_svc->list);