Commit d2875b81 authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen
Browse files

scsi: ufs: core: Fix a deadlock in the frequency scaling code



Commit 08b12cda ("scsi: ufs: core: Switch to scsi_get_internal_cmd()")
accidentally introduced a deadlock in the frequency scaling code.
ufshcd_clock_scaling_unprepare() may submit a device management command
while SCSI command processing is blocked. The deadlock was introduced by
using the SCSI core for submitting device management commands
(scsi_get_internal_cmd() + blk_execute_rq()). Fix this deadlock by calling
blk_mq_unquiesce_tagset() before any device management commands are
submitted by ufshcd_clock_scaling_unprepare().

Fixes: 08b12cda ("scsi: ufs: core: Switch to scsi_get_internal_cmd()")
Reported-by: default avatarManivannan Sadhasivam <mani@kernel.org>
Reported-by: default avatarRoger Shimizu <rosh@debian.org>
Closes: https://lore.kernel.org/linux-scsi/ehorjaflathzab5oekx2nae2zss5vi2r36yqkqsfjb2fgsifz2@yk3us5g3igow/


Tested-by: default avatarRoger Shimizu <rosh@debian.org>
Cc: Nitin Rawat <nitin.rawat@oss.qualcomm.com>
Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Reviewed-by: default avatarPeter Wang <peter.wang@mediatek.com>
Reviewed-by: default avatarNitin Rawat <nitin.rawat@oss.qualcomm.com>
Tested-by: Alexey Klimov <alexey.klimov@linaro.org> # RB5 board
Link: https://patch.msgid.link/20251204181548.1006696-1-bvanassche@acm.org


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 14be351e
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -1455,15 +1455,14 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)
static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err)
{
	up_write(&hba->clk_scaling_lock);
	mutex_unlock(&hba->wb_mutex);
	blk_mq_unquiesce_tagset(&hba->host->tag_set);
	mutex_unlock(&hba->host->scan_mutex);

	/* Enable Write Booster if current gear requires it else disable it */
	if (ufshcd_enable_wb_if_scaling_up(hba) && !err)
		ufshcd_wb_toggle(hba, hba->pwr_info.gear_rx >= hba->clk_scaling.wb_gear);

	mutex_unlock(&hba->wb_mutex);

	blk_mq_unquiesce_tagset(&hba->host->tag_set);
	mutex_unlock(&hba->host->scan_mutex);
	ufshcd_release(hba);
}