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>hifive-unleashed-5.1
parent
c2e6e283c5
commit
2238d31cde
|
@ -451,3 +451,42 @@ Description: This file shows maximum VCC, VCCQ and VCCQ2 value for
|
||||||
power descriptor parameters. The full information about
|
power descriptor parameters. The full information about
|
||||||
the descriptor could be found at UFS specifications 2.1.
|
the descriptor could be found at UFS specifications 2.1.
|
||||||
The file is read only.
|
The file is read only.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/manufacturer_name
|
||||||
|
Date: February 2018
|
||||||
|
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||||
|
Description: This file contains a device manufactureer name string.
|
||||||
|
The full information about the descriptor could be found at
|
||||||
|
UFS specifications 2.1.
|
||||||
|
The file is read only.
|
||||||
|
|
||||||
|
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_name
|
||||||
|
Date: February 2018
|
||||||
|
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||||
|
Description: This file contains a product name string. The full information
|
||||||
|
about the descriptor could be found at UFS specifications 2.1.
|
||||||
|
The file is read only.
|
||||||
|
|
||||||
|
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/oem_id
|
||||||
|
Date: February 2018
|
||||||
|
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||||
|
Description: This file contains a OEM ID string. The full information
|
||||||
|
about the descriptor could be found at UFS specifications 2.1.
|
||||||
|
The file is read only.
|
||||||
|
|
||||||
|
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/serial_number
|
||||||
|
Date: February 2018
|
||||||
|
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||||
|
Description: This file contains a device serial number string. The full
|
||||||
|
information about the descriptor could be found at
|
||||||
|
UFS specifications 2.1.
|
||||||
|
The file is read only.
|
||||||
|
|
||||||
|
What: /sys/bus/platform/drivers/ufshcd/*/string_descriptors/product_revision
|
||||||
|
Date: February 2018
|
||||||
|
Contact: Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
|
||||||
|
Description: This file contains a product revision string. The full
|
||||||
|
information about the descriptor could be found at
|
||||||
|
UFS specifications 2.1.
|
||||||
|
The file is read only.
|
||||||
|
|
|
@ -484,6 +484,61 @@ static const struct attribute_group ufs_sysfs_power_descriptor_group = {
|
||||||
.attrs = ufs_sysfs_power_descriptor,
|
.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[] = {
|
static const struct attribute_group *ufs_sysfs_groups[] = {
|
||||||
&ufs_sysfs_default_group,
|
&ufs_sysfs_default_group,
|
||||||
&ufs_sysfs_device_descriptor_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_geometry_descriptor_group,
|
||||||
&ufs_sysfs_health_descriptor_group,
|
&ufs_sysfs_health_descriptor_group,
|
||||||
&ufs_sysfs_power_descriptor_group,
|
&ufs_sysfs_power_descriptor_group,
|
||||||
|
&ufs_sysfs_string_descriptors_group,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2873,11 +2873,11 @@ out:
|
||||||
* The buf_len parameter will contain, on return, the length parameter
|
* The buf_len parameter will contain, on return, the length parameter
|
||||||
* received on the response.
|
* received on the response.
|
||||||
*/
|
*/
|
||||||
static int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
|
int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
|
||||||
enum query_opcode opcode,
|
enum query_opcode opcode,
|
||||||
enum desc_idn idn, u8 index,
|
enum desc_idn idn, u8 index,
|
||||||
u8 selector,
|
u8 selector,
|
||||||
u8 *desc_buf, int *buf_len)
|
u8 *desc_buf, int *buf_len)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
int retries;
|
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
|
* Return 0 in case of success, non-zero otherwise
|
||||||
*/
|
*/
|
||||||
#define ASCII_STD true
|
#define ASCII_STD true
|
||||||
static int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
|
int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
|
||||||
u8 *buf, u32 size, bool ascii)
|
u8 *buf, u32 size, bool ascii)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
|
|
@ -842,6 +842,12 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expose Query-Request API */
|
/* 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,
|
int ufshcd_read_desc_param(struct ufs_hba *hba,
|
||||||
enum desc_idn desc_id,
|
enum desc_idn desc_id,
|
||||||
int desc_index,
|
int desc_index,
|
||||||
|
@ -850,6 +856,9 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
|
||||||
u8 param_size);
|
u8 param_size);
|
||||||
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
|
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
|
||||||
enum flag_idn idn, bool *flag_res);
|
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);
|
int ufshcd_hold(struct ufs_hba *hba, bool async);
|
||||||
void ufshcd_release(struct ufs_hba *hba);
|
void ufshcd_release(struct ufs_hba *hba);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue