Commit 045da307 authored by Akinobu Mita's avatar Akinobu Mita Committed by Martin K. Petersen

scsi: ufs: core: Make fault injection dynamically configurable per HBA

The UFS driver has two driver-specific fault injection mechanisms
(trigger_eh and timeout). Each fault injection configuration can only be
specified by a module parameter and cannot be reconfigured without
reloading the driver. Also, each configuration is common to all HBAs.

This change adds the following subdirectories for each UFS HBA when
debugfs is enabled:

  /sys/kernel/debug/ufshcd/<HBA>/timeout_inject
  /sys/kernel/debug/ufshcd/<HBA>/trigger_eh_inject

Each fault injection attribute can be dynamically set per HBA by a
corresponding file in these directories.

This is tested with QEMU UFS devices.
Signed-off-by: default avatarAkinobu Mita <akinobu.mita@gmail.com>
Link: https://lore.kernel.org/r/20231118124443.1007116-1-akinobu.mita@gmail.comReviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent edbc78a1
......@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <linux/fault-inject.h>
#include <linux/module.h>
#include <ufs/ufshcd.h>
#include "ufs-fault-injection.h"
static int ufs_fault_get(char *buffer, const struct kernel_param *kp);
......@@ -59,12 +60,22 @@ static int ufs_fault_set(const char *val, const struct kernel_param *kp)
return 0;
}
bool ufs_trigger_eh(void)
void ufs_fault_inject_hba_init(struct ufs_hba *hba)
{
return should_fail(&ufs_trigger_eh_attr, 1);
hba->trigger_eh_attr = ufs_trigger_eh_attr;
hba->timeout_attr = ufs_timeout_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);
#endif
}
bool ufs_fail_completion(void)
bool ufs_trigger_eh(struct ufs_hba *hba)
{
return should_fail(&ufs_timeout_attr, 1);
return should_fail(&hba->trigger_eh_attr, 1);
}
bool ufs_fail_completion(struct ufs_hba *hba)
{
return should_fail(&hba->timeout_attr, 1);
}
......@@ -7,15 +7,20 @@
#include <linux/types.h>
#ifdef CONFIG_SCSI_UFS_FAULT_INJECTION
bool ufs_trigger_eh(void);
bool ufs_fail_completion(void);
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);
#else
static inline bool ufs_trigger_eh(void)
static inline void ufs_fault_inject_hba_init(struct ufs_hba *hba)
{
}
static inline bool ufs_trigger_eh(struct ufs_hba *hba)
{
return false;
}
static inline bool ufs_fail_completion(void)
static inline bool ufs_fail_completion(struct ufs_hba *hba)
{
return false;
}
......
......@@ -2992,7 +2992,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
ufshcd_send_command(hba, tag, hwq);
out:
if (ufs_trigger_eh()) {
if (ufs_trigger_eh(hba)) {
unsigned long flags;
spin_lock_irqsave(hba->host->host_lock, flags);
......@@ -5649,7 +5649,7 @@ static irqreturn_t ufshcd_transfer_req_compl(struct ufs_hba *hba)
!(hba->quirks & UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR))
ufshcd_reset_intr_aggr(hba);
if (ufs_fail_completion())
if (ufs_fail_completion(hba))
return IRQ_HANDLED;
/*
......@@ -9348,6 +9348,7 @@ static int ufshcd_hba_init(struct ufs_hba *hba)
goto out_disable_vreg;
ufs_debugfs_hba_init(hba);
ufs_fault_inject_hba_init(hba);
hba->is_powered = true;
goto out;
......
......@@ -16,6 +16,7 @@
#include <linux/blk-crypto-profile.h>
#include <linux/blk-mq.h>
#include <linux/devfreq.h>
#include <linux/fault-inject.h>
#include <linux/msi.h>
#include <linux/pm_runtime.h>
#include <linux/dma-direction.h>
......@@ -1057,6 +1058,10 @@ struct ufs_hba {
struct dentry *debugfs_root;
struct delayed_work debugfs_ee_work;
u32 debugfs_ee_rate_limit_ms;
#endif
#ifdef CONFIG_SCSI_UFS_FAULT_INJECTION
struct fault_attr trigger_eh_attr;
struct fault_attr timeout_attr;
#endif
u32 luns_avail;
unsigned int nr_hw_queues;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment