scsi: ufs-debugfs: add error state
This change adds support to allow user space query if low level UFS driver has encountered any error or not, this state can be read/cleared via debugfs. Change-Id: I867a4621315108aff17be852cfaadcfa945566a7 Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
parent
a26ae43d87
commit
73fa24503b
4 changed files with 69 additions and 2 deletions
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -1433,6 +1433,41 @@ static const struct file_operations ufsdbg_reset_controller = {
|
|||
.write = ufsdbg_reset_controller_write,
|
||||
};
|
||||
|
||||
static int ufsdbg_clear_err_state(void *data, u64 val)
|
||||
{
|
||||
struct ufs_hba *hba = data;
|
||||
|
||||
if (!hba)
|
||||
return -EINVAL;
|
||||
|
||||
/* clear the error state on any write attempt */
|
||||
hba->debugfs_files.err_occurred = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ufsdbg_read_err_state(void *data, u64 *val)
|
||||
{
|
||||
struct ufs_hba *hba = data;
|
||||
|
||||
if (!hba)
|
||||
return -EINVAL;
|
||||
|
||||
*val = hba->debugfs_files.err_occurred ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ufsdbg_set_err_state(struct ufs_hba *hba)
|
||||
{
|
||||
hba->debugfs_files.err_occurred = true;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_err_state,
|
||||
ufsdbg_read_err_state,
|
||||
ufsdbg_clear_err_state,
|
||||
"%llu\n");
|
||||
|
||||
void ufsdbg_add_debugfs(struct ufs_hba *hba)
|
||||
{
|
||||
char root_name[sizeof("ufshcd00")];
|
||||
|
@ -1594,6 +1629,16 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba)
|
|||
goto err;
|
||||
}
|
||||
|
||||
hba->debugfs_files.err_state =
|
||||
debugfs_create_file("err_state", S_IRUSR | S_IWUSR,
|
||||
hba->debugfs_files.debugfs_root, hba,
|
||||
&ufsdbg_err_state);
|
||||
if (!hba->debugfs_files.err_state) {
|
||||
dev_err(hba->dev,
|
||||
"%s: failed create err_state debugfs entry", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ufsdbg_setup_fault_injection(hba);
|
||||
|
||||
ufshcd_vops_add_debugfs(hba, hba->debugfs_files.debugfs_root);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -37,6 +37,7 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba);
|
|||
void ufsdbg_remove_debugfs(struct ufs_hba *hba);
|
||||
void ufsdbg_pr_buf_to_std(struct ufs_hba *hba, int offset, int num_regs,
|
||||
char *str, void *priv);
|
||||
void ufsdbg_set_err_state(struct ufs_hba *hba);
|
||||
#else
|
||||
static inline void ufsdbg_add_debugfs(struct ufs_hba *hba)
|
||||
{
|
||||
|
@ -48,6 +49,9 @@ static inline void ufsdbg_pr_buf_to_std(struct ufs_hba *hba, int offset,
|
|||
int num_regs, char *str, void *priv)
|
||||
{
|
||||
}
|
||||
void ufsdbg_set_err_state(struct ufs_hba *hba)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UFS_FAULT_INJECTION
|
||||
|
|
|
@ -71,6 +71,7 @@ static int ufshcd_tag_req_type(struct request *rq)
|
|||
|
||||
static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
|
||||
{
|
||||
ufsdbg_set_err_state(hba);
|
||||
if (type < UFS_ERR_MAX)
|
||||
hba->ufs_stats.err_stats[type]++;
|
||||
}
|
||||
|
@ -2143,6 +2144,9 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
|
|||
else
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
if (ret)
|
||||
ufsdbg_set_err_state(hba);
|
||||
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
hba->active_uic_cmd = NULL;
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
|
@ -2842,6 +2846,9 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
|
|||
ufshcd_outstanding_req_clear(hba, lrbp->task_tag);
|
||||
}
|
||||
|
||||
if (err)
|
||||
ufsdbg_set_err_state(hba);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -3874,6 +3881,9 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
|
|||
ret = (status != PWR_OK) ? status : -1;
|
||||
}
|
||||
out:
|
||||
if (ret)
|
||||
ufsdbg_set_err_state(hba);
|
||||
|
||||
ufshcd_save_tstamp_of_last_dme_cmd(hba);
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
hba->active_uic_cmd = NULL;
|
||||
|
@ -4947,6 +4957,11 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
|
|||
ocs == OCS_MISMATCH_DATA_BUF_SIZE);
|
||||
ufshcd_print_trs(hba, 1 << lrbp->task_tag, print_prdt);
|
||||
}
|
||||
|
||||
if ((host_byte(result) == DID_ERROR) ||
|
||||
(host_byte(result) == DID_ABORT))
|
||||
ufsdbg_set_err_state(hba);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -5532,6 +5547,7 @@ static void ufshcd_err_handler(struct work_struct *work)
|
|||
|
||||
hba = container_of(work, struct ufs_hba, eh_work);
|
||||
|
||||
ufsdbg_set_err_state(hba);
|
||||
pm_runtime_get_sync(hba->dev);
|
||||
ufshcd_hold_all(hba);
|
||||
|
||||
|
|
|
@ -543,6 +543,8 @@ struct debugfs_files {
|
|||
u32 dme_local_attr_id;
|
||||
u32 dme_peer_attr_id;
|
||||
struct dentry *reset_controller;
|
||||
struct dentry *err_state;
|
||||
bool err_occurred;
|
||||
#ifdef CONFIG_UFS_FAULT_INJECTION
|
||||
struct dentry *err_inj_scenario;
|
||||
struct dentry *err_inj_stats;
|
||||
|
|
Loading…
Add table
Reference in a new issue