• Subhash Jadavani's avatar
    scsi: ufs: fix race between clock gating and devfreq scaling work · d43f955f
    Subhash Jadavani authored
    commit 30fc33f1 upstream.
    
    UFS devfreq clock scaling work may require clocks to be ON if it need to
    execute some UFS commands hence it may request for clock hold before
    issuing the command. But if UFS clock gating work is already running in
    parallel, ungate work would end up waiting for the clock gating work to
    finish and as clock gating work would also wait for the clock scaling
    work to finish, we would enter in deadlock state. Here is the call trace
    during this deadlock state:
    
    Workqueue: devfreq_wq devfreq_monitor
    	__switch_to
    	__schedule
    	schedule
    	schedule_timeout
    	wait_for_common
    	wait_for_completion
    	flush_work
    	ufshcd_hold
    	ufshcd_send_uic_cmd
    	ufshcd_dme_get_attr
    	ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div
    	ufs_qcom_clk_scale_notify
    	ufshcd_scale_clks
    	ufshcd_devfreq_target
    	update_devfreq
    	devfreq_monitor
    	process_one_work
    	worker_thread
    	kthread
    	ret_from_fork
    
    Workqueue: events ufshcd_gate_work
    	__switch_to
    	__schedule
    	schedule
    	schedule_preempt_disabled
    	__mutex_lock_slowpath
    	mutex_lock
    	devfreq_monitor_suspend
    	devfreq_simple_ondemand_handler
    	devfreq_suspend_device
    	ufshcd_gate_work
    	process_one_work
    	worker_thread
    	kthread
    	ret_from_fork
    
    Workqueue: events ufshcd_ungate_work
    	__switch_to
    	__schedule
    	schedule
    	schedule_timeout
    	wait_for_common
    	wait_for_completion
    	flush_work
    	__cancel_work_timer
    	cancel_delayed_work_sync
    	ufshcd_ungate_work
    	process_one_work
    	worker_thread
    	kthread
    	ret_from_fork
    
    This change fixes this deadlock by doing this in devfreq work (devfreq_wq):
    Try cancelling clock gating work. If we are able to cancel gating work
    or it wasn't scheduled, hold the clock reference count until scaling is
    in progress. If gate work is already running in parallel, let's skip
    the frequecy scaling at this time and it will be retried once next scaling
    window expires.
    Reviewed-by: 's avatarSahitya Tummala <stummala@codeaurora.org>
    Signed-off-by: 's avatarSubhash Jadavani <subhashj@codeaurora.org>
    Signed-off-by: 's avatarMartin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: 's avatarAmit Pundir <amit.pundir@linaro.org>
    Signed-off-by: 's avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    d43f955f
Name
Last commit
Last update
Documentation Loading commit data...
arch Loading commit data...
block Loading commit data...
certs Loading commit data...
crypto Loading commit data...
drivers Loading commit data...
firmware Loading commit data...
fs Loading commit data...
include Loading commit data...
init Loading commit data...
ipc Loading commit data...
kernel Loading commit data...
lib Loading commit data...
mm Loading commit data...
net Loading commit data...
samples Loading commit data...
scripts Loading commit data...
security Loading commit data...
sound Loading commit data...
tools Loading commit data...
usr Loading commit data...
virt Loading commit data...
.get_maintainer.ignore Loading commit data...
.gitignore Loading commit data...
.mailmap Loading commit data...
COPYING Loading commit data...
CREDITS Loading commit data...
Kbuild Loading commit data...
Kconfig Loading commit data...
MAINTAINERS Loading commit data...
Makefile Loading commit data...
README Loading commit data...
REPORTING-BUGS Loading commit data...