scsi: ufs: dump device descriptor info via debugfs
This change adds a debugfs capability to dump Device Descriptor information, parsed and detailed. It helps developer to get important information about the UFS device it handles. Change-Id: Ia149e4c82e33755b235eb6afe52541c8b23a0708 Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
This commit is contained in:
parent
277e3a5096
commit
06a49c67f7
3 changed files with 129 additions and 0 deletions
|
@ -20,6 +20,17 @@
|
|||
#include <linux/random.h>
|
||||
#include "debugfs.h"
|
||||
|
||||
enum field_width {
|
||||
BYTE = 1,
|
||||
WORD = 2,
|
||||
};
|
||||
|
||||
struct desc_field_offset {
|
||||
char *name;
|
||||
int offset;
|
||||
enum field_width width_byte;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_UFS_FAULT_INJECTION
|
||||
|
||||
#define INJECT_COMMAND_HANG (0x0)
|
||||
|
@ -306,6 +317,79 @@ static const struct file_operations ufsdbg_host_regs_fops = {
|
|||
.read = seq_read,
|
||||
};
|
||||
|
||||
static int ufsdbg_dump_device_desc_show(struct seq_file *file, void *data)
|
||||
{
|
||||
int err = 0;
|
||||
int buff_len = QUERY_DESC_DEVICE_MAX_SIZE;
|
||||
u8 desc_buf[QUERY_DESC_DEVICE_MAX_SIZE];
|
||||
struct ufs_hba *hba = (struct ufs_hba *)file->private;
|
||||
|
||||
struct desc_field_offset device_desc_field_name[] = {
|
||||
{"bLength", 0x00, BYTE},
|
||||
{"bDescriptorType", 0x01, BYTE},
|
||||
{"bDevice", 0x02, BYTE},
|
||||
{"bDeviceClass", 0x03, BYTE},
|
||||
{"bDeviceSubClass", 0x04, BYTE},
|
||||
{"bProtocol", 0x05, BYTE},
|
||||
{"bNumberLU", 0x06, BYTE},
|
||||
{"bNumberWLU", 0x07, BYTE},
|
||||
{"bBootEnable", 0x08, BYTE},
|
||||
{"bDescrAccessEn", 0x09, BYTE},
|
||||
{"bInitPowerMode", 0x0A, BYTE},
|
||||
{"bHighPriorityLUN", 0x0B, BYTE},
|
||||
{"bSecureRemovalType", 0x0C, BYTE},
|
||||
{"bSecurityLU", 0x0D, BYTE},
|
||||
{"Reserved", 0x0E, BYTE},
|
||||
{"bInitActiveICCLevel", 0x0F, BYTE},
|
||||
{"wSpecVersion", 0x10, WORD},
|
||||
{"wManufactureDate", 0x12, WORD},
|
||||
{"iManufactureName", 0x14, BYTE},
|
||||
{"iProductName", 0x15, BYTE},
|
||||
{"iSerialNumber", 0x16, BYTE},
|
||||
{"iOemID", 0x17, BYTE},
|
||||
{"wManufactureID", 0x18, WORD},
|
||||
{"bUD0BaseOffset", 0x1A, BYTE},
|
||||
{"bUDConfigPLength", 0x1B, BYTE},
|
||||
{"bDeviceRTTCap", 0x1C, BYTE},
|
||||
{"wPeriodicRTCUpdate", 0x1D, WORD}
|
||||
};
|
||||
|
||||
pm_runtime_get_sync(hba->dev);
|
||||
err = ufshcd_read_device_desc(hba, desc_buf, buff_len);
|
||||
pm_runtime_put_sync(hba->dev);
|
||||
|
||||
if (!err) {
|
||||
int i;
|
||||
struct desc_field_offset *tmp;
|
||||
for (i = 0; i < ARRAY_SIZE(device_desc_field_name); ++i) {
|
||||
tmp = &device_desc_field_name[i];
|
||||
|
||||
if (tmp->width_byte == BYTE) {
|
||||
seq_printf(file,
|
||||
"Device Descriptor[Byte offset 0x%x]: %s = 0x%x\n",
|
||||
tmp->offset,
|
||||
tmp->name,
|
||||
(u8)desc_buf[tmp->offset]);
|
||||
} else if (tmp->width_byte == WORD) {
|
||||
seq_printf(file,
|
||||
"Device Descriptor[Byte offset 0x%x]: %s = 0x%x\n",
|
||||
tmp->offset,
|
||||
tmp->name,
|
||||
*(u16 *)&desc_buf[tmp->offset]);
|
||||
} else {
|
||||
seq_printf(file,
|
||||
"Device Descriptor[offset 0x%x]: %s. Wrong Width = %d",
|
||||
tmp->offset, tmp->name, tmp->width_byte);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
seq_printf(file, "Reading Device Descriptor failed. err = %d\n",
|
||||
err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ufsdbg_show_hba_show(struct seq_file *file, void *data)
|
||||
{
|
||||
struct ufs_hba *hba = (struct ufs_hba *)file->private;
|
||||
|
@ -347,6 +431,17 @@ static const struct file_operations ufsdbg_show_hba_fops = {
|
|||
.read = seq_read,
|
||||
};
|
||||
|
||||
static int ufsdbg_dump_device_desc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file,
|
||||
ufsdbg_dump_device_desc_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations ufsdbg_dump_device_desc = {
|
||||
.open = ufsdbg_dump_device_desc_open,
|
||||
.read = seq_read,
|
||||
};
|
||||
|
||||
void ufsdbg_add_debugfs(struct ufs_hba *hba)
|
||||
{
|
||||
if (!hba) {
|
||||
|
@ -400,6 +495,16 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba)
|
|||
goto err;
|
||||
}
|
||||
|
||||
hba->debugfs_files.dump_dev_desc =
|
||||
debugfs_create_file("dump_device_desc", S_IRUSR,
|
||||
hba->debugfs_files.debugfs_root, hba,
|
||||
&ufsdbg_dump_device_desc);
|
||||
if (!hba->debugfs_files.dump_dev_desc) {
|
||||
dev_err(hba->dev,
|
||||
"%s: NULL dump_device_desc file, exiting", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ufsdbg_setup_fault_injection(hba);
|
||||
|
||||
return;
|
||||
|
|
|
@ -2046,6 +2046,27 @@ static inline int ufshcd_read_power_desc(struct ufs_hba *hba,
|
|||
return err;
|
||||
}
|
||||
|
||||
int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size)
|
||||
{
|
||||
int err = 0;
|
||||
int retries;
|
||||
|
||||
for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
|
||||
/* Read descriptor*/
|
||||
err = ufshcd_read_desc(hba,
|
||||
QUERY_DESC_IDN_DEVICE, 0, buf, size);
|
||||
if (!err)
|
||||
break;
|
||||
dev_dbg(hba->dev, "%s: error %d retrying\n", __func__, err);
|
||||
}
|
||||
|
||||
if (err)
|
||||
dev_err(hba->dev, "%s: reading Device Desc failed. err = %d\n",
|
||||
__func__, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_read_unit_desc_param - read the specified unit descriptor parameter
|
||||
* @hba: Pointer to adapter instance
|
||||
|
|
|
@ -346,6 +346,7 @@ struct debugfs_files {
|
|||
struct dentry *tag_stats;
|
||||
struct dentry *show_hba;
|
||||
struct dentry *host_regs;
|
||||
struct dentry *dump_dev_desc;
|
||||
#ifdef CONFIG_UFS_FAULT_INJECTION
|
||||
struct fault_attr fail_attr;
|
||||
#endif
|
||||
|
@ -742,6 +743,8 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
|
|||
return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER);
|
||||
}
|
||||
|
||||
int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size);
|
||||
|
||||
/* variant specific ops structures */
|
||||
#ifdef CONFIG_SCSI_UFS_MSM
|
||||
extern const struct ufs_hba_variant_ops ufs_hba_msm_vops;
|
||||
|
|
Loading…
Add table
Reference in a new issue