Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d79e38f7 authored by Asutosh Das's avatar Asutosh Das Committed by Sayali Lokhande
Browse files

scsi: ufs: avoid deadlock by releasing rw_sem during hibernate



Consider the below scenario:
Three contexts:
1. Exception event handler [eeh]
2. Clock scaling
3. Error handler [eh]

	- Exception was raised
	- eeh runs
		- acquires dev.cmd.lock [1]
		- waits for rw_sem [3]
	- scaling is triggered from userspace
		- acquires rw_sem [2]
		- issues hibern8
		- error in hibern8
		- triggers error-handler (eh)
		- flushes eh [4]
	- eh is scheduled
		- waits on dev.cmd.lock [5]
So, [3] waits for [2] which flushes eh and waits on [5]
which has been acquired by [1]

So, release the rw_sem before issuing hibern8 and flush pending
error handler work if any, during clock scaling triggered from
user-space.

Change-Id: I968dd3d87bdfbf0aa1373a879a75f3c17349564e
Signed-off-by: default avatarAsutosh Das <asutoshd@codeaurora.org>
parent e83ca98f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -10239,7 +10239,15 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
	 * racing during clock frequency scaling sequence.
	 */
	if (ufshcd_is_auto_hibern8_supported(hba)) {
		/*
		 * Scaling prepare acquires the rw_sem: lock
		 * h8 may sleep in case of errors.
		 * e.g. link_recovery. Hence, release the rw_sem
		 * before hibern8.
		 */
		up_write(&hba->lock);
		ret = ufshcd_uic_hibern8_enter(hba);
		down_write(&hba->lock);
		if (ret)
			/* link will be bad state so no need to scale_up_gear */
			return ret;
@@ -10370,6 +10378,8 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev,

	hba->clk_scaling.is_allowed = value;

	flush_work(&hba->eh_work);

	if (value) {
		ufshcd_resume_clkscaling(hba);
	} else {