* [PATCH] scsi: ufs: core: Add fault injection for task abort failures
@ 2026-09-03 23:53 Stanley Jhu
2026-09-18 13:26 ` Stanley Jhu
0 siblings, 1 reply; 2+ messages in thread
From: Stanley Jhu @ 2026-09-03 23:53 UTC (permalink / raw)
To: Martin K . Petersen, James E . J . Bottomley
Cc: Bart Van Assche, Alim Akhtar, Avri Altman, Peter Wang, Bean Huo,
Can Guo, Hyeoncheol Jeong, Po-Wen Kao, linux-scsi, linux-kernel,
Stanley Jhu
Commit 045da3077bc5 ("scsi: ufs: core: Make fault injection dynamically
configurable per HBA") added fault injection support for UFS error
handling and completion timeouts. However, there was no fault
injection capability to simulate task abort failures.
Both legacy single-doorbell mode (in ufshcd_abort()) and MCQ mode (in
ufshcd_mcq_abort()) invoke ufshcd_try_to_abort_task() to query device
status and execute task aborts.
Add fault injection support for task abort:
- Add "abort" module parameter and "abort_inject" debugfs attribute.
- Hook ufs_fail_abort() at the entry of ufshcd_try_to_abort_task() to
short-circuit task abort with -EIO. This universally simulates task
abort failure across both single-doorbell and MCQ modes without
incurring query polling delays.
Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
---
drivers/ufs/core/ufs-fault-injection.c | 15 +++++++++++++++
drivers/ufs/core/ufs-fault-injection.h | 6 ++++++
drivers/ufs/core/ufshcd.c | 2 ++
include/ufs/ufshcd.h | 1 +
4 files changed, 24 insertions(+)
diff --git a/drivers/ufs/core/ufs-fault-injection.c b/drivers/ufs/core/ufs-fault-injection.c
index 55db38e75cc4..25ae763da4f6 100644
--- a/drivers/ufs/core/ufs-fault-injection.c
+++ b/drivers/ufs/core/ufs-fault-injection.c
@@ -34,6 +34,12 @@ MODULE_PARM_DESC(timeout,
"Fault injection. timeout=<interval>,<probability>,<space>,<times>");
static DECLARE_FAULT_ATTR(ufs_timeout_attr);
+static char g_abort_str[FAULT_INJ_STR_SIZE];
+module_param_cb(abort, &ufs_fault_ops, g_abort_str, 0644);
+MODULE_PARM_DESC(abort,
+ "Fault injection. abort=<interval>,<probability>,<space>,<times>");
+static DECLARE_FAULT_ATTR(ufs_abort_attr);
+
static int ufs_fault_get(char *buffer, const struct kernel_param *kp)
{
const char *fault_str = kp->arg;
@@ -49,6 +55,8 @@ static int ufs_fault_set(const char *val, const struct kernel_param *kp)
attr = &ufs_trigger_eh_attr;
else if (kp->arg == g_timeout_str)
attr = &ufs_timeout_attr;
+ else if (kp->arg == g_abort_str)
+ attr = &ufs_abort_attr;
if (WARN_ON_ONCE(!attr))
return -EINVAL;
@@ -65,9 +73,11 @@ void ufs_fault_inject_hba_init(struct ufs_hba *hba)
{
hba->trigger_eh_attr = ufs_trigger_eh_attr;
hba->timeout_attr = ufs_timeout_attr;
+ hba->abort_attr = ufs_abort_attr;
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
fault_create_debugfs_attr("trigger_eh_inject", hba->debugfs_root, &hba->trigger_eh_attr);
fault_create_debugfs_attr("timeout_inject", hba->debugfs_root, &hba->timeout_attr);
+ fault_create_debugfs_attr("abort_inject", hba->debugfs_root, &hba->abort_attr);
#endif
}
@@ -80,3 +90,8 @@ bool ufs_fail_completion(struct ufs_hba *hba)
{
return should_fail(&hba->timeout_attr, 1);
}
+
+bool ufs_fail_abort(struct ufs_hba *hba)
+{
+ return should_fail(&hba->abort_attr, 1);
+}
diff --git a/drivers/ufs/core/ufs-fault-injection.h b/drivers/ufs/core/ufs-fault-injection.h
index d0c870e19f0e..56725e3d4556 100644
--- a/drivers/ufs/core/ufs-fault-injection.h
+++ b/drivers/ufs/core/ufs-fault-injection.h
@@ -12,6 +12,7 @@ struct ufs_hba;
void ufs_fault_inject_hba_init(struct ufs_hba *hba);
bool ufs_trigger_eh(struct ufs_hba *hba);
bool ufs_fail_completion(struct ufs_hba *hba);
+bool ufs_fail_abort(struct ufs_hba *hba);
#else
static inline void ufs_fault_inject_hba_init(struct ufs_hba *hba)
{
@@ -26,6 +27,11 @@ static inline bool ufs_fail_completion(struct ufs_hba *hba)
{
return false;
}
+
+static inline bool ufs_fail_abort(struct ufs_hba *hba)
+{
+ return false;
+}
#endif
#endif /* _UFS_FAULT_INJECTION_H */
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 2ba244cf40ac..a25b6a0cb5c6 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -7990,6 +7990,8 @@ int ufshcd_try_to_abort_task(struct ufs_hba *hba, int tag)
return -EINVAL;
lrbp = scsi_cmd_priv(cmd);
+ if (ufs_fail_abort(hba))
+ return -EIO;
for (poll_cnt = 100; poll_cnt; poll_cnt--) {
err = ufshcd_issue_tm_cmd(hba, lrbp->lun, tag, UFS_QUERY_TASK,
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index dfd302f2dc7c..dbf326efdbc4 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -1245,6 +1245,7 @@ struct ufs_hba {
#ifdef CONFIG_SCSI_UFS_FAULT_INJECTION
struct fault_attr trigger_eh_attr;
struct fault_attr timeout_attr;
+ struct fault_attr abort_attr;
#endif
u32 luns_avail;
unsigned int nr_hw_queues;
--
2.55.0.970.g62bdec98f9-goog
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] scsi: ufs: core: Add fault injection for task abort failures
2026-09-03 23:53 [PATCH] scsi: ufs: core: Add fault injection for task abort failures Stanley Jhu
@ 2026-09-18 13:26 ` Stanley Jhu
0 siblings, 0 replies; 2+ messages in thread
From: Stanley Jhu @ 2026-09-18 13:26 UTC (permalink / raw)
To: Peter Wang
Cc: Martin K . Petersen, James E . J . Bottomley, Bart Van Assche,
Alim Akhtar, Avri Altman, Bean Huo, Can Guo, Hyeoncheol Jeong,
linux-scsi, linux-kernel
On 9/18/26 6:08 PM, Peter Wang (王信友) wrote:
> The task-abort-fail injection bypasses ufshcd_issue_tm_cmd.
> However, ufshcd_issue_tm_cmd can return different results that
> involve the device and the underlying hardware. Because each result
> may require a different handling flow, a pure injection cannot cover
> all of these error paths?
Agreed. Short-circuiting ufshcd_try_to_abort_task() with -EIO bypasses
ufshcd_issue_tm_cmd() entirely and does not exercise the distinct TMR
response codes or hardware timeout paths.
When re-checking the call graph on an unmodified upstream kernel, there
is an even more fundamental problem with hooking
ufshcd_try_to_abort_task():
- ufs_fail_completion() is only called in ufshcd_transfer_req_compl()
(the legacy single-doorbell completion path) and never in the MCQ
completion path (ufshcd_mcq_poll_cqe_lock()), so timeout_inject
cannot trigger ufshcd_mcq_abort() under MCQ.
- Under single-doorbell mode, the controller has already cleared the
doorbell bit by the time the block-layer timeout fires, so
ufshcd_abort() hits !(reg & (1 << tag)), completes the command, and
returns before ever reaching ufshcd_try_to_abort_task().
Thanks,
Stanley
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-18 13:26 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-03 23:53 [PATCH] scsi: ufs: core: Add fault injection for task abort failures Stanley Jhu
2026-09-18 13:26 ` Stanley Jhu
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®