summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaniv Gardi <ygardi@codeaurora.org>2015-04-01 17:05:01 +0300
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 10:59:47 -0700
commit33e8deb4418fd60ed58e95bad31dfd57f9c9287e (patch)
tree25d3d9ed8e009afd0a8368146f965739b8cd491e
parentd53a1c974d8990e9bcc72d52a734e7680f514f03 (diff)
scsi: ufs: add debugfs for error injection statistics
This change adds a capability to record how many errors are injected per error scenario, and also the debugfs entry to read them and to reset them. cat /d/ufshcd0/err_inj_stats to analyze how many error were injected per error scenario echo 1 > /d/ufshcd0/err_inj_stats (or any other value, to reset all statistics) Change-Id: Ide06c30d1a9d3b65df99cd8bc24cffecc9a4b724 Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
-rw-r--r--drivers/scsi/ufs/ufs-debugfs.c56
-rw-r--r--drivers/scsi/ufs/ufshcd.h1
2 files changed, 57 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index 975bbc655986..7ef0fcb1937b 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -65,6 +65,7 @@ struct ufsdbg_err_scenario {
u32 err_code_mask;
const int *err_code_arr;
u32 num_err_codes;
+ u32 num_err_injected;
};
/*
@@ -355,6 +356,7 @@ void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba,
should_fail:
*ret_value = opt_ret;
+ err_scen_arr[usecase].num_err_injected++;
pr_debug("%s: error code index [%d], error code %d (0x%x) is injected for scenario \"%s\"\n",
__func__, err_code_index, *ret_value, *ret_value,
err_scen_arr[usecase].name);
@@ -438,6 +440,47 @@ static const struct file_operations ufsdbg_err_code_ops = {
.write = ufsdbg_err_code_write,
};
+static int ufsdbg_err_inj_stats_read(struct seq_file *file, void *data)
+{
+ enum ufsdbg_err_inject_scenario err;
+
+ seq_printf(file, "%-40s %-20s\n",
+ "Error Scenario:", "Num of Errors Injected");
+
+ for (err = 0; err < ERR_INJECT_MAX_ERR_SCENARIOS; err++) {
+ seq_printf(file, "%-40s %-20d\n",
+ err_scen_arr[err].name,
+ err_scen_arr[err].num_err_injected);
+ }
+
+ return 0;
+}
+
+static
+int ufsdbg_err_inj_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file,
+ ufsdbg_err_inj_stats_read, inode->i_private);
+}
+
+static ssize_t ufsdbg_err_inj_stats_write(struct file *file,
+ const char __user *ubuf, size_t cnt,
+ loff_t *ppos)
+{
+ enum ufsdbg_err_inject_scenario err;
+
+ for (err = 0; err < ERR_INJECT_MAX_ERR_SCENARIOS; err++)
+ err_scen_arr[err].num_err_injected = 0;
+
+ return cnt;
+}
+
+static const struct file_operations ufsdbg_err_inj_stats_ops = {
+ .open = ufsdbg_err_inj_stats_open,
+ .read = seq_read,
+ .write = ufsdbg_err_inj_stats_write,
+};
+
static void ufsdbg_setup_fault_injection(struct ufs_hba *hba)
{
struct dentry *fault_dir;
@@ -484,8 +527,21 @@ static void ufsdbg_setup_fault_injection(struct ufs_hba *hba)
goto fail_err_inj_codes;
}
+ hba->debugfs_files.err_inj_stats =
+ debugfs_create_file("err_inj_stats", S_IRUSR | S_IWUSR,
+ hba->debugfs_files.debugfs_root, hba,
+ &ufsdbg_err_inj_stats_ops);
+ if (!hba->debugfs_files.err_inj_stats) {
+ dev_err(hba->dev,
+ "%s: failed create err_inj_stats debugfs entry\n",
+ __func__);
+ goto fail_err_inj_stats;
+ }
+
return;
+fail_err_inj_stats:
+ debugfs_remove(hba->debugfs_files.err_inj_codes);
fail_err_inj_codes:
debugfs_remove(hba->debugfs_files.err_inj_scenario);
fail_err_inj_scenario:
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 58126491f624..806d8bafb79f 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -480,6 +480,7 @@ struct debugfs_files {
#ifdef CONFIG_UFS_FAULT_INJECTION
struct dentry *err_inj_codes;
struct dentry *err_inj_scenario;
+ struct dentry *err_inj_stats;
u32 err_inj_scenario_mask;
struct fault_attr fail_attr;
#endif