summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorStanislav Nijnikov <stanislav.nijnikov@wdc.com>2018-02-15 14:14:07 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2018-02-15 18:34:25 -0500
commit2238d31cdeabc585de5869efd11856815aa4dd13 (patch)
treeae44b7db8de163a1404b71b1b387aaceaeda765d /drivers/scsi
parentc2e6e283c52f3a2c4a99774b36bcc88e7cbd5eb7 (diff)
downloadlinux-2238d31cdeabc585de5869efd11856815aa4dd13.tar.gz
linux-2238d31cdeabc585de5869efd11856815aa4dd13.tar.bz2
linux-2238d31cdeabc585de5869efd11856815aa4dd13.zip
scsi: ufs: sysfs: string descriptors
This patch introduces a sysfs group entry for the UFS string descriptors. The group adds "string_descriptors" folder under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The folder will contain 5 files that will show string values defined by the UFS spec: a manufacturer name, a product name, an OEM id, a serial number and a product revision. The full information about the string descriptors could be found at UFS specifications 2.1. Signed-off-by: Stanislav Nijnikov <stanislav.nijnikov@wdc.com> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ufs/ufs-sysfs.c56
-rw-r--r--drivers/scsi/ufs/ufshcd.c14
-rw-r--r--drivers/scsi/ufs/ufshcd.h9
3 files changed, 72 insertions, 7 deletions
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 16e357a95b6b..c1aeb8aa3160 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -484,6 +484,61 @@ static const struct attribute_group ufs_sysfs_power_descriptor_group = {
.attrs = ufs_sysfs_power_descriptor,
};
+#define UFS_STRING_DESCRIPTOR(_name, _pname) \
+static ssize_t _name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ u8 index; \
+ struct ufs_hba *hba = dev_get_drvdata(dev); \
+ int ret; \
+ int desc_len = QUERY_DESC_MAX_SIZE; \
+ u8 *desc_buf; \
+ desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC); \
+ if (!desc_buf) \
+ return -ENOMEM; \
+ ret = ufshcd_query_descriptor_retry(hba, \
+ UPIU_QUERY_OPCODE_READ_DESC, QUERY_DESC_IDN_DEVICE, \
+ 0, 0, desc_buf, &desc_len); \
+ if (ret) { \
+ ret = -EINVAL; \
+ goto out; \
+ } \
+ index = desc_buf[DEVICE_DESC_PARAM##_pname]; \
+ memset(desc_buf, 0, QUERY_DESC_MAX_SIZE); \
+ if (ufshcd_read_string_desc(hba, index, desc_buf, \
+ QUERY_DESC_MAX_SIZE, true)) { \
+ ret = -EINVAL; \
+ goto out; \
+ } \
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", \
+ desc_buf + QUERY_DESC_HDR_SIZE); \
+out: \
+ kfree(desc_buf); \
+ return ret; \
+} \
+static DEVICE_ATTR_RO(_name)
+
+UFS_STRING_DESCRIPTOR(manufacturer_name, _MANF_NAME);
+UFS_STRING_DESCRIPTOR(product_name, _PRDCT_NAME);
+UFS_STRING_DESCRIPTOR(oem_id, _OEM_ID);
+UFS_STRING_DESCRIPTOR(serial_number, _SN);
+UFS_STRING_DESCRIPTOR(product_revision, _PRDCT_REV);
+
+static struct attribute *ufs_sysfs_string_descriptors[] = {
+ &dev_attr_manufacturer_name.attr,
+ &dev_attr_product_name.attr,
+ &dev_attr_oem_id.attr,
+ &dev_attr_serial_number.attr,
+ &dev_attr_product_revision.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_string_descriptors_group = {
+ .name = "string_descriptors",
+ .attrs = ufs_sysfs_string_descriptors,
+};
+
+
static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_default_group,
&ufs_sysfs_device_descriptor_group,
@@ -491,6 +546,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_geometry_descriptor_group,
&ufs_sysfs_health_descriptor_group,
&ufs_sysfs_power_descriptor_group,
+ &ufs_sysfs_string_descriptors_group,
NULL,
};
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b88fcf7be47b..9cfdd8ed198a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2873,11 +2873,11 @@ out:
* The buf_len parameter will contain, on return, the length parameter
* received on the response.
*/
-static int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
- enum query_opcode opcode,
- enum desc_idn idn, u8 index,
- u8 selector,
- u8 *desc_buf, int *buf_len)
+int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
+ enum query_opcode opcode,
+ enum desc_idn idn, u8 index,
+ u8 selector,
+ u8 *desc_buf, int *buf_len)
{
int err;
int retries;
@@ -3093,8 +3093,8 @@ static int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size)
* Return 0 in case of success, non-zero otherwise
*/
#define ASCII_STD true
-static int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
- u8 *buf, u32 size, bool ascii)
+int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
+ u8 *buf, u32 size, bool ascii)
{
int err = 0;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 515c6e6244be..2dad9dada86a 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -842,6 +842,12 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
}
/* Expose Query-Request API */
+int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
+ enum query_opcode opcode,
+ enum desc_idn idn, u8 index,
+ u8 selector,
+ u8 *desc_buf, int *buf_len);
+
int ufshcd_read_desc_param(struct ufs_hba *hba,
enum desc_idn desc_id,
int desc_index,
@@ -850,6 +856,9 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
u8 param_size);
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
enum flag_idn idn, bool *flag_res);
+int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
+ u8 *buf, u32 size, bool ascii);
+
int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba);