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 <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>
This commit is contained in:
Bryan O'Donoghue 2016-06-16 13:42:14 +01:00 committed by Greg Kroah-Hartman
parent df124299d1
commit c9e8f893ee

View 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);