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>
This commit is contained in:
Yaniv Gardi 2015-03-25 17:59:05 +02:00 committed by David Keitel
parent d3715e11f7
commit 3f8adb02aa
3 changed files with 86 additions and 24 deletions

View file

@ -67,12 +67,46 @@ struct ufsdbg_err_scenario {
u32 num_err_codes; 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[] = { static const int err_inject_intr_err_codes[] = {
CONTROLLER_FATAL_ERROR, CONTROLLER_FATAL_ERROR,
SYSTEM_BUS_FATAL_ERROR, SYSTEM_BUS_FATAL_ERROR,
INJECT_COMMAND_HANG, 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[] = { static struct ufsdbg_err_scenario err_scen_arr[] = {
{ {
"ERR_INJECT_INTR", "ERR_INJECT_INTR",
@ -93,34 +127,34 @@ static struct ufsdbg_err_scenario err_scen_arr[] = {
0, 0,
}, },
{ {
"ERR_INJECT_GEAR_CHANGE", "ERR_INJECT_PWR_CHANGE",
ERR_CODES_ALL_ENABLED, ERR_CODES_ALL_ENABLED,
NULL, err_inject_pwr_change_err_codes,
0, ARRAY_SIZE(err_inject_pwr_change_err_codes),
}, },
{ {
"ERR_INJECT_LINK_STARTUP", "ERR_INJECT_LINK_STARTUP",
ERR_CODES_ALL_ENABLED, ERR_CODES_ALL_ENABLED,
NULL, err_inject_link_startup_err_codes,
0, ARRAY_SIZE(err_inject_link_startup_err_codes),
},
{
"ERR_INJECT_UIC",
ERR_CODES_ALL_ENABLED,
err_inject_uic_err_codes,
ARRAY_SIZE(err_inject_uic_err_codes),
}, },
{ {
"ERR_INJECT_DME_ATTR", "ERR_INJECT_DME_ATTR",
ERR_CODES_ALL_ENABLED, ERR_CODES_ALL_ENABLED,
NULL, err_inject_dme_attr_err_codes,
0, ARRAY_SIZE(err_inject_dme_attr_err_codes),
},
{
"ERR_INJECT_DME_PEER_ATTR",
ERR_CODES_ALL_ENABLED,
NULL,
0,
}, },
{ {
"ERR_INJECT_QUERY", "ERR_INJECT_QUERY",
ERR_CODES_ALL_ENABLED, ERR_CODES_ALL_ENABLED,
NULL, err_inject_query_err_codes,
0, ARRAY_SIZE(err_inject_query_err_codes),
}, },
{ {
"ERR_INJECT_RUNTIME_PM", "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, void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba,
enum ufsdbg_err_inject_scenario usecase, enum ufsdbg_err_inject_scenario usecase,
int *ret_value) int success_value, int *ret_value)
{ {
int opt_ret = 0; 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)) if (!should_fail(&hba->debugfs_files.fail_attr, 1))
goto out; goto out;
/* if an error already occurred/injected */
if (*ret_value != success_value)
goto out;
switch (usecase) { switch (usecase) {
case ERR_INJECT_INTR: 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 */ /* fall through */
case ERR_INJECT_HIBERN8_ENTER: case ERR_INJECT_HIBERN8_ENTER:
case ERR_INJECT_HIBERN8_EXIT: case ERR_INJECT_HIBERN8_EXIT:
case ERR_INJECT_GEAR_CHANGE: case ERR_INJECT_PWR_CHANGE:
case ERR_INJECT_LINK_STARTUP: case ERR_INJECT_LINK_STARTUP:
case ERR_INJECT_UIC:
case ERR_INJECT_DME_ATTR: case ERR_INJECT_DME_ATTR:
case ERR_INJECT_DME_PEER_ATTR:
case ERR_INJECT_QUERY: case ERR_INJECT_QUERY:
case ERR_INJECT_RUNTIME_PM: case ERR_INJECT_RUNTIME_PM:
case ERR_INJECT_SYSTEM_PM: case ERR_INJECT_SYSTEM_PM:

View file

@ -27,10 +27,10 @@ enum ufsdbg_err_inject_scenario {
ERR_INJECT_INTR, ERR_INJECT_INTR,
ERR_INJECT_HIBERN8_ENTER, ERR_INJECT_HIBERN8_ENTER,
ERR_INJECT_HIBERN8_EXIT, ERR_INJECT_HIBERN8_EXIT,
ERR_INJECT_GEAR_CHANGE, ERR_INJECT_PWR_CHANGE,
ERR_INJECT_LINK_STARTUP, ERR_INJECT_LINK_STARTUP,
ERR_INJECT_UIC,
ERR_INJECT_DME_ATTR, ERR_INJECT_DME_ATTR,
ERR_INJECT_DME_PEER_ATTR,
ERR_INJECT_QUERY, ERR_INJECT_QUERY,
ERR_INJECT_RUNTIME_PM, ERR_INJECT_RUNTIME_PM,
ERR_INJECT_SYSTEM_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 #ifdef CONFIG_UFS_FAULT_INJECTION
void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba, void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba,
enum ufsdbg_err_inject_scenario err_scenario, enum ufsdbg_err_inject_scenario err_scenario,
int *ret_value); int success_value, int *ret_value);
#else #else
static inline void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba, static inline void ufsdbg_error_inject_dispatcher(struct ufs_hba *hba,
enum ufsdbg_err_inject_scenario err_scenario, enum ufsdbg_err_inject_scenario err_scenario,
int *ret_value) int success_value, int *ret_value)
{ {
} }
#endif #endif

View file

@ -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); ufshcd_save_tstamp_of_last_dme_cmd(hba);
mutex_unlock(&hba->uic_cmd_mutex); mutex_unlock(&hba->uic_cmd_mutex);
ufshcd_release_all(hba); ufshcd_release_all(hba);
ufsdbg_error_inject_dispatcher(hba,
ERR_INJECT_UIC, 0, &ret);
return 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, struct ufs_query_req **request, struct ufs_query_res **response,
enum query_opcode opcode, u8 idn, u8 index, u8 selector) 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; *request = &hba->dev_cmd.query.request;
*response = &hba->dev_cmd.query.response; *response = &hba->dev_cmd.query.response;
memset(*request, 0, sizeof(struct ufs_query_req)); 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 ret;
int retries = UFS_UIC_COMMAND_RETRIES; 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.command = peer ?
UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET; UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
uic_cmd.argument1 = attr_sel; 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.command = peer ?
UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET; 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; uic_cmd.argument1 = attr_sel;
do { do {
@ -4114,6 +4128,9 @@ int ufshcd_change_power_mode(struct ufs_hba *hba,
sizeof(struct ufs_pa_layer_attr)); sizeof(struct ufs_pa_layer_attr));
} }
ufsdbg_error_inject_dispatcher(hba,
ERR_INJECT_PWR_CHANGE, 0, &ret);
return ret; return ret;
} }
@ -4430,6 +4447,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
ret = ufshcd_make_hba_operational(hba); ret = ufshcd_make_hba_operational(hba);
out: out:
ufsdbg_error_inject_dispatcher(hba,
ERR_INJECT_LINK_STARTUP, 0, &ret);
if (ret) if (ret)
dev_err(hba->dev, "link startup failed %d\n", ret); dev_err(hba->dev, "link startup failed %d\n", ret);
return ret; return ret;
@ -5669,7 +5689,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
bool crypto_engine_err = false; bool crypto_engine_err = false;
ufsdbg_error_inject_dispatcher(hba, 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) if (hba->vops && hba->vops->crypto_engine_eh)
crypto_engine_err = hba->vops->crypto_engine_eh(hba); crypto_engine_err = hba->vops->crypto_engine_eh(hba);