scsi: ufs: debugfs: add option to read peer DME attribute
This patch adds the debugfs capability to read the DME attribute of peer UniPro/M-PHY. This should help for debugging. Change-Id: I26d3675bdda8b9fdf0f9aa6b81a1ffafbd828fd0 [subhashj@codeaurora.org: resolved trivial merge conflicts] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> [venkatg@codeaurora.org: resolved trivial merge conflicts] Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
This commit is contained in:
parent
3997870e3b
commit
04218a4f78
4 changed files with 101 additions and 13 deletions
|
@ -753,6 +753,23 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ufsdbg_config_pwr_mode(struct ufs_hba *hba,
|
||||||
|
struct ufs_pa_layer_attr *desired_pwr_mode)
|
||||||
|
{
|
||||||
|
#define DOORBELL_CLR_TOUT_US (1000 * 1000) /* 1 sec */
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pm_runtime_get_sync(hba->dev);
|
||||||
|
scsi_block_requests(hba->host);
|
||||||
|
ret = ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US);
|
||||||
|
if (!ret)
|
||||||
|
ret = ufshcd_change_power_mode(hba, desired_pwr_mode);
|
||||||
|
scsi_unblock_requests(hba->host);
|
||||||
|
pm_runtime_put_sync(hba->dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t ufsdbg_power_mode_write(struct file *file,
|
static ssize_t ufsdbg_power_mode_write(struct file *file,
|
||||||
const char __user *ubuf, size_t cnt,
|
const char __user *ubuf, size_t cnt,
|
||||||
loff_t *ppos)
|
loff_t *ppos)
|
||||||
|
@ -764,7 +781,6 @@ static ssize_t ufsdbg_power_mode_write(struct file *file,
|
||||||
loff_t buff_pos = 0;
|
loff_t buff_pos = 0;
|
||||||
int ret;
|
int ret;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
#define DOORBELL_CLR_TOUT_US (1000 * 1000) /* 1 sec */
|
|
||||||
|
|
||||||
ret = simple_write_to_buffer(pwr_mode_str, BUFF_LINE_CAPACITY,
|
ret = simple_write_to_buffer(pwr_mode_str, BUFF_LINE_CAPACITY,
|
||||||
&buff_pos, ubuf, cnt);
|
&buff_pos, ubuf, cnt);
|
||||||
|
@ -800,13 +816,7 @@ static ssize_t ufsdbg_power_mode_write(struct file *file,
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
pm_runtime_get_sync(hba->dev);
|
ret = ufsdbg_config_pwr_mode(hba, &final_pwr_mode);
|
||||||
scsi_block_requests(hba->host);
|
|
||||||
ret = ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US);
|
|
||||||
if (!ret)
|
|
||||||
ret = ufshcd_change_power_mode(hba, &final_pwr_mode);
|
|
||||||
scsi_unblock_requests(hba->host);
|
|
||||||
pm_runtime_put_sync(hba->dev);
|
|
||||||
if (ret == -EBUSY)
|
if (ret == -EBUSY)
|
||||||
dev_err(hba->dev,
|
dev_err(hba->dev,
|
||||||
"%s: ufshcd_config_pwr_mode failed: system is busy, try again\n",
|
"%s: ufshcd_config_pwr_mode failed: system is busy, try again\n",
|
||||||
|
@ -830,19 +840,21 @@ static const struct file_operations ufsdbg_power_mode_desc = {
|
||||||
.write = ufsdbg_power_mode_write,
|
.write = ufsdbg_power_mode_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ufsdbg_dme_local_read(void *data, u64 *attr_val)
|
static int ufsdbg_dme_read(void *data, u64 *attr_val, bool peer)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct ufs_hba *hba = data;
|
struct ufs_hba *hba = data;
|
||||||
u32 read_val = 0;
|
u32 attr_id, read_val = 0;
|
||||||
|
int (*read_func) (struct ufs_hba *, u32, u32 *);
|
||||||
|
|
||||||
if (!hba)
|
if (!hba)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
read_func = peer ? ufshcd_dme_peer_get : ufshcd_dme_get;
|
||||||
|
attr_id = peer ? hba->debugfs_files.dme_peer_attr_id :
|
||||||
|
hba->debugfs_files.dme_local_attr_id;
|
||||||
pm_runtime_get_sync(hba->dev);
|
pm_runtime_get_sync(hba->dev);
|
||||||
ret = ufshcd_dme_get(hba,
|
ret = ufshcd_dme_get(hba, UIC_ARG_MIB(attr_id), &read_val);
|
||||||
UIC_ARG_MIB(hba->debugfs_files.dme_local_attr_id),
|
|
||||||
&read_val);
|
|
||||||
pm_runtime_put_sync(hba->dev);
|
pm_runtime_put_sync(hba->dev);
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@ -863,11 +875,70 @@ static int ufsdbg_dme_local_set_attr_id(void *data, u64 attr_id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ufsdbg_dme_local_read(void *data, u64 *attr_val)
|
||||||
|
{
|
||||||
|
return ufsdbg_dme_read(data, attr_val, false);
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_dme_local_read_ops,
|
DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_dme_local_read_ops,
|
||||||
ufsdbg_dme_local_read,
|
ufsdbg_dme_local_read,
|
||||||
ufsdbg_dme_local_set_attr_id,
|
ufsdbg_dme_local_set_attr_id,
|
||||||
"%llu\n");
|
"%llu\n");
|
||||||
|
|
||||||
|
static int ufsdbg_dme_peer_read(void *data, u64 *attr_val)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct ufs_hba *hba = data;
|
||||||
|
struct ufs_pa_layer_attr orig_pwr_info;
|
||||||
|
struct ufs_pa_layer_attr temp_pwr_info;
|
||||||
|
bool restore_pwr_mode = false;
|
||||||
|
|
||||||
|
if (!hba)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (hba->quirks & UFSHCD_QUIRK_DME_PEER_GET_FAST_MODE) {
|
||||||
|
orig_pwr_info = hba->pwr_info;
|
||||||
|
temp_pwr_info = orig_pwr_info;
|
||||||
|
if (orig_pwr_info.pwr_tx == FAST_MODE ||
|
||||||
|
orig_pwr_info.pwr_rx == FAST_MODE) {
|
||||||
|
temp_pwr_info.pwr_tx = FASTAUTO_MODE;
|
||||||
|
temp_pwr_info.pwr_rx = FASTAUTO_MODE;
|
||||||
|
ret = ufsdbg_config_pwr_mode(hba, &temp_pwr_info);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
else
|
||||||
|
restore_pwr_mode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ufsdbg_dme_read(data, attr_val, true);
|
||||||
|
|
||||||
|
if (hba->quirks & UFSHCD_QUIRK_DME_PEER_GET_FAST_MODE) {
|
||||||
|
if (restore_pwr_mode)
|
||||||
|
ufsdbg_config_pwr_mode(hba, &orig_pwr_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ufsdbg_dme_peer_set_attr_id(void *data, u64 attr_id)
|
||||||
|
{
|
||||||
|
struct ufs_hba *hba = data;
|
||||||
|
|
||||||
|
if (!hba)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
hba->debugfs_files.dme_peer_attr_id = (u32)attr_id;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_dme_peer_read_ops,
|
||||||
|
ufsdbg_dme_peer_read,
|
||||||
|
ufsdbg_dme_peer_set_attr_id,
|
||||||
|
"%llu\n");
|
||||||
|
|
||||||
void ufsdbg_add_debugfs(struct ufs_hba *hba)
|
void ufsdbg_add_debugfs(struct ufs_hba *hba)
|
||||||
{
|
{
|
||||||
if (!hba) {
|
if (!hba) {
|
||||||
|
@ -962,6 +1033,17 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hba->debugfs_files.dme_peer_read =
|
||||||
|
debugfs_create_file("dme_peer_read", S_IRUSR | S_IWUSR,
|
||||||
|
hba->debugfs_files.debugfs_root, hba,
|
||||||
|
&ufsdbg_dme_peer_read_ops);
|
||||||
|
if (!hba->debugfs_files.dme_peer_read) {
|
||||||
|
dev_err(hba->dev,
|
||||||
|
"%s: failed create dme_peer_read debugfs entry\n",
|
||||||
|
__func__);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
ufsdbg_setup_fault_injection(hba);
|
ufsdbg_setup_fault_injection(hba);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -754,6 +754,8 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
|
||||||
hba->quirks |= (UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS
|
hba->quirks |= (UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS
|
||||||
| UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP
|
| UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP
|
||||||
| UFSHCD_QUIRK_BROKEN_LCC);
|
| UFSHCD_QUIRK_BROKEN_LCC);
|
||||||
|
|
||||||
|
hba->quirks |= UFSHCD_QUIRK_DME_PEER_GET_FAST_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
|
static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
|
||||||
|
|
|
@ -2777,6 +2777,7 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us)
|
||||||
bool timeout = false;
|
bool timeout = false;
|
||||||
ktime_t start = ktime_get();
|
ktime_t start = ktime_get();
|
||||||
|
|
||||||
|
ufshcd_hold(hba, false);
|
||||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||||
if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) {
|
if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
|
@ -2811,6 +2812,7 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us)
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||||
|
ufshcd_release(hba);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -378,7 +378,9 @@ struct debugfs_files {
|
||||||
struct dentry *dump_dev_desc;
|
struct dentry *dump_dev_desc;
|
||||||
struct dentry *power_mode;
|
struct dentry *power_mode;
|
||||||
struct dentry *dme_local_read;
|
struct dentry *dme_local_read;
|
||||||
|
struct dentry *dme_peer_read;
|
||||||
u32 dme_local_attr_id;
|
u32 dme_local_attr_id;
|
||||||
|
u32 dme_peer_attr_id;
|
||||||
#ifdef CONFIG_UFS_FAULT_INJECTION
|
#ifdef CONFIG_UFS_FAULT_INJECTION
|
||||||
struct fault_attr fail_attr;
|
struct fault_attr fail_attr;
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue