[PATCH] scsi: ufs: core: Add fault injection for task abort failures

From: Stanley Jhu

Date: Thu Sep 03 2026 - 19:53:20 EST


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@xxxxxxxxxx>
---
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