From 082fd231c4fa390ec992ddbaa8c34a5205aeb70e Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 27 May 2020 06:38:18 -0700 Subject: [PATCH] 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] f0e7e5baba0a (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: f0e7e5baba0a (scsi: ufs: Avoid potential lrb race caused by early release of lrb_in_use") Signed-off-by: Jaegeuk Kim Change-Id: If738dc3e8e9caa7eee28c729dea3a47a3ed56b97 [dereference23: Apply to msm-4.14] Signed-off-by: Alexander Winkowski --- drivers/scsi/ufs/ufshcd.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 0b44e5bf9bea..97ca00d6b462 100755 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7494,15 +7494,12 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, #endif 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, @@ -7530,6 +7527,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 || @@ -7579,12 +7580,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, @@ -7594,6 +7593,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) {