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

Commit 51f5cf9b authored by Jaegeuk Kim's avatar Jaegeuk Kim Committed by Pranav Vashi
Browse files

scsi: ufs: fix wrong sequence of lrb_in_use and pm



[1] tried to fix wrong lrbp=NULL after clear_bit_unlock, which caused a race
condition. But, it caused a power regression since __ufshcd_release was called
before lrb_in_use is released.

Actually, we should have followed the sequence:
1. lrbp->cmd = NULL
2. clear_bit_unlock()
3. __ufshcd_release()
4. __ufshcd_hibern8_release()

Let's add right fix.

[1] f0e7e5ba (scsi: ufs: Avoid potential lrb race caused by early release of lrb_in_use")

Bug: 157450639
Fixes: 639e1063a57e ("Revert "scsi: ufs: Avoid potential lrb race caused by early release of lrb_in_use"")
Fixes: f0e7e5ba (scsi: ufs: Avoid potential lrb race caused by early release of lrb_in_use")
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@google.com>
Change-Id: If738dc3e8e9caa7eee28c729dea3a47a3ed56b97
[dereference23: Apply to msm-4.14]
Signed-off-by: default avatarAlexander Winkowski <dereference23@outlook.com>
Signed-off-by: default avatarPranav Vashi <neobuddy89@gmail.com>
parent 4ac3f469
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -6502,15 +6502,12 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
			result = ufshcd_transfer_rsp_status(hba, lrbp);
			scsi_dma_unmap(cmd);
			cmd->result = result;
			clear_bit_unlock(index, &hba->lrb_in_use);
			lrbp->complete_time_stamp = ktime_get();
			update_req_stats(hba, lrbp);
			ufshcd_complete_lrbp_crypto(hba, cmd, lrbp);
			/* Mark completed command as NULL in LRB */
			lrbp->cmd = NULL;
			hba->ufs_stats.clk_rel.ctx = XFR_REQ_COMPL;
			__ufshcd_release(hba, false);
			__ufshcd_hibern8_release(hba, false);
			if (cmd->request) {
				/*
				 * As we are accessing the "request" structure,
@@ -6539,6 +6536,10 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
				}
			}

			clear_bit_unlock(index, &hba->lrb_in_use);
			__ufshcd_release(hba, false);
			__ufshcd_hibern8_release(hba, false);

			/* Do not touch lrbp after scsi done */
			cmd->scsi_done(cmd);
		} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE ||
@@ -6588,12 +6589,10 @@ void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, int result)
			/* Clear pending transfer requests */
			ufshcd_clear_cmd(hba, index);
			ufshcd_outstanding_req_clear(hba, index);
			clear_bit_unlock(index, &hba->lrb_in_use);
			lrbp->complete_time_stamp = ktime_get();
			update_req_stats(hba, lrbp);
			/* Mark completed command as NULL in LRB */
			lrbp->cmd = NULL;
			ufshcd_release_all(hba);
			if (cmd->request) {
				/*
				 * As we are accessing the "request" structure,
@@ -6603,6 +6602,9 @@ void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, int result)
				ufshcd_vops_pm_qos_req_end(hba, cmd->request,
					true);
			}
			clear_bit_unlock(index, &hba->lrb_in_use);
			ufshcd_release_all(hba);

			/* Do not touch lrbp after scsi done */
			cmd->scsi_done(cmd);
		} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {