FAILED: patch "[PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in" failed to apply to 6.6-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x 375f3a5691dd46b5d05b90a8968872ec8b2248c5
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026101216-sharpener-discover-cc77@gregkh' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 375f3a5691dd46b5d05b90a8968872ec8b2248c5 Mon Sep 17 00:00:00 2001
From: Stanley Jhu <[email protected]>
Date: Mon, 28 Sep 2026 11:58:15 +0800
Subject: [PATCH] scsi: ufs: core: Avoid unsafe MMIO reads in
ufshcd_mcq_compl_all_cqes_lock()
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():
- Remove the ufshcd_mcq_update_cq_tail_slot() call and the redundant hwq->cq_head_slot = hwq->cq_tail_slot assignment without replacement. The two indices are already equal after the sweep: they are equal when the sweep starts, since ufshcd_mcq_poll_cqe_lock() consumes entries until cq_head_slot reaches cq_tail_slot, and the sweep advances cq_head_slot by exactly one full ring. Both indices are also reinitialized before the queue is reused.
- 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().
drivers/ufs/core/ufs-mcq.c +17 -13
@@ -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 processing the CQE, mark it as an 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,13 @@ 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;spin_unlock_irqrestore (&hwq->cq_lock, flags); }
Sasha Levin
maintainerPATCH 1/5 scsi: ufs: mcq: Remove unused parameters
From: ChanWoo Lee <[email protected]>
[ Upstream commit 01f256228c0f89c4b48fbc7c67b64a26cdcfd740 ]
The 'hwq' parameter is not used in this function. Remove unused parameters.
Stable-dep-of: 375f3a5691dd ("scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock()")
--- drivers/ufs/core/ufs-mcq.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/ufs/core/ufs-mcq.c +2 -4
@@ -255,9 +255,7 @@ EXPORT_SYMBOL_GPL(ufshcd_mcq_write_cqis);* Current MCQ specification doesn't provide a Task Tag or its equivalent in * the Completion Queue Entry. Find the Task Tag using an indirect method. */ -static int ufshcd_mcq_get_tag (struct ufs_hba *hba, -struct ufs_hw_queue *hwq, -struct cq_entry *cqe) +static int ufshcd_mcq_get_tag (struct ufs_hba *hba,struct cq_entry *cqe) {u64 addr;
@@ -275,7 +273,7 @@ static void ufshcd_mcq_process_cqe(struct ufs_hba *hba, struct ufs_hw_queue *hwq) {struct cq_entry *cqe =ufshcd_mcq_cur_cqe (hwq); -int tag =ufshcd_mcq_get_tag (hba, hwq, cqe); +int tag =ufshcd_mcq_get_tag (hba, cqe);if (cqe->command_desc_base_addr) {ufshcd_compl_one_cqe (hba, tag, cqe);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/5 scsi: ufs: core: Move an assignment in ufshcd_mcq_process_cqe()
From: Bart Van Assche <[email protected]>
[ Upstream commit dd4299af9b049c0dcb28699327ebc1386aab4b2a ]
Since 'tag' is only used inside the if-statement, move the 'tag' assignment into the if-statement. This patch prepares for introducing a WARN_ON_ONCE() call in ufshcd_mcq_get_tag() if the tag lookup fails.
Stable-dep-of: 375f3a5691dd ("scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock()")
--- drivers/ufs/core/ufs-mcq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/ufs/core/ufs-mcq.c +2 -1
@@ -273,9 +273,10 @@ static void ufshcd_mcq_process_cqe(struct ufs_hba *hba, struct ufs_hw_queue *hwq) {struct cq_entry *cqe =ufshcd_mcq_cur_cqe (hwq); -int tag =ufshcd_mcq_get_tag (hba, cqe);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 ;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/5 scsi: ufs: core: Add debug log for MCQ command timeout
In reply to Sasha LevinFrom: Peter Wang <[email protected]>
[ Upstream commit 3abe4113e784b4a1135fe0e89828afecbfebf862 ]
It is difficult to debug situations where an MCQ command timeout occurs, the corresponding CQ tag response is received, but the request is not completed. Add a one-line log to indicate when the CQ entry is abnormal.
Stable-dep-of: 375f3a5691dd ("scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock()")
--- drivers/ufs/core/ufs-mcq.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/ufs/core/ufs-mcq.c +2 -0
@@ -280,6 +280,8 @@ static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,ufshcd_compl_one_cqe (hba, tag, cqe);/* After processed the cqe, mark it empty (invalid) entry */ cqe->command_desc_base_addr =0 ; + }else { +dev_err (hba->dev,"Abnormal CQ entry!\n" ); } }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 4/5 scsi: ufs: core: Add a comment block above ufshcd_mcq_compl_all_cqes_lock()
In reply to Sasha LevinFrom: Bart Van Assche <[email protected]>
[ Upstream commit 1373df88d53594a32534fd8960c51d1d09be8ecb ]
Document the aspects of ufshcd_mcq_compl_all_cqes_lock() that are nontrivial in a comment block above this function.
Stable-dep-of: 375f3a5691dd ("scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock()")
--- drivers/ufs/core/ufs-mcq.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/ufs/core/ufs-mcq.c +8 -0
@@ -285,6 +285,14 @@ static void ufshcd_mcq_process_cqe(struct ufs_hba *hba, } } +/* +* This function is called from the UFS error handler with the UFS host +* 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 +* has been processed. +*/ void ufshcd_mcq_compl_all_cqes_lock (struct ufs_hba *hba,struct ufs_hw_queue *hwq) {
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 5/5 scsi: ufs: core: Avoid unsafe MMIO reads in ufshcd_mcq_compl_all_cqes_lock()
In reply to Sasha LevinFrom: Stanley Jhu <[email protected]>
[ Upstream commit 375f3a5691dd46b5d05b90a8968872ec8b2248c5 ]
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():
- Remove the ufshcd_mcq_update_cq_tail_slot() call and the redundant hwq->cq_head_slot = hwq->cq_tail_slot assignment without replacement. The two indices are already equal after the sweep: they are equal when the sweep starts, since ufshcd_mcq_poll_cqe_lock() consumes entries until cq_head_slot reaches cq_tail_slot, and the sweep advances cq_head_slot by exactly one full ring. Both indices are also reinitialized before the queue is reused.
- 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().
--- drivers/ufs/core/ufs-mcq.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-)
drivers/ufs/core/ufs-mcq.c +17 -13
@@ -269,20 +269,24 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba, struct cq_entry *cqe)return div_u64 (addr,ufshcd_get_ucd_size (hba)); } +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 processing the CQE, mark it as an 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" ); - } }/*
@@ -290,7 +294,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,
@@ -301,13 +305,13 @@ 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;spin_unlock_irqrestore (&hwq->cq_lock, flags); }
Signature · 1 line
2.53.0