[PATCH 0/2] scsi: ufs: core: Fix SCSI EH command ownership and remove force_compl

From: Stanley Jhu

Date: Sun Sep 20 2026 - 10:34:18 EST


In ufshcd_host_reset_and_restore(), ufshcd_complete_requests(hba, true)
couples LLD resource release (ufshcd_release_scsi_cmd()) with command
completion (scsi_done()) right after ufshcd_hba_stop():

1. EH-owned SCSI commands (SCMD_STATE_COMPLETE set): skipping
scsi_done() in ufshcd_mcq_force_compl_one() also skips
ufshcd_release_scsi_cmd(), leaking DMA mappings and
clk_gating.active_reqs whenever ufshcd_abort() fails.
2. Non-EH SCSI commands (!SCMD_STATE_COMPLETE): calling scsi_done()
right after ufshcd_hba_stop() completes them before link recovery
finishes.

This series enforces a strict ownership boundary between LLD hardware
resources and SCSI command completion across SDB and MCQ error recovery:

- LLD resources (DMA mappings, crypto PRDT, clk_gating.active_reqs) are
tied to controller execution and are released whenever the hardware
stops executing a command, regardless of whether SCSI EH owns it.
- Command completion (scsi_done()) belongs exclusively to SCSI EH once
SCMD_STATE_COMPLETE is set. For commands where SCMD_STATE_COMPLETE is
not set, UFS cannot delegate completion to SCSI EH because UFS also
performs autonomous resets (ufshcd_err_handler() on UIC/controller
errors) outside of scsi_error_handler(). Since ufshcd_hba_stop()
(HCE = 0) wipes all in-flight hardware transfers while SCSI EH is
inactive, the driver itself requeues halted non-EH commands with
DID_REQUEUE after recovery finishes so they do not stall for the 30s
block timeout.

- Patch 1 tracks controller resource ownership with lrbp->in_flight and
halted non-EH commands with lrbp->pending_requeue, splits host-reset
cleanup into ufshcd_release_stopped_reqs() (at controller stop) and
ufshcd_requeue_non_eh_cmds() (after recovery finishes), and aligns
ownership across ufshcd_compl_one_cqe(), ufshcd_abort(), and
ufshcd_clear_lu_cmds().
- Patch 2 removes the unused force_compl parameter from
ufshcd_complete_requests() and ufshcd_mcq_compl_pending_transfer(),
along with the now-unreachable ufshcd_mcq_force_compl_one() and
ufshcd_mcq_compl_all_cqes_lock() helpers.

This supersedes the v2 series [3].

Link: https://lore.kernel.org/linux-scsi/eacb6c2a-9219-4e9b-8726-8d38b641f543@xxxxxxx/ [1]
Link: https://lore.kernel.org/linux-scsi/1ddc5181-f547-465c-bfbe-dbf14a91493e@xxxxxxx/ [2]
Link: https://lore.kernel.org/linux-scsi/20260918143809.3034592-1-stanleyjhu@xxxxxxxxxx/ [3]
Link: https://lore.kernel.org/linux-scsi/20260920135014.3528082-1-stanleyjhu@xxxxxxxxxx/ [4]

Tested:
Verified on QEMU ARM64 (SDB and MCQ) across probe, I/O, reset, and
unbind without UAF or leaks.

Stanley Jhu (2):
scsi: ufs: core: Release command resources instead of force-completing
scsi: ufs: core: Remove unused force_compl parameter and MCQ helper

drivers/ufs/core/ufs-mcq.c | 26 ----
drivers/ufs/core/ufshcd-priv.h | 2 -
drivers/ufs/core/ufshcd.c | 213 +++++++++++++++++++++++---------
include/ufs/ufshcd.h | 4 +
4 files changed, 157 insertions(+), 88 deletions(-)

--
2.51.0