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

Commit 6dbfcba7 authored by Asutosh Das's avatar Asutosh Das Committed by Nitin Rawat
Browse files

scsi: ufs: fix race between shutdown and rls handler



 Call trace:-
 __switch_to+0xb8/0xd0
 __schedule+0x8d8/0xc70
 schedule+0x74/0xa0
 schedule_timeout+0x44/0x678
 io_schedule_timeout+0x44/0x70
 wait_for_common_io+0x90/0x118
 wait_for_completion_io+0x14/0x28
 blk_execute_rq+0x48/0x78
 scsi_execute+0x114/0x1b8
 ufshcd_set_dev_pwr_mode+0x1ac/0x248
 ufshcd_suspend+0x208/0x548
 ufshcd_shutdown+0x18c/0x1e8
 ufshcd_pltfrm_shutdown+0x14/0x28
 platform_drv_shutdown+0x20/0x30
 device_shutdown+0x178/0x1f8
 kernel_restart+0x54/0x128
 SyS_reboot+0x158/0x228
 __sys_trace_return+0x0/0x4

blk_execute_rq has acquired hba->lock and is waiting for host
to be unblocked.

 Call trace:-
 __switch_to+0xb8/0xd0
 __schedule+0x8d8/0xc70
 schedule+0x74/0xa0
 rwsem_down_write_failed+0x24c/0x328
 down_write+0x54/0x60
 ufshcd_rls_handler+0x8c/0x380
 process_one_work+0x228/0x4b0
 worker_thread+0x2f4/0x460
 kthread+0x114/0x128
 ret_from_fork+0x10/0x20

rls handler has blocked the scsi requests and is waiting
for hba->lock.
Thus a deadlock happens.

Fix this by always acquiring the lock before blocking
scsi requests.

CRs-fixed: 2393722
Change-Id: Ib66682967641e316d70641a5189bdb71d9fdda7b
Signed-off-by: default avatarAsutosh Das <asutoshd@codeaurora.org>
Signed-off-by: default avatarNitin Rawat <nitirawa@codeaurora.org>
parent 6a1ffe01
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1204,8 +1204,8 @@ static int ufsdbg_config_pwr_mode(struct ufs_hba *hba,
	/* let's not get into low power until clock scaling is completed */
	hba->ufs_stats.clk_hold.ctx = DBGFS_CFG_PWR_MODE;
	ufshcd_hold(hba, false);
	ufshcd_scsi_block_requests(hba);
	down_write(&hba->lock);
	ufshcd_scsi_block_requests(hba);
	if (ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) {
		ret = -EBUSY;
		goto out;
+4 −2
Original line number Diff line number Diff line
@@ -1782,8 +1782,8 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
	 * make sure that there are no outstanding requests when
	 * clock scaling is in progress
	 */
	ufshcd_scsi_block_requests(hba);
	down_write(&hba->lock);
	ufshcd_scsi_block_requests(hba);
	if (ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) {
		ret = -EBUSY;
		up_write(&hba->lock);
@@ -7445,8 +7445,10 @@ static void ufshcd_rls_handler(struct work_struct *work)
		return;

	pm_runtime_get_sync(hba->dev);
	ufshcd_scsi_block_requests(hba);
	down_write(&hba->lock);
	ufshcd_scsi_block_requests(hba);
	if (ufshcd_is_shutdown_ongoing(hba))
		goto out;
	ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
	if (ret) {
		dev_err(hba->dev,