* [PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock()
@ 2026-09-01 12:23 Stanley Jhu
2026-09-18 14:38 ` [PATCH v2 0/2] scsi: ufs: core: Fix unsafe MMIO reads and redundant CQ sweeps in MCQ reset Stanley Jhu
2026-09-18 22:15 ` [PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Bart Van Assche
0 siblings, 2 replies; 13+ messages in thread
From: Stanley Jhu @ 2026-09-01 12:23 UTC (permalink / raw)
To: Martin K . Petersen, James E . J . Bottomley
Cc: Alim Akhtar, Avri Altman, Bart Van Assche, Peter Wang, quic_cang,
quic_nguyenb, linux-scsi, linux-kernel, stable
Reading host controller registers (such as CQTP) is unsafe when the
host controller is disabled (HCE = 0), as accessing registers in an
unclocked or reset state can cause bus stalls and system hangs.
In ufshcd_mcq_compl_all_cqes_lock(), all completion queue entries have
already been inspected, processed, and cleared in memory, so the
software queue is logically empty.
Avoid the unsafe MMIO read of CQTP by synchronizing hwq->cq_tail_slot
directly to hwq->cq_head_slot in software. Upon subsequent controller
re-initialization, ufshcd_mcq_make_queues_operational() will
reconfigure and re-zero all queue pointers.
Fixes: ab248643d3d6 ("scsi: ufs: core: Add error handling for MCQ mode")
Cc: stable@vger.kernel.org
Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
---
drivers/ufs/core/ufs-mcq.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index 8106d55f4041..0e1f99c8d77c 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -349,8 +349,12 @@ void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba,
entries--;
}
- ufshcd_mcq_update_cq_tail_slot(hwq);
- hwq->cq_head_slot = hwq->cq_tail_slot;
+ /*
+ * All completion entries have been processed and cleared.
+ * Synchronize tail to head in software to mark the queue empty,
+ * avoiding unsafe MMIO reads while the controller is disabled.
+ */
+ hwq->cq_tail_slot = hwq->cq_head_slot;
spin_unlock_irqrestore(&hwq->cq_lock, flags);
}
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 0/2] scsi: ufs: core: Fix unsafe MMIO reads and redundant CQ sweeps in MCQ reset
2026-09-01 12:23 [PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Stanley Jhu
@ 2026-09-18 14:38 ` Stanley Jhu
2026-09-18 14:38 ` [PATCH v2 1/2] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Stanley Jhu
2026-09-18 14:38 ` [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ Stanley Jhu
2026-09-18 22:15 ` [PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Bart Van Assche
1 sibling, 2 replies; 13+ messages in thread
From: Stanley Jhu @ 2026-09-18 14:38 UTC (permalink / raw)
To: Martin K . Petersen, Bean Huo, Bart Van Assche
Cc: Alim Akhtar, Avri Altman, James E . J . Bottomley,
Manivannan Sadhasivam, Peter Wang, linux-scsi, linux-kernel,
stanleyjhu
During Multi-Circular Queue (MCQ) error recovery and host reset,
ufshcd_mcq_compl_pending_transfer() sweeps or polls completion queues to
reap pending transfers. Two bugs exist in this path:
1. Unsafe MMIO read and spurious errors while HCE = 0 (Patch 1/2):
ufshcd_host_reset_and_restore() stops the controller (HCE = 0) before
calling ufshcd_mcq_compl_all_cqes_lock(). Calling
ufshcd_mcq_update_cq_tail_slot() at the end of the sweep reads CQTPy
over MMIO while HCE = 0, directly contradicting the function's own
documented contract that reading host controller registers is unsafe
when the controller is disabled. In addition, passing expected empty
slots during a full-ring sweep into ufshcd_mcq_process_cqe() prints
spurious "Abnormal CQ entry!" errors.
2. Redundant per-request CQ sweeps and polls (Patch 2/2):
ufshcd_mcq_compl_pending_transfer() runs hardware queue completion
sweeps (force_compl == true) or CQTPy polls (force_compl == false)
inside blk_mq_tagset_busy_iter() callbacks, repeating whole-queue
operations once per busy request instead of once per hardware queue.
Patch 1/2 synchronizes hwq->cq_tail_slot = hwq->cq_head_slot in software
and extracts ufshcd_mcq_compl_cqe() so full-ring sweeps skip empty slots
silently. Patch 2/2 sweeps or polls each hardware queue once before
iterating residual requests and removes ufshcd_mcq_compl_one().
Changes since v1:
- Split into a two-patch series separating ring sweep safety from
per-request tagset iteration.
- Extract ufshcd_mcq_compl_cqe() to skip empty slots without double CQE
checks (dropped Peter Wang's v1 Reviewed-by due to this change).
- Decouple hardware queue polling/sweeping for both force_compl paths
and remove ufshcd_mcq_compl_one().
Tested: Verified MCQ host reset, I/O completion, and queue pointer
integrity on QEMU ARM64 without MMIO aborts or spurious error logs.
Link: https://lore.kernel.org/r/CAE14pdek6ynze+muDZrK+yNX-3ioe3vprxOA4W22qokg352tJQ@mail.gmail.com
Stanley Jhu (2):
scsi: ufs: core: Avoid unsafe MMIO reads in
ufshcd_mcq_compl_all_cqes_lock()
scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ
drivers/ufs/core/ufs-mcq.c | 35 +++++++++++++++++++++++------------
drivers/ufs/core/ufshcd.c | 31 ++++++++++++-------------------
2 files changed, 35 insertions(+), 31 deletions(-)
--
2.55.0.1082.g2b9226bbc0-goog
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 1/2] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock()
2026-09-18 14:38 ` [PATCH v2 0/2] scsi: ufs: core: Fix unsafe MMIO reads and redundant CQ sweeps in MCQ reset Stanley Jhu
@ 2026-09-18 14:38 ` Stanley Jhu
2026-09-22 3:05 ` Peter Wang
2026-09-18 14:38 ` [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ Stanley Jhu
1 sibling, 1 reply; 13+ messages in thread
From: Stanley Jhu @ 2026-09-18 14:38 UTC (permalink / raw)
To: Martin K . Petersen, Bean Huo, Bart Van Assche
Cc: Alim Akhtar, Avri Altman, James E . J . Bottomley,
Manivannan Sadhasivam, Peter Wang, linux-scsi, linux-kernel,
stanleyjhu, stable
During MCQ host reset, ufshcd_host_reset_and_restore() stops the host
controller via ufshcd_hba_stop() (HCE = 0) before calling
ufshcd_complete_requests(hba, true) ->
ufshcd_mcq_compl_pending_transfer(hba, true) ->
ufshcd_mcq_force_compl_one() -> ufshcd_mcq_compl_all_cqes_lock().
Because ufshcd_mcq_force_compl_one() is its sole caller,
ufshcd_mcq_compl_all_cqes_lock() always runs with HCE = 0.
Despite the comment above ufshcd_mcq_compl_all_cqes_lock() stating that
reading CQTPy may not be safe with the controller disabled, the function
still calls ufshcd_mcq_update_cq_tail_slot() at the end of its sweep:
1. Unsafe CQTPy MMIO read:
Calling ufshcd_mcq_update_cq_tail_slot() at the end of the sweep
reads CQTPy over MMIO while HCE = 0, directly contradicting the
function's documented contract (commit 1373df88d535 ("scsi: ufs:
core: Add a comment block above ufshcd_mcq_compl_all_cqes_lock()"))
that reading CQTPy may not be safe with the controller disabled.
2. Spurious error logs on empty slots:
Sweeping all max_entries slots visits empty entries where
command_desc_base_addr is 0, causing ufshcd_mcq_process_cqe() to log
unguarded dev_err(hba->dev, "Abnormal CQ entry!\n") messages.
Fix both issues in ufshcd_mcq_compl_all_cqes_lock():
- Synchronize hwq->cq_tail_slot = hwq->cq_head_slot in software after
sweeping the ring, avoiding CQTPy MMIO reads while HCE = 0.
- Extract ufshcd_mcq_compl_cqe() and invoke it only on non-empty slots
during full-ring sweeps, keeping "Abnormal CQ entry!" logging strictly
for unexpected empty entries in ufshcd_mcq_poll_cqe_lock().
Fixes: ab248643d3d6 ("scsi: ufs: core: Add error handling for MCQ mode")
Cc: stable@vger.kernel.org
Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
---
v2:
- Extract ufshcd_mcq_compl_cqe() to skip empty slots inside
ufshcd_mcq_compl_all_cqes_lock() without double CQE checks (dropped
Peter Wang's v1 Reviewed-by due to this code change).
- Move hardware queue polling and sweeping deduplication to Patch 2/2.
Link: https://lore.kernel.org/r/CAE14pdek6ynze+muDZrK+yNX-3ioe3vprxOA4W22qokg352tJQ@mail.gmail.com
drivers/ufs/core/ufs-mcq.c | 35 +++++++++++++++++++++++------------
1 file changed, 23 insertions(+), 12 deletions(-)
diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
index 8106d55f4041..bfc43a6080e7 100644
--- a/drivers/ufs/core/ufs-mcq.c
+++ b/drivers/ufs/core/ufs-mcq.c
@@ -312,20 +312,24 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba, struct cq_entry *cqe)
UFSHCD_NUM_RESERVED;
}
+static void ufshcd_mcq_compl_cqe(struct ufs_hba *hba, struct cq_entry *cqe)
+{
+ int tag = ufshcd_mcq_get_tag(hba, cqe);
+
+ ufshcd_compl_one_cqe(hba, tag, cqe);
+ /* After processed the cqe, mark it empty (invalid) entry */
+ cqe->command_desc_base_addr = 0;
+}
+
static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,
struct ufs_hw_queue *hwq)
{
struct cq_entry *cqe = ufshcd_mcq_cur_cqe(hwq);
- if (cqe->command_desc_base_addr) {
- int tag = ufshcd_mcq_get_tag(hba, cqe);
-
- ufshcd_compl_one_cqe(hba, tag, cqe);
- /* After processed the cqe, mark it empty (invalid) entry */
- cqe->command_desc_base_addr = 0;
- } else {
+ if (cqe->command_desc_base_addr)
+ ufshcd_mcq_compl_cqe(hba, cqe);
+ else
dev_err(hba->dev, "Abnormal CQ entry!\n");
- }
}
/*
@@ -333,7 +337,7 @@ static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,
* controller disabled (HCE = 0). Reading host controller registers, e.g. the
* CQ tail pointer (CQTPy), may not be safe with the host controller disabled.
* Hence, iterate over all completion queue entries. This won't result in
- * double completions because ufshcd_mcq_process_cqe() clears a CQE after it
+ * double completions because ufshcd_mcq_compl_cqe() clears a CQE after it
* has been processed.
*/
void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba,
@@ -344,13 +348,20 @@ void ufshcd_mcq_compl_all_cqes_lock(struct ufs_hba *hba,
spin_lock_irqsave(&hwq->cq_lock, flags);
while (entries > 0) {
- ufshcd_mcq_process_cqe(hba, hwq);
+ struct cq_entry *cqe = ufshcd_mcq_cur_cqe(hwq);
+
+ if (cqe->command_desc_base_addr)
+ ufshcd_mcq_compl_cqe(hba, cqe);
ufshcd_mcq_inc_cq_head_slot(hwq);
entries--;
}
- ufshcd_mcq_update_cq_tail_slot(hwq);
- hwq->cq_head_slot = hwq->cq_tail_slot;
+ /*
+ * All completion entries have been processed and cleared.
+ * Synchronize tail to head in software to mark the queue empty,
+ * avoiding an MMIO read of CQTPy while the controller is disabled.
+ */
+ hwq->cq_tail_slot = hwq->cq_head_slot;
spin_unlock_irqrestore(&hwq->cq_lock, flags);
}
--
2.55.0.1082.g2b9226bbc0-goog
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ
2026-09-18 14:38 ` [PATCH v2 0/2] scsi: ufs: core: Fix unsafe MMIO reads and redundant CQ sweeps in MCQ reset Stanley Jhu
2026-09-18 14:38 ` [PATCH v2 1/2] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Stanley Jhu
@ 2026-09-18 14:38 ` Stanley Jhu
2026-09-18 16:06 ` Bart Van Assche
1 sibling, 1 reply; 13+ messages in thread
From: Stanley Jhu @ 2026-09-18 14:38 UTC (permalink / raw)
To: Martin K . Petersen, Bean Huo, Bart Van Assche
Cc: Alim Akhtar, Avri Altman, James E . J . Bottomley,
Manivannan Sadhasivam, Peter Wang, linux-scsi, linux-kernel,
stanleyjhu, stable
In MCQ mode, ufshcd_mcq_compl_pending_transfer() uses
blk_mq_tagset_busy_iter() to iterate over busy requests during error
recovery and host reset. However, both iterator callbacks perform
whole-queue operations redundantly for each visited request:
- force_compl == true: ufshcd_mcq_force_compl_one() calls
ufshcd_mcq_compl_all_cqes_lock() on every busy request, sweeping the
entire completion ring (hwq->max_entries slots) once per active
request under spin_lock_irqsave even though the first sweep already
cleared all completion entries.
- force_compl == false: ufshcd_mcq_compl_one() acquires cq_lock and
polls CQTPy over MMIO via ufshcd_mcq_poll_cqe_lock() for every busy
request without doing any per-request work.
Sweep or poll each hardware queue (hba->uhq[i]) once at the start of
ufshcd_mcq_compl_pending_transfer(). When force_compl is true, run
blk_mq_tagset_busy_iter() afterward to complete residual in-flight
requests with DID_REQUEUE, and remove the now-unused
ufshcd_mcq_compl_one() callback.
Fixes: ab248643d3d6 ("scsi: ufs: core: Add error handling for MCQ mode")
Cc: stable@vger.kernel.org
Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
---
drivers/ufs/core/ufshcd.c | 31 ++++++++++++-------------------
1 file changed, 12 insertions(+), 19 deletions(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 2ba244cf40ac..a69dcb04d985 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -6044,8 +6044,6 @@ static bool ufshcd_mcq_force_compl_one(struct request *rq, void *priv)
if (blk_mq_is_reserved_rq(rq) || !hwq)
return true;
- ufshcd_mcq_compl_all_cqes_lock(hba, hwq);
-
/*
* For those cmds of which the cqes are not present in the cq, complete
* them explicitly.
@@ -6061,19 +6059,6 @@ static bool ufshcd_mcq_force_compl_one(struct request *rq, void *priv)
return true;
}
-static bool ufshcd_mcq_compl_one(struct request *rq, void *priv)
-{
- struct scsi_device *sdev = rq->q->queuedata;
- struct Scsi_Host *shost = sdev->host;
- struct ufs_hba *hba = shost_priv(shost);
- struct ufs_hw_queue *hwq = ufshcd_mcq_req_to_hwq(hba, rq);
-
- if (!blk_mq_is_reserved_rq(rq) && hwq)
- ufshcd_mcq_poll_cqe_lock(hba, hwq);
-
- return true;
-}
-
/**
* ufshcd_mcq_compl_pending_transfer - MCQ mode function. It is
* invoked from the error handler context or ufshcd_host_reset_and_restore()
@@ -6088,10 +6073,18 @@ static bool ufshcd_mcq_compl_one(struct request *rq, void *priv)
static void ufshcd_mcq_compl_pending_transfer(struct ufs_hba *hba,
bool force_compl)
{
- blk_mq_tagset_busy_iter(&hba->host->tag_set,
- force_compl ? ufshcd_mcq_force_compl_one :
- ufshcd_mcq_compl_one,
- NULL);
+ int i;
+
+ for (i = 0; i < hba->nr_hw_queues; i++) {
+ if (force_compl)
+ ufshcd_mcq_compl_all_cqes_lock(hba, &hba->uhq[i]);
+ else
+ ufshcd_mcq_poll_cqe_lock(hba, &hba->uhq[i]);
+ }
+
+ if (force_compl)
+ blk_mq_tagset_busy_iter(&hba->host->tag_set,
+ ufshcd_mcq_force_compl_one, NULL);
}
/**
--
2.55.0.1082.g2b9226bbc0-goog
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ
2026-09-18 14:38 ` [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ Stanley Jhu
@ 2026-09-18 16:06 ` Bart Van Assche
2026-09-20 13:49 ` Stanley Jhu
0 siblings, 1 reply; 13+ messages in thread
From: Bart Van Assche @ 2026-09-18 16:06 UTC (permalink / raw)
To: Stanley Jhu, Martin K . Petersen, Bean Huo
Cc: Alim Akhtar, Avri Altman, James E . J . Bottomley,
Manivannan Sadhasivam, Peter Wang, linux-scsi, linux-kernel,
stable
On 9/18/26 7:38 AM, Stanley Jhu wrote:
> In MCQ mode, ufshcd_mcq_compl_pending_transfer() uses
> blk_mq_tagset_busy_iter() to iterate over busy requests during error
> recovery and host reset. However, both iterator callbacks perform
> whole-queue operations redundantly for each visited request:
>
> - force_compl == true: ufshcd_mcq_force_compl_one() calls
> ufshcd_mcq_compl_all_cqes_lock() on every busy request, sweeping the
> entire completion ring (hwq->max_entries slots) once per active
> request under spin_lock_irqsave even though the first sweep already
> cleared all completion entries.
> - force_compl == false: ufshcd_mcq_compl_one() acquires cq_lock and
> polls CQTPy over MMIO via ufshcd_mcq_poll_cqe_lock() for every busy
> request without doing any per-request work.
>
> Sweep or poll each hardware queue (hba->uhq[i]) once at the start of
> ufshcd_mcq_compl_pending_transfer(). When force_compl is true, run
> blk_mq_tagset_busy_iter() afterward to complete residual in-flight
> requests with DID_REQUEUE, and remove the now-unused
> ufshcd_mcq_compl_one() callback.
Forcibly completing SCSI commands from inside the UFS SCSI host reset
error handling callback is incompatible with the SCSI core error
handler. The "force_compl" behavior should be removed instead of
reworking it. If you take a look at the SDB (single doorbell) code you
will see that forcibly completing requests doesn't happen for SDB mode.
Bart.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock()
2026-09-01 12:23 [PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Stanley Jhu
2026-09-18 14:38 ` [PATCH v2 0/2] scsi: ufs: core: Fix unsafe MMIO reads and redundant CQ sweeps in MCQ reset Stanley Jhu
@ 2026-09-18 22:15 ` Bart Van Assche
1 sibling, 0 replies; 13+ messages in thread
From: Bart Van Assche @ 2026-09-18 22:15 UTC (permalink / raw)
To: Stanley Jhu, Martin K . Petersen, James E . J . Bottomley
Cc: Alim Akhtar, Avri Altman, Peter Wang, quic_cang, quic_nguyenb,
linux-scsi, linux-kernel, stable
On 9/1/26 5:23 AM, Stanley Jhu wrote:
> Reading host controller registers (such as CQTP) is unsafe when the
> host controller is disabled (HCE = 0), as accessing registers in an
> unclocked or reset state can cause bus stalls and system hangs.
>
> In ufshcd_mcq_compl_all_cqes_lock(), all completion queue entries have
> already been inspected, processed, and cleared in memory, so the
> software queue is logically empty.
>
> Avoid the unsafe MMIO read of CQTP by synchronizing hwq->cq_tail_slot
> directly to hwq->cq_head_slot in software. Upon subsequent controller
> re-initialization, ufshcd_mcq_make_queues_operational() will
> reconfigure and re-zero all queue pointers.
ufshcd_mcq_compl_all_cqes_lock() is only used to forcibly complete UFS
commands. The UFS driver should not forcibly complete UFS commands from
inside its error handler. Please remove the
ufshcd_mcq_compl_all_cqes_lock() function.
Thanks,
Bart.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ
2026-09-18 16:06 ` Bart Van Assche
@ 2026-09-20 13:49 ` Stanley Jhu
2026-09-21 17:13 ` Bart Van Assche
2026-09-22 7:36 ` Peter Wang
0 siblings, 2 replies; 13+ messages in thread
From: Stanley Jhu @ 2026-09-20 13:49 UTC (permalink / raw)
To: Bart Van Assche
Cc: Stanley Jhu, linux-scsi, Martin K. Petersen,
James E.J. Bottomley, Alim Akhtar, Avri Altman, Peter Wang,
Bean Huo, Bao D. Nguyen, Can Guo, Manivannan Sadhasivam,
linux-kernel
On 9/18/26 9:06 AM, Bart Van Assche wrote:
> Forcibly completing SCSI commands from inside the UFS SCSI host reset
> error handling callback is incompatible with the SCSI core error
> handler. The "force_compl" behavior should be removed instead of
> reworking it. If you take a look at the SDB (single doorbell) code you
> will see that forcibly completing requests doesn't happen for SDB mode.
Note that ufshcd_mcq_force_compl_one() already checks
!test_bit(SCMD_STATE_COMPLETE, &cmd->state), so it only completes non-EH
commands (e.g. during an autonomous ufshcd_err_handler() reset); in SDB
mode, ufshcd_hba_stop() (HCE = 0) clears UTRLDBR to 0, so ufshcd_poll()
similarly treats all outstanding_reqs as completed right after
ufshcd_hba_stop().
That said, doing this inside ufshcd_host_reset_and_restore() right after
ufshcd_hba_stop() is indeed the wrong place: at controller stop time we
should only release LLD resources (ufshcd_release_scsi_cmd()), and
requeue any remaining non-EH (!SCMD_STATE_COMPLETE) commands with
DID_REQUEUE only after host/link recovery finishes (so autonomous resets
neither wake callers mid-reset nor leave in-flight I/O stalled for the
30s block layer timeout, similar to autonomous reset handling in
hisi_sas, megaraid_sas, and smartpqi).
Let's drop this v2 series. I will send a separate 2-patch series shortly
to replace this and remove force_compl and
ufshcd_mcq_compl_all_cqes_lock().
Thanks,
Stanley
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ
2026-09-20 13:49 ` Stanley Jhu
@ 2026-09-21 17:13 ` Bart Van Assche
2026-09-22 7:37 ` Peter Wang
2026-09-22 7:36 ` Peter Wang
1 sibling, 1 reply; 13+ messages in thread
From: Bart Van Assche @ 2026-09-21 17:13 UTC (permalink / raw)
To: Stanley Jhu
Cc: linux-scsi, Martin K. Petersen, James E.J. Bottomley,
Alim Akhtar, Avri Altman, Peter Wang, Bean Huo, Bao D. Nguyen,
Can Guo, Manivannan Sadhasivam, linux-kernel
On 9/20/26 6:49 AM, Stanley Jhu wrote:
> On 9/18/26 9:06 AM, Bart Van Assche wrote:
>> Forcibly completing SCSI commands from inside the UFS SCSI host reset
>> error handling callback is incompatible with the SCSI core error
>> handler. The "force_compl" behavior should be removed instead of
>> reworking it. If you take a look at the SDB (single doorbell) code you
>> will see that forcibly completing requests doesn't happen for SDB mode.
>
> Note that ufshcd_mcq_force_compl_one() already checks
> !test_bit(SCMD_STATE_COMPLETE, &cmd->state), so it only completes non-EH
> commands (e.g. during an autonomous ufshcd_err_handler() reset);
What are "non-EH" commands? The SCSI error handler only starts its
error handling strategy after all pending commands have either timed
out or completed.
I think that you are misunderstanding the code. The purpose of the
SCMD_STATE_COMPLETE check is to prevent double completions of SCSI
commands.
> in SDB mode, ufshcd_hba_stop() (HCE = 0) clears UTRLDBR to 0, so
> ufshcd_poll() similarly treats all outstanding_reqs as completed
> right after ufshcd_hba_stop().
>
> That said, doing this inside ufshcd_host_reset_and_restore() right after
> ufshcd_hba_stop() is indeed the wrong place: at controller stop time we
> should only release LLD resources (ufshcd_release_scsi_cmd()), and
> requeue any remaining non-EH (!SCMD_STATE_COMPLETE) commands with
> DID_REQUEUE only after host/link recovery finishes (so autonomous resets
> neither wake callers mid-reset nor leave in-flight I/O stalled for the
> 30s block layer timeout, similar to autonomous reset handling in
> hisi_sas, megaraid_sas, and smartpqi).
In SDB mode, clearing UTRLDBR will cause all pending commands to be
requeued because the OCS member is initialized to
OCS_INVALID_COMMAND_STATUS and because ufshcd_transfer_rsp_status()
translates this status value into DID_REQUEUE << 16. I'm concerned
that this approach may cause the deadlines for SCSI commands to be
exceeded. Hence my proposal for MCQ mode not to requeue pending SCSI
commands but instead to let the SCSI error handler decide what to do
with these commands.
Thanks,
Bart.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 1/2] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock()
2026-09-18 14:38 ` [PATCH v2 1/2] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Stanley Jhu
@ 2026-09-22 3:05 ` Peter Wang
0 siblings, 0 replies; 13+ messages in thread
From: Peter Wang @ 2026-09-22 3:05 UTC (permalink / raw)
To: Stanley Jhu, Martin K . Petersen, Bean Huo, Bart Van Assche
Cc: Alim Akhtar, Avri Altman, James E . J . Bottomley,
Manivannan Sadhasivam, linux-scsi, linux-kernel, stable
On Fri, 2026-09-18 at 22:38 +0800, Stanley Jhu wrote:
> During MCQ host reset, ufshcd_host_reset_and_restore() stops the host
> controller via ufshcd_hba_stop() (HCE = 0) before calling
> ufshcd_complete_requests(hba, true) ->
> ufshcd_mcq_compl_pending_transfer(hba, true) ->
> ufshcd_mcq_force_compl_one() -> ufshcd_mcq_compl_all_cqes_lock().
> Because ufshcd_mcq_force_compl_one() is its sole caller,
> ufshcd_mcq_compl_all_cqes_lock() always runs with HCE = 0.
>
> Despite the comment above ufshcd_mcq_compl_all_cqes_lock() stating
> that
> reading CQTPy may not be safe with the controller disabled, the
> function
> still calls ufshcd_mcq_update_cq_tail_slot() at the end of its sweep:
>
> 1. Unsafe CQTPy MMIO read:
> Calling ufshcd_mcq_update_cq_tail_slot() at the end of the sweep
> reads CQTPy over MMIO while HCE = 0, directly contradicting the
> function's documented contract (commit 1373df88d535 ("scsi: ufs:
> core: Add a comment block above
> ufshcd_mcq_compl_all_cqes_lock()"))
> that reading CQTPy may not be safe with the controller disabled.
>
> 2. Spurious error logs on empty slots:
> Sweeping all max_entries slots visits empty entries where
> command_desc_base_addr is 0, causing ufshcd_mcq_process_cqe() to
> log
> unguarded dev_err(hba->dev, "Abnormal CQ entry!\n") messages.
>
> Fix both issues in ufshcd_mcq_compl_all_cqes_lock():
> - Synchronize hwq->cq_tail_slot = hwq->cq_head_slot in software after
> sweeping the ring, avoiding CQTPy MMIO reads while HCE = 0.
> - Extract ufshcd_mcq_compl_cqe() and invoke it only on non-empty
> slots
> during full-ring sweeps, keeping "Abnormal CQ entry!" logging
> strictly
> for unexpected empty entries in ufshcd_mcq_poll_cqe_lock().
>
> Fixes: ab248643d3d6 ("scsi: ufs: core: Add error handling for MCQ
> mode")
> Cc: stable@vger.kernel.org
> Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
> ---
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ
2026-09-20 13:49 ` Stanley Jhu
2026-09-21 17:13 ` Bart Van Assche
@ 2026-09-22 7:36 ` Peter Wang
1 sibling, 0 replies; 13+ messages in thread
From: Peter Wang @ 2026-09-22 7:36 UTC (permalink / raw)
To: Stanley Jhu, Bart Van Assche
Cc: linux-scsi, Martin K. Petersen, James E.J. Bottomley,
Alim Akhtar, Avri Altman, Bean Huo, Bao D. Nguyen, Can Guo,
Manivannan Sadhasivam, linux-kernel
On Sun, 2026-09-20 at 21:49 +0800, Stanley Jhu wrote:
> That said, doing this inside ufshcd_host_reset_and_restore() right
> after
> ufshcd_hba_stop() is indeed the wrong place: at controller stop time
Hi Stanley,
I have different idea. The original design was that only after
the HBA stop can we ensure the host will no longer process the
remaining commands (those that need to be forcibly requeued)
due to receiving IRQs or other factors, thus avoiding unnecessary
racing. Both SDB and MCQ modes are implemented based on this idea.
However, MCQ indeed does not need to read the CQ register to update
the CQ, because it holds no meaning after the host reset either.
Thanks
Peter
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ
2026-09-21 17:13 ` Bart Van Assche
@ 2026-09-22 7:37 ` Peter Wang
2026-09-22 16:30 ` Bart Van Assche
0 siblings, 1 reply; 13+ messages in thread
From: Peter Wang @ 2026-09-22 7:37 UTC (permalink / raw)
To: Bart Van Assche, Stanley Jhu
Cc: linux-scsi, Martin K. Petersen, James E.J. Bottomley,
Alim Akhtar, Avri Altman, Bean Huo, Bao D. Nguyen, Can Guo,
Manivannan Sadhasivam, linux-kernel
On Mon, 2026-09-21 at 10:13 -0700, Bart Van Assche wrote:
> In SDB mode, clearing UTRLDBR will cause all pending commands to be
> requeued because the OCS member is initialized to
> OCS_INVALID_COMMAND_STATUS and because ufshcd_transfer_rsp_status()
> translates this status value into DID_REQUEUE << 16. I'm concerned
> that this approach may cause the deadlines for SCSI commands to be
> exceeded. Hence my proposal for MCQ mode not to requeue pending SCSI
> commands but instead to let the SCSI error handler decide what to do
> with these commands.
>
Hi Bart,
The current MCQ flow is similar to SDB. We discussed this two years
ago.
Aborted commands will be requeued immediately, just like in SDB mode
https://patchwork.kernel.org/project/linux-scsi/list/?series=894411&state=*
Thanks
Peter
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ
2026-09-22 7:37 ` Peter Wang
@ 2026-09-22 16:30 ` Bart Van Assche
0 siblings, 0 replies; 13+ messages in thread
From: Bart Van Assche @ 2026-09-22 16:30 UTC (permalink / raw)
To: Peter Wang, Stanley Jhu
Cc: linux-scsi, Martin K. Petersen, James E.J. Bottomley,
Alim Akhtar, Avri Altman, Bean Huo, Bao D. Nguyen, Can Guo,
Manivannan Sadhasivam, linux-kernel
On 9/22/26 12:37 AM, Peter Wang wrote:
> On Mon, 2026-09-21 at 10:13 -0700, Bart Van Assche wrote:
>> In SDB mode, clearing UTRLDBR will cause all pending commands to be
>> requeued because the OCS member is initialized to
>> OCS_INVALID_COMMAND_STATUS and because ufshcd_transfer_rsp_status()
>> translates this status value into DID_REQUEUE << 16. I'm concerned
>> that this approach may cause the deadlines for SCSI commands to be
>> exceeded. Hence my proposal for MCQ mode not to requeue pending SCSI
>> commands but instead to let the SCSI error handler decide what to do
>> with these commands.
>
> The current MCQ flow is similar to SDB. We discussed this two years
> ago.
> Aborted commands will be requeued immediately, just like in SDB mode
A SCSI host controller reset must abort all pending commands. Requeuing
SCSI commands during a host controller reset violates the API contract
between the SCSI error handler and SCSI LLDs. I'm not aware of any other
SCSI LLD than the UFS host controller driver that requeues pending
commands upon a host controller reset instead of aborting these.
.eh_host_reset_handler() is expected to reset all logical units and the
host controller. The SCSI architecture manual (SAM) mentions explicitly
that resetting logical units involves aborting all commands.
Thanks,
Bart.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ
@ 2026-09-22 6:13 Peter Wang (王信友)
0 siblings, 0 replies; 13+ messages in thread
From: Peter Wang (王信友) @ 2026-09-22 6:13 UTC (permalink / raw)
To: Stanley Jhu, Bart Van Assche
Cc: linux-scsi, Martin K. Petersen, James E.J. Bottomley,
Alim Akhtar, Avri Altman, Bean Huo, Bao D. Nguyen, Can Guo,
Manivannan Sadhasivam, linux-kernel
[-- Attachment #1: winmail.dat --]
[-- Type: application/ms-tnef, Size: 12707 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-09-22 16:30 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-01 12:23 [PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Stanley Jhu
2026-09-18 14:38 ` [PATCH v2 0/2] scsi: ufs: core: Fix unsafe MMIO reads and redundant CQ sweeps in MCQ reset Stanley Jhu
2026-09-18 14:38 ` [PATCH v2 1/2] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Stanley Jhu
2026-09-22 3:05 ` Peter Wang
2026-09-18 14:38 ` [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ Stanley Jhu
2026-09-18 16:06 ` Bart Van Assche
2026-09-20 13:49 ` Stanley Jhu
2026-09-21 17:13 ` Bart Van Assche
2026-09-22 7:37 ` Peter Wang
2026-09-22 16:30 ` Bart Van Assche
2026-09-22 7:36 ` Peter Wang
2026-09-18 22:15 ` [PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock() Bart Van Assche
2026-09-22 6:13 [PATCH v2 2/2] scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ Peter Wang (王信友)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®