| From 2e4586bff96a2377548618a193a97b6605dd407d Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 11 Aug 2020 16:18:58 +0200 |
| Subject: scsi: ufs: Clean up completed request without interrupt notification |
| |
| From: Stanley Chu <stanley.chu@mediatek.com> |
| |
| [ Upstream commit b10178ee7fa88b68a9e8adc06534d2605cb0ec23 ] |
| |
| If somehow no interrupt notification is raised for a completed request and |
| its doorbell bit is cleared by host, UFS driver needs to cleanup its |
| outstanding bit in ufshcd_abort(). Otherwise, system may behave abnormally |
| in the following scenario: |
| |
| After ufshcd_abort() returns, this request will be requeued by SCSI layer |
| with its outstanding bit set. Any future completed request will trigger |
| ufshcd_transfer_req_compl() to handle all "completed outstanding bits". At |
| this time the "abnormal outstanding bit" will be detected and the "requeued |
| request" will be chosen to execute request post-processing flow. This is |
| wrong because this request is still "alive". |
| |
| Link: https://lore.kernel.org/r/20200811141859.27399-2-huobean@gmail.com |
| Reviewed-by: Can Guo <cang@codeaurora.org> |
| Acked-by: Avri Altman <avri.altman@wdc.com> |
| Signed-off-by: Stanley Chu <stanley.chu@mediatek.com> |
| Signed-off-by: Bean Huo <beanhuo@micron.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/scsi/ufs/ufshcd.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c |
| index 619fe46fcc5f0..c1792f271ac5d 100644 |
| --- a/drivers/scsi/ufs/ufshcd.c |
| +++ b/drivers/scsi/ufs/ufshcd.c |
| @@ -5694,7 +5694,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) |
| /* command completed already */ |
| dev_err(hba->dev, "%s: cmd at tag %d successfully cleared from DB.\n", |
| __func__, tag); |
| - goto out; |
| + goto cleanup; |
| } else { |
| dev_err(hba->dev, |
| "%s: no response from device. tag = %d, err %d\n", |
| @@ -5728,6 +5728,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) |
| goto out; |
| } |
| |
| +cleanup: |
| scsi_dma_unmap(cmd); |
| |
| spin_lock_irqsave(host->host_lock, flags); |
| -- |
| 2.25.1 |
| |