summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaniv Gardi <ygardi@codeaurora.org>2015-03-25 17:59:05 +0200
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 10:59:44 -0700
commit3f8adb02aab70723ec239d901aa5f3525dc2ee08 (patch)
tree472233d8d1717b7feed78962df3a4d9acf74c7da
parentd3715e11f76ce0f96bca8650213636381f867373 (diff)
scsi: ufs: add additional error injection scenarios
This change adds the following additional error scenarios: - power mode change error - link start-up error - send UIC command error - get/set DME command error (to host and device) - send invalid query (flag/attribute/descriptor) Change-Id: I440519c385a5da269b85ed2cdad66565ed3e6d7e Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org> [subhashj@codeaurora.org: resolved trivial merge conflicts] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
-rw-r--r--drivers/scsi/ufs/ufs-debugfs.c76
-rw-r--r--drivers/scsi/ufs/ufs-debugfs.h8
-rw-r--r--drivers/scsi/ufs/ufshcd.c22
3 files changed, 84 insertions, 22 deletions
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index 3f05d2e6c6c1..0df02f2e03b2 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -67,12 +67,46 @@ struct ufsdbg_err_scenario {
u32 num_err_codes;
};
+/*
+ * the following static arrays are aggregation of possible errors
+ * that might occur during the relevant error scenario
+ */
static const int err_inject_intr_err_codes[] = {
CONTROLLER_FATAL_ERROR,
SYSTEM_BUS_FATAL_ERROR,
INJECT_COMMAND_HANG,
};
+static const int err_inject_pwr_change_err_codes[] = {
+ -EIO,
+ -ETIMEDOUT,
+ -1,
+ PWR_REMOTE,
+ PWR_BUSY,
+ PWR_ERROR_CAP,
+ PWR_FATAL_ERROR,
+};
+
+static const int err_inject_link_startup_err_codes[] = {
+ -EIO,
+ -ETIMEDOUT,
+};
+
+static const int err_inject_uic_err_codes[] = {
+ -EIO,
+ -ETIMEDOUT,
+};
+
+static const int err_inject_dme_attr_err_codes[] = {
+ /* an invalid DME attribute for host and device */
+ 0x1600,
+};
+
+static const int err_inject_query_err_codes[] = {
+ /* an invalid idn for flag/attribute/descriptor query request */
+ 0xFF,
+};
+
static struct ufsdbg_err_scenario err_scen_arr[] = {
{
"ERR_INJECT_INTR",
@@ -93,34 +127,34 @@ static struct ufsdbg_err_scenario err_scen_arr[] = {
0,
},
{
- "ERR_INJECT_GEAR_CHANGE",
+ "ERR_INJECT_PWR_CHANGE",
ERR_CODES_ALL_ENABLED,
- NULL,
- 0,
+ err_inject_pwr_change_err_codes,
+ ARRAY_SIZE(err_inject_pwr_change_err_codes),
},
{
"ERR_INJECT_LINK_STARTUP",
ERR_CODES_ALL_ENABLED,
- NULL,
- 0,
+ err_inject_link_startup_err_codes,
+ ARRAY_SIZE(err_inject_link_startup_err_codes),
},
{
- "ERR_INJECT_DME_ATTR",
+ "ERR_INJECT_UIC",
ERR_CODES_ALL_ENABLED,
- NULL,
- 0,
+ err_inject_uic_err_codes,
+ ARRAY_SIZE(err_inject_uic_err_codes),
},
{
- "ERR_INJECT_DME_PEER_ATTR",
+ "ERR_INJECT_DME_ATTR",
ERR_CODES_ALL_ENABLED,
- NULL,
- 0,
+ err_inject_dme_attr_err_codes,
+ ARRAY_SIZE(err_inject_dme_attr_err_codes),
},
{
"ERR_INJECT_QUERY",
ERR_CODES_ALL_ENABLED,
- NULL,
- 0,
+ err_inject_query_err_codes,
+ ARRAY_SIZE(err_inject_query_err_codes),
},
{
"ERR_INJECT_RUNTIME_PM",
@@ -264,7 +298,7 @@ ufsdbg_find_err_code(enum ufsdbg_err_inject_scenario usecase, int *ret)
void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba,
enum ufsdbg_err_inject_scenario usecase,
- int *ret_value)
+ int success_value, int *ret_value)
{
int opt_ret = 0;
@@ -280,16 +314,24 @@ void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba,
if (!should_fail(&hba->debugfs_files.fail_attr, 1))
goto out;
+ /* if an error already occurred/injected */
+ if (*ret_value != success_value)
+ goto out;
+
switch (usecase) {
case ERR_INJECT_INTR:
- ufsdbg_intr_fail_request(hba, &opt_ret);
+ /* an error already occurred */
+ if (*ret_value & UFSHCD_ERROR_MASK)
+ goto out;
+
+ ufsdbg_intr_fail_request(hba, (u32 *)&opt_ret);
/* fall through */
case ERR_INJECT_HIBERN8_ENTER:
case ERR_INJECT_HIBERN8_EXIT:
- case ERR_INJECT_GEAR_CHANGE:
+ case ERR_INJECT_PWR_CHANGE:
case ERR_INJECT_LINK_STARTUP:
+ case ERR_INJECT_UIC:
case ERR_INJECT_DME_ATTR:
- case ERR_INJECT_DME_PEER_ATTR:
case ERR_INJECT_QUERY:
case ERR_INJECT_RUNTIME_PM:
case ERR_INJECT_SYSTEM_PM:
diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h
index 95b582d16c39..6aaa2a407a5f 100644
--- a/drivers/scsi/ufs/ufs-debugfs.h
+++ b/drivers/scsi/ufs/ufs-debugfs.h
@@ -27,10 +27,10 @@ enum ufsdbg_err_inject_scenario {
ERR_INJECT_INTR,
ERR_INJECT_HIBERN8_ENTER,
ERR_INJECT_HIBERN8_EXIT,
- ERR_INJECT_GEAR_CHANGE,
+ ERR_INJECT_PWR_CHANGE,
ERR_INJECT_LINK_STARTUP,
+ ERR_INJECT_UIC,
ERR_INJECT_DME_ATTR,
- ERR_INJECT_DME_PEER_ATTR,
ERR_INJECT_QUERY,
ERR_INJECT_RUNTIME_PM,
ERR_INJECT_SYSTEM_PM,
@@ -60,11 +60,11 @@ static inline void ufsdbg_pr_buf_to_std(struct ufs_hba *hba, int offset,
#ifdef CONFIG_UFS_FAULT_INJECTION
void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba,
enum ufsdbg_err_inject_scenario err_scenario,
- int *ret_value);
+ int success_value, int *ret_value);
#else
static inline void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba,
enum ufsdbg_err_inject_scenario err_scenario,
- int *ret_value)
+ int success_value, int *ret_value)
{
}
#endif
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index dea629abf830..e24c3421db3c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2199,6 +2199,10 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
ufshcd_save_tstamp_of_last_dme_cmd(hba);
mutex_unlock(&hba->uic_cmd_mutex);
ufshcd_release_all(hba);
+
+ ufsdbg_error_inject_dispatcher(hba,
+ ERR_INJECT_UIC, 0, &ret);
+
return ret;
}
@@ -2861,6 +2865,9 @@ static inline void ufshcd_init_query(struct ufs_hba *hba,
struct ufs_query_req **request, struct ufs_query_res **response,
enum query_opcode opcode, u8 idn, u8 index, u8 selector)
{
+ ufsdbg_error_inject_dispatcher(hba,
+ ERR_INJECT_QUERY, idn, (int *)&idn);
+
*request = &hba->dev_cmd.query.request;
*response = &hba->dev_cmd.query.response;
memset(*request, 0, sizeof(struct ufs_query_req));
@@ -3624,6 +3631,9 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
int ret;
int retries = UFS_UIC_COMMAND_RETRIES;
+ ufsdbg_error_inject_dispatcher(hba,
+ ERR_INJECT_DME_ATTR, attr_sel, &attr_sel);
+
uic_cmd.command = peer ?
UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
uic_cmd.argument1 = attr_sel;
@@ -3695,6 +3705,10 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
uic_cmd.command = peer ?
UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
+
+ ufsdbg_error_inject_dispatcher(hba,
+ ERR_INJECT_DME_ATTR, attr_sel, &attr_sel);
+
uic_cmd.argument1 = attr_sel;
do {
@@ -4114,6 +4128,9 @@ int ufshcd_change_power_mode(struct ufs_hba *hba,
sizeof(struct ufs_pa_layer_attr));
}
+ ufsdbg_error_inject_dispatcher(hba,
+ ERR_INJECT_PWR_CHANGE, 0, &ret);
+
return ret;
}
@@ -4430,6 +4447,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
ret = ufshcd_make_hba_operational(hba);
out:
+ ufsdbg_error_inject_dispatcher(hba,
+ ERR_INJECT_LINK_STARTUP, 0, &ret);
+
if (ret)
dev_err(hba->dev, "link startup failed %d\n", ret);
return ret;
@@ -5669,7 +5689,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
bool crypto_engine_err = false;
ufsdbg_error_inject_dispatcher(hba,
- ERR_INJECT_INTR, &intr_status);
+ ERR_INJECT_INTR, intr_status, &intr_status);
if (hba->vops && hba->vops->crypto_engine_eh)
crypto_engine_err = hba->vops->crypto_engine_eh(hba);