summary refs log tree commit diff
path: root/drivers/scsi/ufs/ufshcd.h
diff options
context:
space:
mode:
authorCan Guo <cang@codeaurora.org>2020-12-02 04:04:02 -0800
committerMartin K. Petersen <martin.petersen@oracle.com>2020-12-07 18:29:24 -0500
commit7a7e66c65d4148fc3f23b058405bc9f102414fcb (patch)
tree8ad6db852e0314bf3246a3713637e3af0ccef4a5 /drivers/scsi/ufs/ufshcd.h
parent88a92d6ae4fe09b2b27781178c5c9432d27b1ffb (diff)
downloadlinux-7a7e66c65d4148fc3f23b058405bc9f102414fcb.tar.gz
scsi: ufs: Fix a race condition between ufshcd_abort() and eh_work()
In current task abort routine, if task abort happens to the device W-LUN,
the code directly jumps to ufshcd_eh_host_reset_handler() to perform a full
reset and restore then returns FAIL or SUCCESS. Commands sent to the device
W-LUN are most likely the SSU cmds sent during UFS PM operations. If such
SSU cmd enters task abort routine when ufshcd_eh_host_reset_handler()
flushes eh_work, it will get stuck there since err_handler is serialized
with PM operations.

In order to unblock above call path, we merely clean up the lrb taken by
this cmd, queue the eh_work and return SUCCESS. Once the cmd is aborted,
the PM operation which sends out the cmd just errors out, then err_handler
shall be able to proceed with the full reset and restore.

In this scenario, the cmd is aborted even before it is actually cleared by
HW, set the lrb->in_use flag to prevent subsequent cmds, including SCSI
cmds and dev cmds, from taking the lrb released from abort. The flag shall
evetually be cleared in __ufshcd_transfer_req_compl() invoked by the full
reset and restore from err_handler.

[mkp: conflict with event logging series]

Link: https://lore.kernel.org/r/1606910644-21185-3-git-send-email-cang@codeaurora.org
Reviewed-by: Asutosh Das <asutoshd@codeaurora.org>
Reviewed-by: Stanley Chu <stanley.chu@mediatek.com>
Signed-off-by: Can Guo <cang@codeaurora.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/ufs/ufshcd.h')
-rw-r--r--drivers/scsi/ufs/ufshcd.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 1d4d3f80caa0..08c8a591e6b0 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -193,6 +193,7 @@ struct ufs_pm_lvl_states {
  * @crypto_key_slot: the key slot to use for inline crypto (-1 if none)
  * @data_unit_num: the data unit number for the first block for inline crypto
  * @req_abort_skip: skip request abort task flag
+ * @in_use: indicates that this lrb is still in use
  */
 struct ufshcd_lrb {
 	struct utp_transfer_req_desc *utr_descriptor_ptr;
@@ -222,6 +223,7 @@ struct ufshcd_lrb {
 #endif
 
 	bool req_abort_skip;
+	bool in_use;
 };
 
 /**