2017-12-28 13:29:36

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 0/9] ufs: sysfs: read-only access to device descriptors, attributes and flags

This patch introduces sysfs entries that will provide read-only access to
device management data that could be received with UFS query requests.
User-space applications will be able to read UFS device descriptors,
flags and attributes. This will allow to get full UFS device configuration
and its status. The descriptors are provided as set of files representing
its parameters. The flags are using "true"/"false" representation of
their value. The attributes are shown as hexadecimal value. The
descriptors, attributes and flags are placed in separate subfolders under
the UFS device sysfs entry (/sys/bus/platform/drivers/ufshcd/*/). The
string descriptor subfolder contains five string descriptors defined by
UFS specification 2.1. The LUN specific descriptor and attribute are
placed under corresponding SCSI device sysfs entries
(/sys/class/scsi_device/*/device/).
In addition the patch presents an additional field in the
scsi_host_template structure - struct attribute_group **sdev_group.
This field allows to define groups of attributes. It will provide an
ability to use binary attributes in addition to device attributes and
to group them under subfolders if necessary.

Changelog:
v2 -> v3
The Makefile is updated to make ufs-sysfs.c part of the ufshcd module.
The unnecessary EXPORT_SYMBOL were removed
Added a legal info header to the new files
The date in Documentation/ABI/testing/sysfs-driver-ufs was updated.

v1 -> v2
Provided additional description for the changes

Stanislav Nijnikov (9):
ufs: sysfs: device descriptor
ufs: sysfs: interconnect descriptor
ufs: sysfs: geometry descriptor
ufs: sysfs: health descriptor
ufs: sysfs: power descriptor
ufs: sysfs: string descriptors
ufs: sysfs: unit descriptor
ufs: sysfs: flags
ufs: sysfs: attributes

Documentation/ABI/testing/sysfs-driver-ufs | 804 +++++++++++++++++++++++++++++
drivers/scsi/scsi_sysfs.c | 14 +
drivers/scsi/ufs/Makefile | 3 +-
drivers/scsi/ufs/ufs-sysfs.c | 659 +++++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.h | 29 ++
drivers/scsi/ufs/ufs.h | 115 ++++-
drivers/scsi/ufs/ufshcd.c | 52 +-
drivers/scsi/ufs/ufshcd.h | 25 +
include/scsi/scsi_host.h | 6 +
9 files changed, 1674 insertions(+), 33 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-driver-ufs
create mode 100644 drivers/scsi/ufs/ufs-sysfs.c
create mode 100644 drivers/scsi/ufs/ufs-sysfs.h

--
2.7.4


2017-12-28 13:29:38

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 2/9] ufs: sysfs: interconnect descriptor

This patch introduces a sysfs group entry for the UFS interconnect
descriptor parameters. The group adds "interconnect_descriptor" folder
under the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*).
The parameters are shown as hexadecimal numbers. The full information
about the parameters could be found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov <[email protected]>

Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Stanislav Nijnikov <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 19 +++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.c | 18 ++++++++++++++++++
drivers/scsi/ufs/ufs.h | 8 ++++++++
3 files changed, 45 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index 17cc4aa..f982e46 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -221,3 +221,22 @@ Description: This file shows the command maximum timeout for a change
parameters. 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/*/interconnect_descriptor/unipro_version
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the MIPI UniPro version number in BCD format.
+ This is one of the UFS interconnect descriptor parameters.
+ 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/*/interconnect_descriptor/mphy_version
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the MIPI M-PHY version number in BCD format.
+ This is one of the UFS interconnect descriptor parameters.
+ The full information about the descriptor could be found at
+ UFS specifications 2.1.
+ The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 1c685f3..9f7627e 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -148,8 +148,26 @@ static const struct attribute_group ufs_sysfs_device_descriptor_group = {
.attrs = ufs_sysfs_device_descriptor,
};

+#define UFS_INTERCONNECT_DESC_PARAM(_name, _uname, _size) \
+ UFS_DESC_PARAM(_name, _uname, INTERCONNECT, _size)
+
+UFS_INTERCONNECT_DESC_PARAM(unipro_version, UNIPRO_VER, WORD);
+UFS_INTERCONNECT_DESC_PARAM(mphy_version, MPHY_VER, WORD);
+
+static struct attribute *ufs_sysfs_interconnect_descriptor[] = {
+ &dev_attr_unipro_version.attr,
+ &dev_attr_mphy_version.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_interconnect_descriptor_group = {
+ .name = "interconnect_descriptor",
+ .attrs = ufs_sysfs_interconnect_descriptor,
+};
+
static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_device_descriptor_group,
+ &ufs_sysfs_interconnect_descriptor_group,
NULL,
};

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 6ae1e08..773c049 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -230,6 +230,14 @@ enum device_desc_param {
DEVICE_DESC_PARAM_PRDCT_REV = 0x2A,
};

+/* Interconnect descriptor parameters offsets in bytes*/
+enum interconnect_desc_param {
+ INTERCONNECT_DESC_PARAM_LEN = 0x0,
+ INTERCONNECT_DESC_PARAM_TYPE = 0x1,
+ INTERCONNECT_DESC_PARAM_UNIPRO_VER = 0x2,
+ INTERCONNECT_DESC_PARAM_MPHY_VER = 0x4,
+};
+
/*
* Logical Unit Write Protect
* 00h: LU not write protected
--
2.7.4

2017-12-28 13:29:42

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 6/9] 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 <[email protected]>

Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Stanislav Nijnikov <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 39 ++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.c | 58 ++++++++++++++++++++++++++++++
drivers/scsi/ufs/ufshcd.c | 4 +--
drivers/scsi/ufs/ufshcd.h | 3 ++
4 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index 48cd49c..ff292127 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -451,3 +451,42 @@ Description: This file shows maximum VCC, VCCQ and VCCQ2 value for
power descriptor parameters. 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/manufacturer_name
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+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: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+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: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+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: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+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: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+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.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 0db4bed..f3ef281 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -387,12 +387,70 @@ static const struct attribute_group ufs_sysfs_power_descriptor_group = {
.attrs = ufs_sysfs_power_descriptor,
};

+#define ufs_sysfs_string_descriptor_show(_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; \
+}
+
+#define UFS_STRING_DESCRIPTOR(_name, _pname) \
+ ufs_sysfs_string_descriptor_show(_name, _pname) \
+ 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_device_descriptor_group,
&ufs_sysfs_interconnect_descriptor_group,
&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 6ed31ca..8703c81 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3114,8 +3114,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 2235e7d..e5c2615 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -848,6 +848,9 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
u8 *desc_buf, int *buf_len);
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);

--
2.7.4

2017-12-28 13:29:53

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 8/9] ufs: sysfs: flags

This patch introduces a sysfs group entry for the UFS flags. The group adds
"flags" folder under the UFS driver sysfs entry
(/sys/bus/platform/drivers/ufshcd/*). The flags are shown as boolean value
("true" or "false"). The full information about the UFS flags could be
found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 65 ++++++++++++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.c | 42 +++++++++++++++++++
drivers/scsi/ufs/ufs.h | 14 +++++--
3 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index e5f66e3..90f8574 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -598,3 +598,68 @@ Description: This file shows the granularity of the LUN. This is one of
the UFS unit descriptor parameters. 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/*/flags/device_init
+Date: August 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the device init status. The full information
+ about the flag could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/flags/permanent_wpe
+Date: August 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows whether permanent write protection is enabled.
+ The full information about the flag could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe
+Date: August 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows whether write protection is enabled on all
+ logical units configured as power on write protected. The
+ full information about the flag could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable
+Date: August 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows whether the device background operations are
+ enabled. The full information about the flag could be
+ found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/flags/life_span_mode_enable
+Date: August 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows whether the device life span mode is enabled.
+ The full information about the flag could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal
+Date: August 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows whether physical resource removal is enable.
+ The full information about the flag could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/flags/busy_rtc
+Date: August 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows whether the device is executing internal
+ operation related to real time clock. The full information
+ about the flag could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/flags/disable_fw_update
+Date: August 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows whether the device FW update is permanently
+ disabled. The full information about the flag could be found
+ at UFS specifications 2.1.
+ The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 3d08abf..2095124 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -443,6 +443,47 @@ static const struct attribute_group ufs_sysfs_string_descriptors_group = {
.attrs = ufs_sysfs_string_descriptors,
};

+#define ufs_sysfs_flag_show(_name, _uname) \
+static ssize_t _name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ bool flag; \
+ struct ufs_hba *hba = dev_get_drvdata(dev); \
+ if (ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG, \
+ QUERY_FLAG_IDN_##_uname, &flag)) \
+ return -EINVAL; \
+ return sprintf(buf, "%s\n", flag ? "true" : "false"); \
+}
+
+#define UFS_FLAG(_name, _uname) \
+ ufs_sysfs_flag_show(_name, _uname) \
+ static DEVICE_ATTR_RO(_name)
+
+UFS_FLAG(device_init, FDEVICEINIT);
+UFS_FLAG(permanent_wpe, PERMANENT_WPE);
+UFS_FLAG(power_on_wpe, PWR_ON_WPE);
+UFS_FLAG(bkops_enable, BKOPS_EN);
+UFS_FLAG(life_span_mode_enable, LIFE_SPAN_MODE_ENABLE);
+UFS_FLAG(phy_resource_removal, FPHYRESOURCEREMOVAL);
+UFS_FLAG(busy_rtc, BUSY_RTC);
+UFS_FLAG(disable_fw_update, PERMANENTLY_DISABLE_FW_UPDATE);
+
+static struct attribute *ufs_sysfs_device_flags[] = {
+ &dev_attr_device_init.attr,
+ &dev_attr_permanent_wpe.attr,
+ &dev_attr_power_on_wpe.attr,
+ &dev_attr_bkops_enable.attr,
+ &dev_attr_life_span_mode_enable.attr,
+ &dev_attr_phy_resource_removal.attr,
+ &dev_attr_busy_rtc.attr,
+ &dev_attr_disable_fw_update.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_flags_group = {
+ .name = "flags",
+ .attrs = ufs_sysfs_device_flags,
+};

static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_device_descriptor_group,
@@ -451,6 +492,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_health_descriptor_group,
&ufs_sysfs_power_descriptor_group,
&ufs_sysfs_string_descriptors_group,
+ &ufs_sysfs_flags_group,
NULL,
};

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 7387059..df5e73e 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -130,9 +130,17 @@ enum {

/* Flag idn for Query Requests*/
enum flag_idn {
- QUERY_FLAG_IDN_FDEVICEINIT = 0x01,
- QUERY_FLAG_IDN_PWR_ON_WPE = 0x03,
- QUERY_FLAG_IDN_BKOPS_EN = 0x04,
+ QUERY_FLAG_IDN_FDEVICEINIT = 0x01,
+ QUERY_FLAG_IDN_PERMANENT_WPE = 0x02,
+ QUERY_FLAG_IDN_PWR_ON_WPE = 0x03,
+ QUERY_FLAG_IDN_BKOPS_EN = 0x04,
+ QUERY_FLAG_IDN_LIFE_SPAN_MODE_ENABLE = 0x05,
+ QUERY_FLAG_IDN_PURGE_ENABLE = 0x06,
+ QUERY_FLAG_IDN_RESERVED2 = 0x07,
+ QUERY_FLAG_IDN_FPHYRESOURCEREMOVAL = 0x08,
+ QUERY_FLAG_IDN_BUSY_RTC = 0x09,
+ QUERY_FLAG_IDN_RESERVED3 = 0x0A,
+ QUERY_FLAG_IDN_PERMANENTLY_DISABLE_FW_UPDATE = 0x0B,
};

/* Attribute idn for Query requests */
--
2.7.4

2017-12-28 13:29:51

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 9/9] ufs: sysfs: attributes

This patch introduces a sysfs group entry for the UFS attributes. The
group adds "attributes" folder under the UFS driver sysfs entry
(/sys/bus/platform/drivers/ufshcd/*). The attributes are shown
as hexadecimal numbers. The full information about the attributes could
be found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 155 +++++++++++++++++++++++++++--
drivers/scsi/ufs/ufs-sysfs.c | 89 +++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.h | 1 +
drivers/scsi/ufs/ufs.h | 27 ++++-
drivers/scsi/ufs/ufshcd.c | 5 +-
drivers/scsi/ufs/ufshcd.h | 2 +
6 files changed, 265 insertions(+), 14 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index 90f8574..f2c3679 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -601,14 +601,14 @@ Description: This file shows the granularity of the LUN. This is one of


What: /sys/bus/platform/drivers/ufshcd/*/flags/device_init
-Date: August 2017
+Date: December 2017
Contact: Stanislav Nijnikov <[email protected]>
Description: This file shows the device init status. The full information
about the flag could be found at UFS specifications 2.1.
The file is read only.

What: /sys/bus/platform/drivers/ufshcd/*/flags/permanent_wpe
-Date: August 2017
+Date: December 2017
Contact: Stanislav Nijnikov <[email protected]>
Description: This file shows whether permanent write protection is enabled.
The full information about the flag could be found at
@@ -616,7 +616,7 @@ Description: This file shows whether permanent write protection is enabled.
The file is read only.

What: /sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe
-Date: August 2017
+Date: December 2017
Contact: Stanislav Nijnikov <[email protected]>
Description: This file shows whether write protection is enabled on all
logical units configured as power on write protected. The
@@ -625,7 +625,7 @@ Description: This file shows whether write protection is enabled on all
The file is read only.

What: /sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable
-Date: August 2017
+Date: December 2017
Contact: Stanislav Nijnikov <[email protected]>
Description: This file shows whether the device background operations are
enabled. The full information about the flag could be
@@ -633,7 +633,7 @@ Description: This file shows whether the device background operations are
The file is read only.

What: /sys/bus/platform/drivers/ufshcd/*/flags/life_span_mode_enable
-Date: August 2017
+Date: December 2017
Contact: Stanislav Nijnikov <[email protected]>
Description: This file shows whether the device life span mode is enabled.
The full information about the flag could be found at
@@ -641,7 +641,7 @@ Description: This file shows whether the device life span mode is enabled.
The file is read only.

What: /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal
-Date: August 2017
+Date: December 2017
Contact: Stanislav Nijnikov <[email protected]>
Description: This file shows whether physical resource removal is enable.
The full information about the flag could be found at
@@ -649,7 +649,7 @@ Description: This file shows whether physical resource removal is enable.
The file is read only.

What: /sys/bus/platform/drivers/ufshcd/*/flags/busy_rtc
-Date: August 2017
+Date: December 2017
Contact: Stanislav Nijnikov <[email protected]>
Description: This file shows whether the device is executing internal
operation related to real time clock. The full information
@@ -657,9 +657,148 @@ Description: This file shows whether the device is executing internal
The file is read only.

What: /sys/bus/platform/drivers/ufshcd/*/flags/disable_fw_update
-Date: August 2017
+Date: December 2017
Contact: Stanislav Nijnikov <[email protected]>
Description: This file shows whether the device FW update is permanently
disabled. The full information about the flag could be found
at UFS specifications 2.1.
The file is read only.
+
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/boot_lun_enabled
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the boot lun enabled UFS device attribute.
+ The full information about the attribute could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/current_power_mode
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the current power mode UFS device attribute.
+ The full information about the attribute could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/active_icc_level
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the active icc level UFS device attribute.
+ The full information about the attribute could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/ooo_data_enabled
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the out of order data transfer enabled UFS
+ device attribute. The full information about the attribute
+ could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/bkops_status
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the background operations status UFS device
+ attribute. The full information about the attribute could
+ be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/purge_status
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the purge operation status UFS device
+ attribute. The full information about the attribute could
+ be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_in_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the maximum data size in a DATA IN
+ UPIU. The full information about the attribute could
+ be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_out_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the maximum number of bytes that can be
+ requested with a READY TO TRANSFER UPIU. The full information
+ about the attribute could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/reference_clock_frequency
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the reference clock frequency UFS device
+ attribute. The full information about the attribute could
+ be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/configuration_descriptor_lock
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows whether the configuration descriptor is locked.
+ The full information about the attribute could be found at
+ UFS specifications 2.1. The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_number_of_rtt
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the maximum current number of
+ outstanding RTTs in device that is allowed. The full
+ information about the attribute could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_control
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the exception event control UFS device
+ attribute. The full information about the attribute could
+ be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_status
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the exception event status UFS device
+ attribute. The full information about the attribute could
+ be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/ffu_status
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file provides the ffu status UFS device attribute.
+ The full information about the attribute could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/psa_state
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file show the PSA feature status. The full information
+ about the attribute could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/attributes/psa_data_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the amount of data that the host plans to
+ load to all logical units in pre-soldering state.
+ The full information about the attribute could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+
+What: /sys/class/scsi_device/*/device/dyn_cap_needed
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the The amount of physical memory needed
+ to be removed from the physical memory resources pool of
+ the particular logical unit. The full information about
+ the attribute could be found at UFS specifications 2.1.
+ The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 2095124..f3ec1b0 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -485,6 +485,64 @@ static const struct attribute_group ufs_sysfs_flags_group = {
.attrs = ufs_sysfs_device_flags,
};

+#define ufs_sysfs_attribute_show_function(_name, _uname) \
+static ssize_t _name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct ufs_hba *hba = dev_get_drvdata(dev); \
+ u32 value; \
+ if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \
+ QUERY_ATTR_IDN_##_uname, 0, 0, &value)) \
+ return -EINVAL; \
+ return sprintf(buf, "0x%08X\n", value); \
+}
+
+#define UFS_ATTRIBUTE(_name, _uname) \
+ ufs_sysfs_attribute_show_function(_name, _uname) \
+ static DEVICE_ATTR_RO(_name)
+
+UFS_ATTRIBUTE(boot_lun_enabled, BOOT_LU_EN);
+UFS_ATTRIBUTE(current_power_mode, POWER_MODE);
+UFS_ATTRIBUTE(active_icc_level, ACTIVE_ICC_LVL);
+UFS_ATTRIBUTE(ooo_data_enabled, OOO_DATA_EN);
+UFS_ATTRIBUTE(bkops_status, BKOPS_STATUS);
+UFS_ATTRIBUTE(purge_status, PURGE_STATUS);
+UFS_ATTRIBUTE(max_data_in_size, MAX_DATA_IN);
+UFS_ATTRIBUTE(max_data_out_size, MAX_DATA_OUT);
+UFS_ATTRIBUTE(reference_clock_frequency, REF_CLK_FREQ);
+UFS_ATTRIBUTE(configuration_descriptor_lock, CONF_DESC_LOCK);
+UFS_ATTRIBUTE(max_number_of_rtt, MAX_NUM_OF_RTT);
+UFS_ATTRIBUTE(exception_event_control, EE_CONTROL);
+UFS_ATTRIBUTE(exception_event_status, EE_STATUS);
+UFS_ATTRIBUTE(ffu_status, FFU_STATUS);
+UFS_ATTRIBUTE(psa_state, PSA_STATE);
+UFS_ATTRIBUTE(psa_data_size, PSA_DATA_SIZE);
+
+static struct attribute *ufs_sysfs_attributes[] = {
+ &dev_attr_boot_lun_enabled.attr,
+ &dev_attr_current_power_mode.attr,
+ &dev_attr_active_icc_level.attr,
+ &dev_attr_ooo_data_enabled.attr,
+ &dev_attr_bkops_status.attr,
+ &dev_attr_purge_status.attr,
+ &dev_attr_max_data_in_size.attr,
+ &dev_attr_max_data_out_size.attr,
+ &dev_attr_reference_clock_frequency.attr,
+ &dev_attr_configuration_descriptor_lock.attr,
+ &dev_attr_max_number_of_rtt.attr,
+ &dev_attr_exception_event_control.attr,
+ &dev_attr_exception_event_status.attr,
+ &dev_attr_ffu_status.attr,
+ &dev_attr_psa_state.attr,
+ &dev_attr_psa_data_size.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_attributes_group = {
+ .name = "attributes",
+ .attrs = ufs_sysfs_attributes,
+};
+
static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_device_descriptor_group,
&ufs_sysfs_interconnect_descriptor_group,
@@ -493,6 +551,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_power_descriptor_group,
&ufs_sysfs_string_descriptors_group,
&ufs_sysfs_flags_group,
+ &ufs_sysfs_attributes_group,
NULL,
};

@@ -553,6 +612,36 @@ struct attribute_group ufs_sysfs_unit_descriptor_group = {
.attrs = ufs_sysfs_unit_descriptor,
};

+#define ufs_sysfs_lun_attribute_show_function(_name, _uname) \
+static ssize_t _name##_attribute_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ u32 value; \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ struct ufs_hba *hba = shost_priv(sdev->host); \
+ u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun); \
+ if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \
+ QUERY_ATTR_IDN_##_uname, lun, 0, &value)) \
+ return -EINVAL; \
+ return sprintf(buf, "0x%08X\n", value); \
+}
+
+#define UFS_LUN_ATTRIBUTE(_name, _uname) \
+ ufs_sysfs_lun_attribute_show_function(_name, _uname) \
+ static DEVICE_ATTR_RO(_name##_attribute)
+
+
+UFS_LUN_ATTRIBUTE(dyn_cap_needed, DYN_CAP_NEEDED);
+
+static struct attribute *ufs_sysfs_lun_attributes[] = {
+ &dev_attr_dyn_cap_needed_attribute.attr,
+ NULL,
+};
+
+struct attribute_group ufs_sysfs_lun_attributes_group = {
+ .attrs = ufs_sysfs_lun_attributes,
+};
+
void ufs_sysfs_add_device_management(struct ufs_hba *hba)
{
int ret;
diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
index 1ec1217..cff5360 100644
--- a/drivers/scsi/ufs/ufs-sysfs.h
+++ b/drivers/scsi/ufs/ufs-sysfs.h
@@ -25,4 +25,5 @@ void ufs_sysfs_add_device_management(struct ufs_hba *hba);
void ufs_sysfs_remove_device_management(struct ufs_hba *hba);

extern struct attribute_group ufs_sysfs_unit_descriptor_group;
+extern struct attribute_group ufs_sysfs_lun_attributes_group;
#endif
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index df5e73e..14e5bf7 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -145,10 +145,29 @@ enum flag_idn {

/* Attribute idn for Query requests */
enum attr_idn {
- QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
- QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
- QUERY_ATTR_IDN_EE_CONTROL = 0x0D,
- QUERY_ATTR_IDN_EE_STATUS = 0x0E,
+ QUERY_ATTR_IDN_BOOT_LU_EN = 0x00,
+ QUERY_ATTR_IDN_RESERVED = 0x01,
+ QUERY_ATTR_IDN_POWER_MODE = 0x02,
+ QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
+ QUERY_ATTR_IDN_OOO_DATA_EN = 0x04,
+ QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
+ QUERY_ATTR_IDN_PURGE_STATUS = 0x06,
+ QUERY_ATTR_IDN_MAX_DATA_IN = 0x07,
+ QUERY_ATTR_IDN_MAX_DATA_OUT = 0x08,
+ QUERY_ATTR_IDN_DYN_CAP_NEEDED = 0x09,
+ QUERY_ATTR_IDN_REF_CLK_FREQ = 0x0A,
+ QUERY_ATTR_IDN_CONF_DESC_LOCK = 0x0B,
+ QUERY_ATTR_IDN_MAX_NUM_OF_RTT = 0x0C,
+ QUERY_ATTR_IDN_EE_CONTROL = 0x0D,
+ QUERY_ATTR_IDN_EE_STATUS = 0x0E,
+ QUERY_ATTR_IDN_SECONDS_PASSED = 0x0F,
+ QUERY_ATTR_IDN_CNTX_CONF = 0x10,
+ QUERY_ATTR_IDN_CORR_PRG_BLK_NUM = 0x11,
+ QUERY_ATTR_IDN_RESERVED2 = 0x12,
+ QUERY_ATTR_IDN_RESERVED3 = 0x13,
+ QUERY_ATTR_IDN_FFU_STATUS = 0x14,
+ QUERY_ATTR_IDN_PSA_STATE = 0x15,
+ QUERY_ATTR_IDN_PSA_DATA_SIZE = 0x16,
};

/* Descriptor idn for Query requests */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3ddab23..6dab9a6 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2711,8 +2711,8 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
*
* Returns 0 for success, non-zero in case of failure
*/
-static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
- enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
+int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
+ enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
{
struct ufs_query_req *request = NULL;
struct ufs_query_res *response = NULL;
@@ -6489,6 +6489,7 @@ static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd)

static struct attribute_group *ufshcd_driver_groups[] = {
&ufs_sysfs_unit_descriptor_group,
+ &ufs_sysfs_lun_attributes_group,
NULL,
};

diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 209c563..5a1b21b 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -846,6 +846,8 @@ 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_attr(struct ufs_hba *hba, enum query_opcode opcode,
+ enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
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,
--
2.7.4

2017-12-28 13:30:28

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 7/9] ufs: sysfs: unit descriptor

This patch introduces a sysfs group entry for the UFS unit descriptor
parameters. The group adds "unit_descriptor" folder under the corresponding
SCSI device sysfs entry (/sys/class/scsi_device/*/device/). The parameters
are shown as hexadecimal numbers. The full information about the parameters
could be found at UFS specifications 2.1.
In addition the patch presents an additional field in the
scsi_host_template structure - struct attribute_group **sdev_group.
This field allows to define groups of attributes. It will provide an
ability to use binary attributes in addition to device attributes and
to group them under subfolders if necessary.

Signed-off-by: Stanislav Nijnikov <[email protected]>

Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Stanislav Nijnikov <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 108 +++++++++++++++++++++++++++++
drivers/scsi/scsi_sysfs.c | 14 ++++
drivers/scsi/ufs/ufs-sysfs.c | 57 +++++++++++++++
drivers/scsi/ufs/ufs-sysfs.h | 3 +
drivers/scsi/ufs/ufs.h | 11 +++
drivers/scsi/ufs/ufshcd.c | 23 ++----
drivers/scsi/ufs/ufshcd.h | 15 ++++
include/scsi/scsi_host.h | 6 ++
8 files changed, 221 insertions(+), 16 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index ff292127..e5f66e3 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -490,3 +490,111 @@ 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.
+
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/boot_lun_id
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows boot LUN information. This is one of
+ the UFS unit descriptor parameters. The full information
+ about the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/lun_write_protect
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows LUN write protection status. This is one of
+ the UFS unit descriptor parameters. The full information
+ about the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/lun_queue_depth
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows LUN queue depth. This is one of the UFS
+ unit descriptor parameters. The full information about
+ the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/psa_sensitive
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows PSA sensitivity. This is one of the UFS
+ unit descriptor parameters. The full information about
+ the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/lun_memory_type
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows LUN memory type. This is one of the UFS
+ unit descriptor parameters. The full information about
+ the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/data_reliability
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file defines the device behavior when a power failure
+ occurs during a write operation. This is one of the UFS
+ unit descriptor parameters. The full information about
+ the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/logical_block_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the size of addressable logical blocks
+ (calculated as an exponent with base 2). This is one of
+ the UFS unit descriptor parameters. The full information about
+ the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/logical_block_count
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows total number of addressable logical blocks.
+ This is one of the UFS unit descriptor parameters. The full
+ information about the descriptor could be found at
+ UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/erase_block_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the erase block size. This is one of
+ the UFS unit descriptor parameters. The full information
+ about the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/provisioning_type
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the thin provisioning type. This is one of
+ the UFS unit descriptor parameters. The full information
+ about the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/physical_memory_resourse_count
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the total physical memory resources. This is
+ one of the UFS unit descriptor parameters. The full information
+ about the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/context_capabilities
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the context capabilities. This is one of
+ the UFS unit descriptor parameters. The full information
+ about the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
+
+What: /sys/class/scsi_device/*/device/unit_descriptor/large_unit_granularity
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the granularity of the LUN. This is one of
+ the UFS unit descriptor parameters. The full information
+ about the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 91b90f6..9d5c834 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1310,6 +1310,14 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
}
}

+ if (sdev->host->hostt->sdev_groups) {
+ error = sysfs_create_groups(&sdev->sdev_gendev.kobj,
+ (const struct attribute_group **)
+ sdev->host->hostt->sdev_groups);
+ if (error)
+ return error;
+ }
+
scsi_autopm_put_device(sdev);
return error;
}
@@ -1327,6 +1335,12 @@ void __scsi_remove_device(struct scsi_device *sdev)
if (sdev->sdev_state == SDEV_DEL)
return;

+ if (sdev->host->hostt->sdev_groups) {
+ sysfs_remove_groups(&sdev->sdev_gendev.kobj,
+ (const struct attribute_group **)
+ sdev->host->hostt->sdev_groups);
+ }
+
if (sdev->is_visible) {
/*
* If scsi_internal_target_block() is running concurrently,
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index f3ef281..3d08abf 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -454,6 +454,63 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
NULL,
};

+#define ufs_sysfs_lun_desc_param_show(_pname, _puname, _duname, _size) \
+static ssize_t _pname##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct scsi_device *sdev = to_scsi_device(dev); \
+ struct ufs_hba *hba = shost_priv(sdev->host); \
+ u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun); \
+ if (!ufs_is_valid_unit_desc_lun(lun)) \
+ return -EINVAL; \
+ return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname, \
+ lun, buf, _duname##_DESC_PARAM_##_puname, \
+ UFS_PARAM_##_size##_SIZE); \
+}
+
+#define UFS_LUN_DESC_PARAM(_pname, _puname, _duname, _size) \
+ ufs_sysfs_lun_desc_param_show(_pname, _puname, _duname, _size) \
+ static DEVICE_ATTR_RO(_pname)
+
+#define UFS_UNIT_DESC_PARAM(_name, _uname, _size) \
+ UFS_LUN_DESC_PARAM(_name, _uname, UNIT, _size)
+
+UFS_UNIT_DESC_PARAM(boot_lun_id, BOOT_LUN_ID, BYTE);
+UFS_UNIT_DESC_PARAM(lun_write_protect, LU_WR_PROTECT, BYTE);
+UFS_UNIT_DESC_PARAM(lun_queue_depth, LU_Q_DEPTH, BYTE);
+UFS_UNIT_DESC_PARAM(psa_sensitive, PSA_SENSITIVE, BYTE);
+UFS_UNIT_DESC_PARAM(lun_memory_type, MEM_TYPE, BYTE);
+UFS_UNIT_DESC_PARAM(data_reliability, DATA_RELIABILITY, BYTE);
+UFS_UNIT_DESC_PARAM(logical_block_size, LOGICAL_BLK_SIZE, BYTE);
+UFS_UNIT_DESC_PARAM(logical_block_count, LOGICAL_BLK_COUNT, QWORD);
+UFS_UNIT_DESC_PARAM(erase_block_size, ERASE_BLK_SIZE, DWORD);
+UFS_UNIT_DESC_PARAM(provisioning_type, PROVISIONING_TYPE, BYTE);
+UFS_UNIT_DESC_PARAM(physical_memory_resourse_count, PHY_MEM_RSRC_CNT, QWORD);
+UFS_UNIT_DESC_PARAM(context_capabilities, CTX_CAPABILITIES, WORD);
+UFS_UNIT_DESC_PARAM(large_unit_granularity, LARGE_UNIT_SIZE_M1, BYTE);
+
+static struct attribute *ufs_sysfs_unit_descriptor[] = {
+ &dev_attr_boot_lun_id.attr,
+ &dev_attr_lun_write_protect.attr,
+ &dev_attr_lun_queue_depth.attr,
+ &dev_attr_psa_sensitive.attr,
+ &dev_attr_lun_memory_type.attr,
+ &dev_attr_data_reliability.attr,
+ &dev_attr_logical_block_size.attr,
+ &dev_attr_logical_block_count.attr,
+ &dev_attr_erase_block_size.attr,
+ &dev_attr_provisioning_type.attr,
+ &dev_attr_physical_memory_resourse_count.attr,
+ &dev_attr_context_capabilities.attr,
+ &dev_attr_large_unit_granularity.attr,
+ NULL,
+};
+
+struct attribute_group ufs_sysfs_unit_descriptor_group = {
+ .name = "unit_descriptor",
+ .attrs = ufs_sysfs_unit_descriptor,
+};
+
void ufs_sysfs_add_device_management(struct ufs_hba *hba)
{
int ret;
diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
index a1fc9dc..1ec1217 100644
--- a/drivers/scsi/ufs/ufs-sysfs.h
+++ b/drivers/scsi/ufs/ufs-sysfs.h
@@ -17,9 +17,12 @@
#define __UFS_SYSFS_H__

#include <linux/sysfs.h>
+#include <scsi/scsi_device.h>

#include "ufshcd.h"

void ufs_sysfs_add_device_management(struct ufs_hba *hba);
void ufs_sysfs_remove_device_management(struct ufs_hba *hba);
+
+extern struct attribute_group ufs_sysfs_unit_descriptor_group;
#endif
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 6bfeedb..7387059 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -182,6 +182,7 @@ enum unit_desc_param {
UNIT_DESC_PARAM_BOOT_LUN_ID = 0x4,
UNIT_DESC_PARAM_LU_WR_PROTECT = 0x5,
UNIT_DESC_PARAM_LU_Q_DEPTH = 0x6,
+ UNIT_DESC_PARAM_PSA_SENSITIVE = 0x7,
UNIT_DESC_PARAM_MEM_TYPE = 0x8,
UNIT_DESC_PARAM_DATA_RELIABILITY = 0x9,
UNIT_DESC_PARAM_LOGICAL_BLK_SIZE = 0xA,
@@ -592,4 +593,14 @@ struct ufs_dev_desc {
char model[MAX_MODEL_LEN + 1];
};

+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+ return lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN);
+}
+
#endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 8703c81..3ddab23 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2244,21 +2244,6 @@ static int ufshcd_comp_scsi_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
return ret;
}

-/*
- * ufshcd_scsi_to_upiu_lun - maps scsi LUN to UPIU LUN
- * @scsi_lun: scsi LUN id
- *
- * Returns UPIU LUN id
- */
-static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun)
-{
- if (scsi_is_wlun(scsi_lun))
- return (scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID)
- | UFS_UPIU_WLUN_ID;
- else
- return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID;
-}
-
/**
* ufshcd_upiu_wlun_to_scsi_wlun - maps UPIU W-LUN id to SCSI W-LUN ID
* @scsi_lun: UPIU W-LUN id
@@ -3192,7 +3177,7 @@ static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba,
* Unit descriptors are only available for general purpose LUs (LUN id
* from 0 to 7) and RPMB Well known LU.
*/
- if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
+ if (!ufs_is_valid_unit_desc_lun(lun))
return -EOPNOTSUPP;

return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
@@ -6502,6 +6487,11 @@ static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd)
return found ? BLK_EH_NOT_HANDLED : BLK_EH_RESET_TIMER;
}

+static struct attribute_group *ufshcd_driver_groups[] = {
+ &ufs_sysfs_unit_descriptor_group,
+ NULL,
+};
+
static struct scsi_host_template ufshcd_driver_template = {
.module = THIS_MODULE,
.name = UFSHCD,
@@ -6521,6 +6511,7 @@ static struct scsi_host_template ufshcd_driver_template = {
.can_queue = UFSHCD_CAN_QUEUE,
.max_host_blocked = 1,
.track_queue_depth = 1,
+ .sdev_groups = ufshcd_driver_groups,
};

static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index e5c2615..209c563 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -993,4 +993,19 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
hba->vops->dbg_register_dump(hba);
}

+/*
+ * ufshcd_scsi_to_upiu_lun - maps scsi LUN to UPIU LUN
+ * @scsi_lun: scsi LUN id
+ *
+ * Returns UPIU LUN id
+ */
+static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun)
+{
+ if (scsi_is_wlun(scsi_lun))
+ return (scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID)
+ | UFS_UPIU_WLUN_ID;
+ else
+ return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID;
+}
+
#endif /* End of Header */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 1a1df0d..face126 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -477,6 +477,12 @@ struct scsi_host_template {
struct device_attribute **sdev_attrs;

/*
+ * Pointer to the SCSI device attribute groups for this host,
+ * NULL terminated.
+ */
+ struct attribute_group **sdev_groups;
+
+ /*
* List of hosts per template.
*
* This is only for use by scsi_module.c for legacy templates.
--
2.7.4

2017-12-28 13:30:48

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 4/9] ufs: sysfs: health descriptor

This patch introduces a sysfs group entry for the UFS health descriptor
parameters. The group adds "health_descriptor" folder under the UFS driver
sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown
as hexadecimal numbers. The full information about the parameters could be
found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov <[email protected]>

Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Stanislav Nijnikov <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 28 ++++++++++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.c | 20 ++++++++++++++++++++
drivers/scsi/ufs/ufs.h | 11 +++++++++++
drivers/scsi/ufs/ufshcd.c | 8 ++++++++
drivers/scsi/ufs/ufshcd.h | 1 +
5 files changed, 68 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index 55134d3..6ba0f4d 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -413,3 +413,31 @@ Description: This file shows the memory capacity adjustment factor for
descriptor parameters. 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/*/health_descriptor/eol_info
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows preend of life information. This is one
+ of the UFS health descriptor parameters. 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/*/health_descriptor/life_time_estimation_a
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows indication of the device life time
+ (method a). This is one of the UFS health descriptor
+ parameters. 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/*/health_descriptor/life_time_estimation_b
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows indication of the device life time
+ (method b). This is one of the UFS health descriptor
+ parameters. The full information about the descriptor
+ could be found at UFS specifications 2.1.
+ The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index e439e92..ce6d27e 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -248,10 +248,30 @@ static const struct attribute_group ufs_sysfs_geometry_descriptor_group = {
.attrs = ufs_sysfs_geometry_descriptor,
};

+#define UFS_HEALTH_DESC_PARAM(_name, _uname, _size) \
+ UFS_DESC_PARAM(_name, _uname, HEALTH, _size)
+
+UFS_HEALTH_DESC_PARAM(eol_info, EOL_INFO, BYTE);
+UFS_HEALTH_DESC_PARAM(life_time_estimation_a, LIFE_TIME_EST_A, BYTE);
+UFS_HEALTH_DESC_PARAM(life_time_estimation_b, LIFE_TIME_EST_B, BYTE);
+
+static struct attribute *ufs_sysfs_health_descriptor[] = {
+ &dev_attr_eol_info.attr,
+ &dev_attr_life_time_estimation_a.attr,
+ &dev_attr_life_time_estimation_b.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_health_descriptor_group = {
+ .name = "health_descriptor",
+ .attrs = ufs_sysfs_health_descriptor,
+};
+
static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_device_descriptor_group,
&ufs_sysfs_interconnect_descriptor_group,
&ufs_sysfs_geometry_descriptor_group,
+ &ufs_sysfs_health_descriptor_group,
NULL,
};

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 04d41c8..6bfeedb 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -154,6 +154,7 @@ enum desc_idn {
QUERY_DESC_IDN_RFU_1 = 0x6,
QUERY_DESC_IDN_GEOMETRY = 0x7,
QUERY_DESC_IDN_POWER = 0x8,
+ QUERY_DESC_IDN_HEALTH = 0x9,
QUERY_DESC_IDN_MAX,
};

@@ -169,6 +170,7 @@ enum ufs_desc_def_size {
QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06,
QUERY_DESC_GEOMETRY_DEF_SIZE = 0x44,
QUERY_DESC_POWER_DEF_SIZE = 0x62,
+ QUERY_DESC_HEALTH_DEF_SIZE = 0x25,
};

/* Unit descriptor parameters offsets in bytes*/
@@ -274,6 +276,15 @@ enum geometry_desc_param {
GEOMETRY_DESC_PARAM_OPT_LOG_BLK_SIZE = 0x44,
};

+/* Health descriptor parameters offsets in bytes*/
+enum health_desc_param {
+ HEALTH_DESC_PARAM_LEN = 0x0,
+ HEALTH_DESC_PARAM_TYPE = 0x1,
+ HEALTH_DESC_PARAM_EOL_INFO = 0x2,
+ HEALTH_DESC_PARAM_LIFE_TIME_EST_A = 0x3,
+ HEALTH_DESC_PARAM_LIFE_TIME_EST_B = 0x4,
+};
+
/*
* Logical Unit Write Protect
* 00h: LU not write protected
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 97dcb52..6ed31ca 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2987,6 +2987,9 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba,
case QUERY_DESC_IDN_STRING:
*desc_len = QUERY_DESC_MAX_SIZE;
break;
+ case QUERY_DESC_IDN_HEALTH:
+ *desc_len = hba->desc_size.hlth_desc;
+ break;
case QUERY_DESC_IDN_RFU_0:
case QUERY_DESC_IDN_RFU_1:
*desc_len = 0;
@@ -6298,6 +6301,10 @@ static void ufshcd_init_desc_sizes(struct ufs_hba *hba)
&hba->desc_size.geom_desc);
if (err)
hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE;
+ err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_HEALTH, 0,
+ &hba->desc_size.hlth_desc);
+ if (err)
+ hba->desc_size.hlth_desc = QUERY_DESC_HEALTH_DEF_SIZE;
}

static void ufshcd_def_desc_sizes(struct ufs_hba *hba)
@@ -6308,6 +6315,7 @@ static void ufshcd_def_desc_sizes(struct ufs_hba *hba)
hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE;
hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE;
hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE;
+ hba->desc_size.hlth_desc = QUERY_DESC_HEALTH_DEF_SIZE;
}

/**
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 6a0ec4b..2235e7d 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -229,6 +229,7 @@ struct ufs_desc_size {
int interc_desc;
int unit_desc;
int conf_desc;
+ int hlth_desc;
};

/**
--
2.7.4

2017-12-28 13:30:46

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 5/9] ufs: sysfs: power descriptor

This patch introduces a sysfs group entry for the UFS power descriptor
parameters. The group adds "power_descriptor" folder under the UFS driver
sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown
as hexadecimal numbers. The full information about the parameters could be
found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov <[email protected]>

Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Stanislav Nijnikov <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 10 +++
drivers/scsi/ufs/ufs-sysfs.c | 121 +++++++++++++++++++++++++++++
2 files changed, 131 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index 6ba0f4d..48cd49c 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -441,3 +441,13 @@ Description: This file shows indication of the device life time
parameters. 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/*/power_descriptor/active_icc_levels_vcc*
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows maximum VCC, VCCQ and VCCQ2 value for
+ active ICC levels from 0 to 15. This is one of the UFS
+ power descriptor parameters. The full information about
+ the descriptor could be found at UFS specifications 2.1.
+ The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index ce6d27e..0db4bed 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -267,11 +267,132 @@ static const struct attribute_group ufs_sysfs_health_descriptor_group = {
.attrs = ufs_sysfs_health_descriptor,
};

+#define ufs_sysfs_power_desc_param_show(_name, _puname, _index) \
+static ssize_t _name##_index##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct ufs_hba *hba = dev_get_drvdata(dev); \
+ return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_POWER, 0, buf, \
+ PWR_DESC_##_puname##_0 + _index * UFS_PARAM_WORD_SIZE, \
+ UFS_PARAM_WORD_SIZE); \
+}
+
+#define UFS_POWER_DESC_PARAM(_pname, _puname, _index) \
+ ufs_sysfs_power_desc_param_show(_pname, _puname, _index) \
+ static DEVICE_ATTR_RO(_pname##_index)
+
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 0);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 1);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 2);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 3);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 4);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 5);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 6);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 7);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 8);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 9);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 10);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 11);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 12);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 13);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 14);
+UFS_POWER_DESC_PARAM(active_icc_levels_vcc, ACTIVE_LVLS_VCC, 15);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 0);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 1);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 2);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 3);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 4);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 5);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 6);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 7);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 8);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 9);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 10);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 11);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 12);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 13);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 14);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq, ACTIVE_LVLS_VCCQ, 15);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 0);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 1);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 2);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 3);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 4);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 5);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 6);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 7);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 8);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 9);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 10);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 11);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 12);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 13);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 14);
+UFS_POWER_DESC_PARAM(active_icc_levels_vccq2, ACTIVE_LVLS_VCCQ2, 15);
+
+static struct attribute *ufs_sysfs_power_descriptor[] = {
+ &dev_attr_active_icc_levels_vcc0.attr,
+ &dev_attr_active_icc_levels_vcc1.attr,
+ &dev_attr_active_icc_levels_vcc2.attr,
+ &dev_attr_active_icc_levels_vcc3.attr,
+ &dev_attr_active_icc_levels_vcc4.attr,
+ &dev_attr_active_icc_levels_vcc5.attr,
+ &dev_attr_active_icc_levels_vcc6.attr,
+ &dev_attr_active_icc_levels_vcc7.attr,
+ &dev_attr_active_icc_levels_vcc8.attr,
+ &dev_attr_active_icc_levels_vcc9.attr,
+ &dev_attr_active_icc_levels_vcc10.attr,
+ &dev_attr_active_icc_levels_vcc11.attr,
+ &dev_attr_active_icc_levels_vcc12.attr,
+ &dev_attr_active_icc_levels_vcc13.attr,
+ &dev_attr_active_icc_levels_vcc14.attr,
+ &dev_attr_active_icc_levels_vcc15.attr,
+ &dev_attr_active_icc_levels_vccq0.attr,
+ &dev_attr_active_icc_levels_vccq1.attr,
+ &dev_attr_active_icc_levels_vccq2.attr,
+ &dev_attr_active_icc_levels_vccq3.attr,
+ &dev_attr_active_icc_levels_vccq4.attr,
+ &dev_attr_active_icc_levels_vccq5.attr,
+ &dev_attr_active_icc_levels_vccq6.attr,
+ &dev_attr_active_icc_levels_vccq7.attr,
+ &dev_attr_active_icc_levels_vccq8.attr,
+ &dev_attr_active_icc_levels_vccq9.attr,
+ &dev_attr_active_icc_levels_vccq10.attr,
+ &dev_attr_active_icc_levels_vccq11.attr,
+ &dev_attr_active_icc_levels_vccq12.attr,
+ &dev_attr_active_icc_levels_vccq13.attr,
+ &dev_attr_active_icc_levels_vccq14.attr,
+ &dev_attr_active_icc_levels_vccq15.attr,
+ &dev_attr_active_icc_levels_vccq20.attr,
+ &dev_attr_active_icc_levels_vccq21.attr,
+ &dev_attr_active_icc_levels_vccq22.attr,
+ &dev_attr_active_icc_levels_vccq23.attr,
+ &dev_attr_active_icc_levels_vccq24.attr,
+ &dev_attr_active_icc_levels_vccq25.attr,
+ &dev_attr_active_icc_levels_vccq26.attr,
+ &dev_attr_active_icc_levels_vccq27.attr,
+ &dev_attr_active_icc_levels_vccq28.attr,
+ &dev_attr_active_icc_levels_vccq29.attr,
+ &dev_attr_active_icc_levels_vccq210.attr,
+ &dev_attr_active_icc_levels_vccq211.attr,
+ &dev_attr_active_icc_levels_vccq212.attr,
+ &dev_attr_active_icc_levels_vccq213.attr,
+ &dev_attr_active_icc_levels_vccq214.attr,
+ &dev_attr_active_icc_levels_vccq215.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_power_descriptor_group = {
+ .name = "power_descriptor",
+ .attrs = ufs_sysfs_power_descriptor,
+};
+
static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_device_descriptor_group,
&ufs_sysfs_interconnect_descriptor_group,
&ufs_sysfs_geometry_descriptor_group,
&ufs_sysfs_health_descriptor_group,
+ &ufs_sysfs_power_descriptor_group,
NULL,
};

--
2.7.4

2017-12-28 13:31:21

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 3/9] ufs: sysfs: geometry descriptor

This patch introduces a sysfs group entry for the UFS geometry descriptor
parameters. The group adds "geometry_descriptor" folder under the UFS
driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters
are shown as hexadecimal numbers. The full information about the parameters
could be found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov <[email protected]>

Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Stanislav Nijnikov <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 173 +++++++++++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.c | 84 ++++++++++++++
drivers/scsi/ufs/ufs.h | 36 ++++++
3 files changed, 293 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index f982e46..55134d3 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -240,3 +240,176 @@ Description: This file shows the MIPI M-PHY version number in BCD format.
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/*/geometry_descriptor/raw_device_capacity
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the total memory quantity available to
+ the user to configure the device logical units. This is one
+ of the UFS geometry descriptor parameters. 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/*/geometry_descriptor/max_number_of_luns
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the maximum number of logical units
+ supported by the UFS device. This is one of the UFS
+ geometry descriptor parameters. 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/*/geometry_descriptor/segment_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the segment size. This is one of the UFS
+ geometry descriptor parameters. 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/*/geometry_descriptor/allocation_unit_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the allocation unit size. This is one of
+ the UFS geometry descriptor parameters. 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/*/geometry_descriptor/min_addressable_block_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the minimum addressable block size. This
+ is one of the UFS geometry descriptor parameters. 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/*/geometry_descriptor/optimal_read_block_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the optimal read block size. This is one
+ of the UFS geometry descriptor parameters. 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/*/geometry_descriptor/optimal_write_block_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the optimal write block size. This is one
+ of the UFS geometry descriptor parameters. 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/*/geometry_descriptor/max_in_buffer_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the maximum data-in buffer size. This
+ is one of the UFS geometry descriptor parameters. 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/*/geometry_descriptor/max_out_buffer_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the maximum data-out buffer size. This
+ is one of the UFS geometry descriptor parameters. 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/*/geometry_descriptor/rpmb_rw_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the maximum number of RPMB frames allowed
+ in Security Protocol In/Out. This is one of the UFS geometry
+ descriptor parameters. 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/*/geometry_descriptor/dyn_capacity_resource_policy
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the dynamic capacity resource policy. This
+ is one of the UFS geometry descriptor parameters. 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/*/geometry_descriptor/data_ordering
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows support for out-of-order data transfer.
+ This is one of the UFS geometry descriptor parameters.
+ 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/*/geometry_descriptor/max_number_of_contexts
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows maximum available number of contexts which
+ are supported by the device. This is one of the UFS geometry
+ descriptor parameters. 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/*/geometry_descriptor/sys_data_tag_unit_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows system data tag unit size. This is one of
+ the UFS geometry descriptor parameters. 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/*/geometry_descriptor/sys_data_tag_resource_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows maximum storage area size allocated by
+ the device to handle system data by the tagging mechanism.
+ This is one of the UFS geometry descriptor parameters.
+ 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/*/geometry_descriptor/secure_removal_types
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows supported secure removal types. This is
+ one of the UFS geometry descriptor parameters. 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/*/geometry_descriptor/memory_types
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows supported memory types. This is one of
+ the UFS geometry descriptor parameters. 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/*/geometry_descriptor/*_memory_max_alloc_units
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the maximum number of allocation units for
+ different memory types (system code, non persistent,
+ enhanced type 1-4). This is one of the UFS geometry
+ descriptor parameters. 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/*/geometry_descriptor/*_memory_capacity_adjustment_factor
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the memory capacity adjustment factor for
+ different memory types (system code, non persistent,
+ enhanced type 1-4). This is one of the UFS geometry
+ descriptor parameters. The full information about the
+ descriptor could be found at UFS specifications 2.1.
+ The file is read only.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 9f7627e..e439e92 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -165,9 +165,93 @@ static const struct attribute_group ufs_sysfs_interconnect_descriptor_group = {
.attrs = ufs_sysfs_interconnect_descriptor,
};

+#define UFS_GEOMETRY_DESC_PARAM(_name, _uname, _size) \
+ UFS_DESC_PARAM(_name, _uname, GEOMETRY, _size)
+
+UFS_GEOMETRY_DESC_PARAM(raw_device_capacity, DEV_CAP, QWORD);
+UFS_GEOMETRY_DESC_PARAM(max_number_of_luns, MAX_NUM_LUN, BYTE);
+UFS_GEOMETRY_DESC_PARAM(segment_size, SEG_SIZE, DWORD);
+UFS_GEOMETRY_DESC_PARAM(allocation_unit_size, ALLOC_UNIT_SIZE, BYTE);
+UFS_GEOMETRY_DESC_PARAM(min_addressable_block_size, MIN_BLK_SIZE, BYTE);
+UFS_GEOMETRY_DESC_PARAM(optimal_read_block_size, OPT_RD_BLK_SIZE, BYTE);
+UFS_GEOMETRY_DESC_PARAM(optimal_write_block_size, OPT_RD_BLK_SIZE, BYTE);
+UFS_GEOMETRY_DESC_PARAM(max_in_buffer_size, MAX_IN_BUF_SIZE, BYTE);
+UFS_GEOMETRY_DESC_PARAM(max_out_buffer_size, MAX_OUT_BUF_SIZE, BYTE);
+UFS_GEOMETRY_DESC_PARAM(rpmb_rw_size, RPMB_RW_SIZE, BYTE);
+UFS_GEOMETRY_DESC_PARAM(dyn_capacity_resource_policy, DYN_CAP_RSRC_PLC, BYTE);
+UFS_GEOMETRY_DESC_PARAM(data_ordering, DATA_ORDER, BYTE);
+UFS_GEOMETRY_DESC_PARAM(max_number_of_contexts, MAX_NUM_CTX, BYTE);
+UFS_GEOMETRY_DESC_PARAM(sys_data_tag_unit_size, TAG_UNIT_SIZE, BYTE);
+UFS_GEOMETRY_DESC_PARAM(sys_data_tag_resource_size, TAG_RSRC_SIZE, BYTE);
+UFS_GEOMETRY_DESC_PARAM(secure_removal_types, SEC_RM_TYPES, BYTE);
+UFS_GEOMETRY_DESC_PARAM(memory_types, MEM_TYPES, WORD);
+UFS_GEOMETRY_DESC_PARAM(sys_code_memory_max_alloc_units,
+ SCM_MAX_NUM_UNITS, DWORD);
+UFS_GEOMETRY_DESC_PARAM(sys_code_memory_capacity_adjustment_factor,
+ SCM_CAP_ADJ_FCTR, WORD);
+UFS_GEOMETRY_DESC_PARAM(non_persist_memory_max_alloc_units,
+ NPM_MAX_NUM_UNITS, DWORD);
+UFS_GEOMETRY_DESC_PARAM(non_persist_memory_capacity_adjustment_factor,
+ NPM_CAP_ADJ_FCTR, WORD);
+UFS_GEOMETRY_DESC_PARAM(enh1_memory_max_alloc_units,
+ ENM1_MAX_NUM_UNITS, DWORD);
+UFS_GEOMETRY_DESC_PARAM(enh1_memory_capacity_adjustment_factor,
+ ENM1_CAP_ADJ_FCTR, WORD);
+UFS_GEOMETRY_DESC_PARAM(enh2_memory_max_alloc_units,
+ ENM2_MAX_NUM_UNITS, DWORD);
+UFS_GEOMETRY_DESC_PARAM(enh2_memory_capacity_adjustment_factor,
+ ENM2_CAP_ADJ_FCTR, WORD);
+UFS_GEOMETRY_DESC_PARAM(enh3_memory_max_alloc_units,
+ ENM3_MAX_NUM_UNITS, DWORD);
+UFS_GEOMETRY_DESC_PARAM(enh3_memory_capacity_adjustment_factor,
+ ENM3_CAP_ADJ_FCTR, WORD);
+UFS_GEOMETRY_DESC_PARAM(enh4_memory_max_alloc_units,
+ ENM4_MAX_NUM_UNITS, DWORD);
+UFS_GEOMETRY_DESC_PARAM(enh4_memory_capacity_adjustment_factor,
+ ENM4_CAP_ADJ_FCTR, WORD);
+
+static struct attribute *ufs_sysfs_geometry_descriptor[] = {
+ &dev_attr_raw_device_capacity.attr,
+ &dev_attr_max_number_of_luns.attr,
+ &dev_attr_segment_size.attr,
+ &dev_attr_allocation_unit_size.attr,
+ &dev_attr_min_addressable_block_size.attr,
+ &dev_attr_optimal_read_block_size.attr,
+ &dev_attr_optimal_write_block_size.attr,
+ &dev_attr_max_in_buffer_size.attr,
+ &dev_attr_max_out_buffer_size.attr,
+ &dev_attr_rpmb_rw_size.attr,
+ &dev_attr_dyn_capacity_resource_policy.attr,
+ &dev_attr_data_ordering.attr,
+ &dev_attr_max_number_of_contexts.attr,
+ &dev_attr_sys_data_tag_unit_size.attr,
+ &dev_attr_sys_data_tag_resource_size.attr,
+ &dev_attr_secure_removal_types.attr,
+ &dev_attr_memory_types.attr,
+ &dev_attr_sys_code_memory_max_alloc_units.attr,
+ &dev_attr_sys_code_memory_capacity_adjustment_factor.attr,
+ &dev_attr_non_persist_memory_max_alloc_units.attr,
+ &dev_attr_non_persist_memory_capacity_adjustment_factor.attr,
+ &dev_attr_enh1_memory_max_alloc_units.attr,
+ &dev_attr_enh1_memory_capacity_adjustment_factor.attr,
+ &dev_attr_enh2_memory_max_alloc_units.attr,
+ &dev_attr_enh2_memory_capacity_adjustment_factor.attr,
+ &dev_attr_enh3_memory_max_alloc_units.attr,
+ &dev_attr_enh3_memory_capacity_adjustment_factor.attr,
+ &dev_attr_enh4_memory_max_alloc_units.attr,
+ &dev_attr_enh4_memory_capacity_adjustment_factor.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_geometry_descriptor_group = {
+ .name = "geometry_descriptor",
+ .attrs = ufs_sysfs_geometry_descriptor,
+};
+
static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_device_descriptor_group,
&ufs_sysfs_interconnect_descriptor_group,
+ &ufs_sysfs_geometry_descriptor_group,
NULL,
};

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 773c049..04d41c8 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -238,6 +238,42 @@ enum interconnect_desc_param {
INTERCONNECT_DESC_PARAM_MPHY_VER = 0x4,
};

+/* Geometry descriptor parameters offsets in bytes*/
+enum geometry_desc_param {
+ GEOMETRY_DESC_PARAM_LEN = 0x0,
+ GEOMETRY_DESC_PARAM_TYPE = 0x1,
+ GEOMETRY_DESC_PARAM_DEV_CAP = 0x4,
+ GEOMETRY_DESC_PARAM_MAX_NUM_LUN = 0xC,
+ GEOMETRY_DESC_PARAM_SEG_SIZE = 0xD,
+ GEOMETRY_DESC_PARAM_ALLOC_UNIT_SIZE = 0x11,
+ GEOMETRY_DESC_PARAM_MIN_BLK_SIZE = 0x12,
+ GEOMETRY_DESC_PARAM_OPT_RD_BLK_SIZE = 0x13,
+ GEOMETRY_DESC_PARAM_OPT_WR_BLK_SIZE = 0x14,
+ GEOMETRY_DESC_PARAM_MAX_IN_BUF_SIZE = 0x15,
+ GEOMETRY_DESC_PARAM_MAX_OUT_BUF_SIZE = 0x16,
+ GEOMETRY_DESC_PARAM_RPMB_RW_SIZE = 0x17,
+ GEOMETRY_DESC_PARAM_DYN_CAP_RSRC_PLC = 0x18,
+ GEOMETRY_DESC_PARAM_DATA_ORDER = 0x19,
+ GEOMETRY_DESC_PARAM_MAX_NUM_CTX = 0x1A,
+ GEOMETRY_DESC_PARAM_TAG_UNIT_SIZE = 0x1B,
+ GEOMETRY_DESC_PARAM_TAG_RSRC_SIZE = 0x1C,
+ GEOMETRY_DESC_PARAM_SEC_RM_TYPES = 0x1D,
+ GEOMETRY_DESC_PARAM_MEM_TYPES = 0x1E,
+ GEOMETRY_DESC_PARAM_SCM_MAX_NUM_UNITS = 0x20,
+ GEOMETRY_DESC_PARAM_SCM_CAP_ADJ_FCTR = 0x24,
+ GEOMETRY_DESC_PARAM_NPM_MAX_NUM_UNITS = 0x26,
+ GEOMETRY_DESC_PARAM_NPM_CAP_ADJ_FCTR = 0x2A,
+ GEOMETRY_DESC_PARAM_ENM1_MAX_NUM_UNITS = 0x2C,
+ GEOMETRY_DESC_PARAM_ENM1_CAP_ADJ_FCTR = 0x30,
+ GEOMETRY_DESC_PARAM_ENM2_MAX_NUM_UNITS = 0x32,
+ GEOMETRY_DESC_PARAM_ENM2_CAP_ADJ_FCTR = 0x36,
+ GEOMETRY_DESC_PARAM_ENM3_MAX_NUM_UNITS = 0x38,
+ GEOMETRY_DESC_PARAM_ENM3_CAP_ADJ_FCTR = 0x3C,
+ GEOMETRY_DESC_PARAM_ENM4_MAX_NUM_UNITS = 0x3E,
+ GEOMETRY_DESC_PARAM_ENM4_CAP_ADJ_FCTR = 0x42,
+ GEOMETRY_DESC_PARAM_OPT_LOG_BLK_SIZE = 0x44,
+};
+
/*
* Logical Unit Write Protect
* 00h: LU not write protected
--
2.7.4

2017-12-28 13:31:58

by Stanislav Nijnikov

[permalink] [raw]
Subject: [PATCH v3 1/9] ufs: sysfs: device descriptor

This patch introduces a sysfs group entry for the UFS device descriptor
parameters. The group adds "device_descriptor" folder under the UFS driver
sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown
as hexadecimal numbers. The full information about the parameters could be
found at UFS specifications 2.1.

Signed-off-by: Stanislav Nijnikov <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 223 +++++++++++++++++++++++++++++
drivers/scsi/ufs/Makefile | 3 +-
drivers/scsi/ufs/ufs-sysfs.c | 170 ++++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.h | 25 ++++
drivers/scsi/ufs/ufs.h | 8 ++
drivers/scsi/ufs/ufshcd.c | 12 +-
drivers/scsi/ufs/ufshcd.h | 4 +
7 files changed, 439 insertions(+), 6 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-driver-ufs
create mode 100644 drivers/scsi/ufs/ufs-sysfs.c
create mode 100644 drivers/scsi/ufs/ufs-sysfs.h

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
new file mode 100644
index 0000000..17cc4aa
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -0,0 +1,223 @@
+What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_type
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the device type. This is one of the UFS
+ device descriptor parameters. 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/*/device_descriptor/device_class
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the device class. This is one of the UFS
+ device descriptor parameters. 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/*/device_descriptor/device_sub_class
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the UFS storage subclass. This is one of
+ the UFS device descriptor parameters. 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/*/device_descriptor/protocol
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the protocol supported by an UFS device.
+ This is one of the UFS device descriptor parameters.
+ 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/*/device_descriptor/number_of_luns
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows number of logical units. This is one of
+ the UFS device descriptor parameters. 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/*/device_descriptor/number_of_wluns
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows number of well known logical units.
+ This is one of the UFS device descriptor parameters.
+ 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/*/device_descriptor/boot_enable
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows value that indicates whether the device is
+ enabled for boot. This is one of the UFS device descriptor
+ parameters. 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/*/device_descriptor/descriptor_access_enable
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows value that indicates whether the device
+ descriptor could be read after partial initialization phase
+ of the boot sequence. This is one of the UFS device descriptor
+ parameters. 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/*/device_descriptor/initial_power_mode
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows value that defines the power mode after
+ device initialization or hardware reset. This is one of
+ the UFS device descriptor parameters. 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/*/device_descriptor/high_priority_lun
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the high priority lun. This is one of
+ the UFS device descriptor parameters. 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/*/device_descriptor/secure_removal_type
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the secure removal type. This is one of
+ the UFS device descriptor parameters. 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/*/device_descriptor/support_security_lun
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows whether the security lun is supported.
+ This is one of the UFS device descriptor parameters.
+ 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/*/device_descriptor/bkops_termination_latency
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the background operations termination
+ latency. This is one of the UFS device descriptor parameters.
+ 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/*/device_descriptor/initial_active_icc_level
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the initial active ICC level. This is one
+ of the UFS device descriptor parameters. 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/*/device_descriptor/specification_version
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the specification version. This is one
+ of the UFS device descriptor parameters. 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/*/device_descriptor/manufacturing_date
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the manufacturing date in BCD format.
+ This is one of the UFS device descriptor parameters.
+ 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/*/device_descriptor/manufacturer_id
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the manufacturee ID. This is one of the
+ UFS device descriptor parameters. 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/*/device_descriptor/rtt_capability
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the maximum number of outstanding RTTs
+ supported by the device. This is one of the UFS device
+ descriptor parameters. 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/*/device_descriptor/rtc_update
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the frequency and method of the realtime
+ clock update. This is one of the UFS device descriptor
+ parameters. 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/*/device_descriptor/ufs_features
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows which features are supported by the device.
+ This is one of the UFS device descriptor parameters.
+ 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/*/device_descriptor/ffu_timeout
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the FFU timeout. This is one of the
+ UFS device descriptor parameters. 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/*/device_descriptor/queue_depth
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the device queue depth. This is one of the
+ UFS device descriptor parameters. 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/*/device_descriptor/device_version
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the device version. This is one of the
+ UFS device descriptor parameters. 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/*/device_descriptor/number_of_secure_wpa
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows number of secure write protect areas
+ supported by the device. This is one of the UFS device
+ descriptor parameters. 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/*/device_descriptor/psa_max_data_size
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the maximum amount of data that may be
+ written during the pre-soldering phase of the PSA flow.
+ This is one of the UFS device descriptor parameters.
+ 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/*/device_descriptor/psa_state_timeout
+Date: December 2017
+Contact: Stanislav Nijnikov <[email protected]>
+Description: This file shows the command maximum timeout for a change
+ in PSA state. This is one of the UFS device descriptor
+ parameters. The full information about the descriptor could
+ be found at UFS specifications 2.1.
+ The file is read only.
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 9310c6c..918f579 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,6 +3,7 @@
obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o
obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o
obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
-obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
+ufshcd-core-objs := ufshcd.o ufs-sysfs.o
obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
new file mode 100644
index 0000000..1c685f3
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -0,0 +1,170 @@
+/*
+* UFS Device Management sysfs
+*
+* Copyright (C) 2017 Western Digital Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+*/
+
+#include <linux/err.h>
+#include <linux/string.h>
+
+#include "ufs.h"
+#include "ufs-sysfs.h"
+/* collision between the device descriptor parameter and the definition */
+#undef DEVICE_CLASS
+
+enum ufs_desc_param_size {
+ UFS_PARAM_BYTE_SIZE = 1,
+ UFS_PARAM_WORD_SIZE = 2,
+ UFS_PARAM_DWORD_SIZE = 4,
+ UFS_PARAM_QWORD_SIZE = 8,
+};
+
+static inline ssize_t ufs_sysfs_read_desc_param(
+ struct ufs_hba *hba, u8 desc_idn, u8 index, char *buf, u8 off,
+ enum ufs_desc_param_size param_size)
+{
+ int desc_len;
+ int ret;
+ u8 *desc_buf;
+
+ if (ufshcd_map_desc_id_to_length(hba, desc_idn, &desc_len) ||
+ off >= desc_len)
+ return -EINVAL;
+ desc_buf = kzalloc(desc_len, GFP_ATOMIC);
+ if (!desc_buf)
+ return -ENOMEM;
+ ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
+ desc_idn, index, 0, desc_buf, &desc_len);
+ if (ret)
+ return -EINVAL;
+ switch (param_size) {
+ case UFS_PARAM_BYTE_SIZE:
+ ret = sprintf(buf, "0x%02X\n", desc_buf[off]);
+ break;
+ case UFS_PARAM_WORD_SIZE:
+ ret = sprintf(buf, "0x%04X\n",
+ be16_to_cpu(*((u16 *)(desc_buf + off))));
+ break;
+ case UFS_PARAM_DWORD_SIZE:
+ ret = sprintf(buf, "0x%08X\n",
+ be32_to_cpu(*((u32 *)(desc_buf + off))));
+ break;
+ case UFS_PARAM_QWORD_SIZE:
+ ret = sprintf(buf, "0x%016llX\n",
+ be64_to_cpu(*((u64 *)(desc_buf + off))));
+ break;
+ }
+ kfree(desc_buf);
+
+ return ret;
+}
+
+#define ufs_sysfs_desc_param_show(_name, _puname, _duname, _size) \
+static ssize_t _name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct ufs_hba *hba = dev_get_drvdata(dev); \
+ return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname, \
+ 0, buf, _duname##_DESC_PARAM_##_puname, \
+ UFS_PARAM_##_size##_SIZE); \
+}
+
+#define UFS_DESC_PARAM(_pname, _puname, _duname, _size) \
+ ufs_sysfs_desc_param_show(_pname, _puname, _duname, _size) \
+ static DEVICE_ATTR_RO(_pname)
+
+#define UFS_DEVICE_DESC_PARAM(_name, _uname, _size) \
+ UFS_DESC_PARAM(_name, _uname, DEVICE, _size)
+
+UFS_DEVICE_DESC_PARAM(device_type, DEVICE_TYPE, BYTE);
+UFS_DEVICE_DESC_PARAM(device_class, DEVICE_CLASS, BYTE);
+UFS_DEVICE_DESC_PARAM(device_sub_class, DEVICE_SUB_CLASS, BYTE);
+UFS_DEVICE_DESC_PARAM(protocol, PRTCL, BYTE);
+UFS_DEVICE_DESC_PARAM(number_of_luns, NUM_LU, BYTE);
+UFS_DEVICE_DESC_PARAM(number_of_wluns, NUM_WLU, BYTE);
+UFS_DEVICE_DESC_PARAM(boot_enable, BOOT_ENBL, BYTE);
+UFS_DEVICE_DESC_PARAM(descriptor_access_enable, DESC_ACCSS_ENBL, BYTE);
+UFS_DEVICE_DESC_PARAM(initial_power_mode, INIT_PWR_MODE, BYTE);
+UFS_DEVICE_DESC_PARAM(high_priority_lun, HIGH_PR_LUN, BYTE);
+UFS_DEVICE_DESC_PARAM(secure_removal_type, SEC_RMV_TYPE, BYTE);
+UFS_DEVICE_DESC_PARAM(support_security_lun, SEC_LU, BYTE);
+UFS_DEVICE_DESC_PARAM(bkops_termination_latency, BKOP_TERM_LT, BYTE);
+UFS_DEVICE_DESC_PARAM(initial_active_icc_level, ACTVE_ICC_LVL, BYTE);
+UFS_DEVICE_DESC_PARAM(specification_version, SPEC_VER, WORD);
+UFS_DEVICE_DESC_PARAM(manufacturing_date, MANF_DATE, WORD);
+UFS_DEVICE_DESC_PARAM(manufacturer_id, MANF_ID, WORD);
+UFS_DEVICE_DESC_PARAM(rtt_capability, RTT_CAP, BYTE);
+UFS_DEVICE_DESC_PARAM(rtc_update, FRQ_RTC, WORD);
+UFS_DEVICE_DESC_PARAM(ufs_features, UFS_FEAT, BYTE);
+UFS_DEVICE_DESC_PARAM(ffu_timeout, FFU_TMT, BYTE);
+UFS_DEVICE_DESC_PARAM(queue_depth, Q_DPTH, BYTE);
+UFS_DEVICE_DESC_PARAM(device_version, DEV_VER, WORD);
+UFS_DEVICE_DESC_PARAM(number_of_secure_wpa, NUM_SEC_WPA, BYTE);
+UFS_DEVICE_DESC_PARAM(psa_max_data_size, PSA_MAX_DATA, DWORD);
+UFS_DEVICE_DESC_PARAM(psa_state_timeout, PSA_TMT, BYTE);
+
+static struct attribute *ufs_sysfs_device_descriptor[] = {
+ &dev_attr_device_type.attr,
+ &dev_attr_device_class.attr,
+ &dev_attr_device_sub_class.attr,
+ &dev_attr_protocol.attr,
+ &dev_attr_number_of_luns.attr,
+ &dev_attr_number_of_wluns.attr,
+ &dev_attr_boot_enable.attr,
+ &dev_attr_descriptor_access_enable.attr,
+ &dev_attr_initial_power_mode.attr,
+ &dev_attr_high_priority_lun.attr,
+ &dev_attr_secure_removal_type.attr,
+ &dev_attr_support_security_lun.attr,
+ &dev_attr_bkops_termination_latency.attr,
+ &dev_attr_initial_active_icc_level.attr,
+ &dev_attr_specification_version.attr,
+ &dev_attr_manufacturing_date.attr,
+ &dev_attr_manufacturer_id.attr,
+ &dev_attr_rtt_capability.attr,
+ &dev_attr_rtc_update.attr,
+ &dev_attr_ufs_features.attr,
+ &dev_attr_ffu_timeout.attr,
+ &dev_attr_queue_depth.attr,
+ &dev_attr_device_version.attr,
+ &dev_attr_number_of_secure_wpa.attr,
+ &dev_attr_psa_max_data_size.attr,
+ &dev_attr_psa_state_timeout.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_device_descriptor_group = {
+ .name = "device_descriptor",
+ .attrs = ufs_sysfs_device_descriptor,
+};
+
+static const struct attribute_group *ufs_sysfs_groups[] = {
+ &ufs_sysfs_device_descriptor_group,
+ NULL,
+};
+
+void ufs_sysfs_add_device_management(struct ufs_hba *hba)
+{
+ int ret;
+
+ ret = sysfs_create_groups(&hba->dev->kobj, ufs_sysfs_groups);
+ if (ret)
+ dev_err(hba->dev,
+ "%s: sysfs groups creation failed (err = %d)\n",
+ __func__, ret);
+}
+
+void ufs_sysfs_remove_device_management(struct ufs_hba *hba)
+{
+ sysfs_remove_groups(&hba->dev->kobj, ufs_sysfs_groups);
+}
diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
new file mode 100644
index 0000000..a1fc9dc
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-sysfs.h
@@ -0,0 +1,25 @@
+/*
+* UFS Device Management sysfs
+*
+* Copyright (C) 2017 Western Digital Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License version
+* 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+*/
+#ifndef __UFS_SYSFS_H__
+#define __UFS_SYSFS_H__
+
+#include <linux/sysfs.h>
+
+#include "ufshcd.h"
+
+void ufs_sysfs_add_device_management(struct ufs_hba *hba);
+void ufs_sysfs_remove_device_management(struct ufs_hba *hba);
+#endif
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 54deeb7..6ae1e08 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -220,6 +220,14 @@ enum device_desc_param {
DEVICE_DESC_PARAM_UD_LEN = 0x1B,
DEVICE_DESC_PARAM_RTT_CAP = 0x1C,
DEVICE_DESC_PARAM_FRQ_RTC = 0x1D,
+ DEVICE_DESC_PARAM_UFS_FEAT = 0x1F,
+ DEVICE_DESC_PARAM_FFU_TMT = 0x20,
+ DEVICE_DESC_PARAM_Q_DPTH = 0x21,
+ DEVICE_DESC_PARAM_DEV_VER = 0x22,
+ DEVICE_DESC_PARAM_NUM_SEC_WPA = 0x24,
+ DEVICE_DESC_PARAM_PSA_MAX_DATA = 0x25,
+ DEVICE_DESC_PARAM_PSA_TMT = 0x29,
+ DEVICE_DESC_PARAM_PRDCT_REV = 0x2A,
};

/*
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a355d98..97dcb52 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -44,6 +44,7 @@
#include "ufshcd.h"
#include "ufs_quirks.h"
#include "unipro.h"
+#include "ufs-sysfs.h"

#define CREATE_TRACE_POINTS
#include <trace/events/ufs.h>
@@ -2894,11 +2895,10 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
* 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;
@@ -7704,10 +7704,12 @@ static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba)
{
ufshcd_add_rpm_lvl_sysfs_nodes(hba);
ufshcd_add_spm_lvl_sysfs_nodes(hba);
+ ufs_sysfs_add_device_management(hba);
}

static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba)
{
+ ufs_sysfs_remove_device_management(hba);
device_remove_file(hba->dev, &hba->rpm_lvl_attr);
device_remove_file(hba->dev, &hba->spm_lvl_attr);
}
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 1332e54..6a0ec4b 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -841,6 +841,10 @@ 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_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
enum flag_idn idn, bool *flag_res);
int ufshcd_hold(struct ufs_hba *hba, bool async);
--
2.7.4

2017-12-28 19:37:22

by Jaegeuk Kim

[permalink] [raw]
Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor

On 12/28, Stanislav Nijnikov wrote:
> This patch introduces a sysfs group entry for the UFS device descriptor
> parameters. The group adds "device_descriptor" folder under the UFS driver
> sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown
> as hexadecimal numbers. The full information about the parameters could be
> found at UFS specifications 2.1.
>
> Signed-off-by: Stanislav Nijnikov <[email protected]>
> ---
> Documentation/ABI/testing/sysfs-driver-ufs | 223 +++++++++++++++++++++++++++++
> drivers/scsi/ufs/Makefile | 3 +-
> drivers/scsi/ufs/ufs-sysfs.c | 170 ++++++++++++++++++++++
> drivers/scsi/ufs/ufs-sysfs.h | 25 ++++
> drivers/scsi/ufs/ufs.h | 8 ++
> drivers/scsi/ufs/ufshcd.c | 12 +-
> drivers/scsi/ufs/ufshcd.h | 4 +
> 7 files changed, 439 insertions(+), 6 deletions(-)
> create mode 100644 Documentation/ABI/testing/sysfs-driver-ufs
> create mode 100644 drivers/scsi/ufs/ufs-sysfs.c
> create mode 100644 drivers/scsi/ufs/ufs-sysfs.h
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
> new file mode 100644
> index 0000000..17cc4aa
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs

[snip]

> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> index 9310c6c..918f579 100644
> --- a/drivers/scsi/ufs/Makefile
> +++ b/drivers/scsi/ufs/Makefile
> @@ -3,6 +3,7 @@
> obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o
> obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o
> obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
> -obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
> +obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
> +ufshcd-core-objs := ufshcd.o ufs-sysfs.o

Why not just adding ufs-sysfs.o in the existing configuration?

> obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> new file mode 100644
> index 0000000..1c685f3
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -0,0 +1,170 @@
> +/*
> +* UFS Device Management sysfs
> +*
> +* Copyright (C) 2017 Western Digital Corporation
> +*
> +* This program is free software; you can redistribute it and/or
> +* modify it under the terms of the GNU General Public License version
> +* 2 as published by the Free Software Foundation.
> +*
> +* This program is distributed in the hope that it will be useful, but
> +* WITHOUT ANY WARRANTY; without even the implied warranty of
> +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +* General Public License for more details.
> +*
> +*/
> +
> +#include <linux/err.h>
> +#include <linux/string.h>
> +
> +#include "ufs.h"
> +#include "ufs-sysfs.h"
> +/* collision between the device descriptor parameter and the definition */
> +#undef DEVICE_CLASS

Does this make sense? How about attaching "_" for all the macro like
_DEVICE_CLASS below?

> +
> +enum ufs_desc_param_size {
> + UFS_PARAM_BYTE_SIZE = 1,
> + UFS_PARAM_WORD_SIZE = 2,
> + UFS_PARAM_DWORD_SIZE = 4,
> + UFS_PARAM_QWORD_SIZE = 8,
> +};
> +
> +static inline ssize_t ufs_sysfs_read_desc_param(
> + struct ufs_hba *hba, u8 desc_idn, u8 index, char *buf, u8 off,
> + enum ufs_desc_param_size param_size)
> +{
> + int desc_len;
> + int ret;
> + u8 *desc_buf;
> +
> + if (ufshcd_map_desc_id_to_length(hba, desc_idn, &desc_len) ||
> + off >= desc_len)
> + return -EINVAL;
> + desc_buf = kzalloc(desc_len, GFP_ATOMIC);
> + if (!desc_buf)
> + return -ENOMEM;
> + ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
> + desc_idn, index, 0, desc_buf, &desc_len);
> + if (ret)

Should free desc_buf here.

> + return -EINVAL;
> + switch (param_size) {
> + case UFS_PARAM_BYTE_SIZE:
> + ret = sprintf(buf, "0x%02X\n", desc_buf[off]);
> + break;
> + case UFS_PARAM_WORD_SIZE:
> + ret = sprintf(buf, "0x%04X\n",
> + be16_to_cpu(*((u16 *)(desc_buf + off))));
> + break;
> + case UFS_PARAM_DWORD_SIZE:
> + ret = sprintf(buf, "0x%08X\n",
> + be32_to_cpu(*((u32 *)(desc_buf + off))));
> + break;
> + case UFS_PARAM_QWORD_SIZE:
> + ret = sprintf(buf, "0x%016llX\n",
> + be64_to_cpu(*((u64 *)(desc_buf + off))));
> + break;
> + }
> + kfree(desc_buf);
> +
> + return ret;
> +}
> +
> +#define ufs_sysfs_desc_param_show(_name, _puname, _duname, _size) \
> +static ssize_t _name##_show(struct device *dev, \
> + struct device_attribute *attr, char *buf) \
> +{ \
> + struct ufs_hba *hba = dev_get_drvdata(dev); \
> + return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname, \
> + 0, buf, _duname##_DESC_PARAM_##_puname, \
> + UFS_PARAM_##_size##_SIZE); \
> +}
> +
> +#define UFS_DESC_PARAM(_pname, _puname, _duname, _size) \
> + ufs_sysfs_desc_param_show(_pname, _puname, _duname, _size) \
> + static DEVICE_ATTR_RO(_pname)
> +
> +#define UFS_DEVICE_DESC_PARAM(_name, _uname, _size) \
> + UFS_DESC_PARAM(_name, _uname, DEVICE, _size)
> +
> +UFS_DEVICE_DESC_PARAM(device_type, DEVICE_TYPE, BYTE);
> +UFS_DEVICE_DESC_PARAM(device_class, DEVICE_CLASS, BYTE);
> +UFS_DEVICE_DESC_PARAM(device_sub_class, DEVICE_SUB_CLASS, BYTE);
> +UFS_DEVICE_DESC_PARAM(protocol, PRTCL, BYTE);
> +UFS_DEVICE_DESC_PARAM(number_of_luns, NUM_LU, BYTE);
> +UFS_DEVICE_DESC_PARAM(number_of_wluns, NUM_WLU, BYTE);
> +UFS_DEVICE_DESC_PARAM(boot_enable, BOOT_ENBL, BYTE);
> +UFS_DEVICE_DESC_PARAM(descriptor_access_enable, DESC_ACCSS_ENBL, BYTE);
> +UFS_DEVICE_DESC_PARAM(initial_power_mode, INIT_PWR_MODE, BYTE);
> +UFS_DEVICE_DESC_PARAM(high_priority_lun, HIGH_PR_LUN, BYTE);
> +UFS_DEVICE_DESC_PARAM(secure_removal_type, SEC_RMV_TYPE, BYTE);
> +UFS_DEVICE_DESC_PARAM(support_security_lun, SEC_LU, BYTE);
> +UFS_DEVICE_DESC_PARAM(bkops_termination_latency, BKOP_TERM_LT, BYTE);
> +UFS_DEVICE_DESC_PARAM(initial_active_icc_level, ACTVE_ICC_LVL, BYTE);
> +UFS_DEVICE_DESC_PARAM(specification_version, SPEC_VER, WORD);
> +UFS_DEVICE_DESC_PARAM(manufacturing_date, MANF_DATE, WORD);
> +UFS_DEVICE_DESC_PARAM(manufacturer_id, MANF_ID, WORD);
> +UFS_DEVICE_DESC_PARAM(rtt_capability, RTT_CAP, BYTE);
> +UFS_DEVICE_DESC_PARAM(rtc_update, FRQ_RTC, WORD);
> +UFS_DEVICE_DESC_PARAM(ufs_features, UFS_FEAT, BYTE);
> +UFS_DEVICE_DESC_PARAM(ffu_timeout, FFU_TMT, BYTE);
> +UFS_DEVICE_DESC_PARAM(queue_depth, Q_DPTH, BYTE);
> +UFS_DEVICE_DESC_PARAM(device_version, DEV_VER, WORD);
> +UFS_DEVICE_DESC_PARAM(number_of_secure_wpa, NUM_SEC_WPA, BYTE);
> +UFS_DEVICE_DESC_PARAM(psa_max_data_size, PSA_MAX_DATA, DWORD);
> +UFS_DEVICE_DESC_PARAM(psa_state_timeout, PSA_TMT, BYTE);
> +
> +static struct attribute *ufs_sysfs_device_descriptor[] = {
> + &dev_attr_device_type.attr,
> + &dev_attr_device_class.attr,
> + &dev_attr_device_sub_class.attr,
> + &dev_attr_protocol.attr,
> + &dev_attr_number_of_luns.attr,
> + &dev_attr_number_of_wluns.attr,
> + &dev_attr_boot_enable.attr,
> + &dev_attr_descriptor_access_enable.attr,
> + &dev_attr_initial_power_mode.attr,
> + &dev_attr_high_priority_lun.attr,
> + &dev_attr_secure_removal_type.attr,
> + &dev_attr_support_security_lun.attr,
> + &dev_attr_bkops_termination_latency.attr,
> + &dev_attr_initial_active_icc_level.attr,
> + &dev_attr_specification_version.attr,
> + &dev_attr_manufacturing_date.attr,
> + &dev_attr_manufacturer_id.attr,
> + &dev_attr_rtt_capability.attr,
> + &dev_attr_rtc_update.attr,
> + &dev_attr_ufs_features.attr,
> + &dev_attr_ffu_timeout.attr,
> + &dev_attr_queue_depth.attr,
> + &dev_attr_device_version.attr,
> + &dev_attr_number_of_secure_wpa.attr,
> + &dev_attr_psa_max_data_size.attr,
> + &dev_attr_psa_state_timeout.attr,
> + NULL,
> +};
> +
> +static const struct attribute_group ufs_sysfs_device_descriptor_group = {
> + .name = "device_descriptor",
> + .attrs = ufs_sysfs_device_descriptor,
> +};
> +
> +static const struct attribute_group *ufs_sysfs_groups[] = {
> + &ufs_sysfs_device_descriptor_group,
> + NULL,
> +};
> +
> +void ufs_sysfs_add_device_management(struct ufs_hba *hba)
> +{
> + int ret;
> +
> + ret = sysfs_create_groups(&hba->dev->kobj, ufs_sysfs_groups);
> + if (ret)
> + dev_err(hba->dev,
> + "%s: sysfs groups creation failed (err = %d)\n",
> + __func__, ret);
> +}
> +
> +void ufs_sysfs_remove_device_management(struct ufs_hba *hba)
> +{
> + sysfs_remove_groups(&hba->dev->kobj, ufs_sysfs_groups);
> +}
> diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
> new file mode 100644
> index 0000000..a1fc9dc
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufs-sysfs.h
> @@ -0,0 +1,25 @@
> +/*
> +* UFS Device Management sysfs
> +*
> +* Copyright (C) 2017 Western Digital Corporation
> +*
> +* This program is free software; you can redistribute it and/or
> +* modify it under the terms of the GNU General Public License version
> +* 2 as published by the Free Software Foundation.
> +*
> +* This program is distributed in the hope that it will be useful, but
> +* WITHOUT ANY WARRANTY; without even the implied warranty of
> +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +* General Public License for more details.
> +*
> +*/
> +#ifndef __UFS_SYSFS_H__
> +#define __UFS_SYSFS_H__
> +
> +#include <linux/sysfs.h>
> +
> +#include "ufshcd.h"
> +
> +void ufs_sysfs_add_device_management(struct ufs_hba *hba);
> +void ufs_sysfs_remove_device_management(struct ufs_hba *hba);
> +#endif
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index 54deeb7..6ae1e08 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -220,6 +220,14 @@ enum device_desc_param {
> DEVICE_DESC_PARAM_UD_LEN = 0x1B,
> DEVICE_DESC_PARAM_RTT_CAP = 0x1C,
> DEVICE_DESC_PARAM_FRQ_RTC = 0x1D,
> + DEVICE_DESC_PARAM_UFS_FEAT = 0x1F,
> + DEVICE_DESC_PARAM_FFU_TMT = 0x20,
> + DEVICE_DESC_PARAM_Q_DPTH = 0x21,
> + DEVICE_DESC_PARAM_DEV_VER = 0x22,
> + DEVICE_DESC_PARAM_NUM_SEC_WPA = 0x24,
> + DEVICE_DESC_PARAM_PSA_MAX_DATA = 0x25,
> + DEVICE_DESC_PARAM_PSA_TMT = 0x29,
> + DEVICE_DESC_PARAM_PRDCT_REV = 0x2A,
> };
>
> /*
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index a355d98..97dcb52 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -44,6 +44,7 @@
> #include "ufshcd.h"
> #include "ufs_quirks.h"
> #include "unipro.h"
> +#include "ufs-sysfs.h"
>
> #define CREATE_TRACE_POINTS
> #include <trace/events/ufs.h>
> @@ -2894,11 +2895,10 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
> * 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;
> @@ -7704,10 +7704,12 @@ static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba)
> {
> ufshcd_add_rpm_lvl_sysfs_nodes(hba);
> ufshcd_add_spm_lvl_sysfs_nodes(hba);
> + ufs_sysfs_add_device_management(hba);

IMO, ufs-sysfs.c must have the existing entries above, rpm/spm, as a default
group first, and then would be better to add device_descriptor_group on top of
it.

Thanks,

> }
>
> static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba)
> {
> + ufs_sysfs_remove_device_management(hba);
> device_remove_file(hba->dev, &hba->rpm_lvl_attr);
> device_remove_file(hba->dev, &hba->spm_lvl_attr);
> }
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 1332e54..6a0ec4b 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -841,6 +841,10 @@ 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_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
> enum flag_idn idn, bool *flag_res);
> int ufshcd_hold(struct ufs_hba *hba, bool async);
> --
> 2.7.4

2017-12-28 19:44:19

by Jaegeuk Kim

[permalink] [raw]
Subject: Re: [PATCH v3 4/9] ufs: sysfs: health descriptor

On 12/28, Stanislav Nijnikov wrote:
> This patch introduces a sysfs group entry for the UFS health descriptor
> parameters. The group adds "health_descriptor" folder under the UFS driver
> sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown
> as hexadecimal numbers. The full information about the parameters could be
> found at UFS specifications 2.1.
>
> Signed-off-by: Stanislav Nijnikov <[email protected]>

It needs to remove the above SOB.

>
> Reviewed-by: Greg Kroah-Hartman <[email protected]>

Reviewed-by: Jaegeuk Kim <[email protected]>

> Signed-off-by: Stanislav Nijnikov <[email protected]>
> ---
> Documentation/ABI/testing/sysfs-driver-ufs | 28 ++++++++++++++++++++++++++++
> drivers/scsi/ufs/ufs-sysfs.c | 20 ++++++++++++++++++++
> drivers/scsi/ufs/ufs.h | 11 +++++++++++
> drivers/scsi/ufs/ufshcd.c | 8 ++++++++
> drivers/scsi/ufs/ufshcd.h | 1 +
> 5 files changed, 68 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
> index 55134d3..6ba0f4d 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -413,3 +413,31 @@ Description: This file shows the memory capacity adjustment factor for
> descriptor parameters. 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/*/health_descriptor/eol_info
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file shows preend of life information. This is one
> + of the UFS health descriptor parameters. 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/*/health_descriptor/life_time_estimation_a
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file shows indication of the device life time
> + (method a). This is one of the UFS health descriptor
> + parameters. 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/*/health_descriptor/life_time_estimation_b
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file shows indication of the device life time
> + (method b). This is one of the UFS health descriptor
> + parameters. The full information about the descriptor
> + could be found at UFS specifications 2.1.
> + The file is read only.
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> index e439e92..ce6d27e 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -248,10 +248,30 @@ static const struct attribute_group ufs_sysfs_geometry_descriptor_group = {
> .attrs = ufs_sysfs_geometry_descriptor,
> };
>
> +#define UFS_HEALTH_DESC_PARAM(_name, _uname, _size) \
> + UFS_DESC_PARAM(_name, _uname, HEALTH, _size)
> +
> +UFS_HEALTH_DESC_PARAM(eol_info, EOL_INFO, BYTE);
> +UFS_HEALTH_DESC_PARAM(life_time_estimation_a, LIFE_TIME_EST_A, BYTE);
> +UFS_HEALTH_DESC_PARAM(life_time_estimation_b, LIFE_TIME_EST_B, BYTE);
> +
> +static struct attribute *ufs_sysfs_health_descriptor[] = {
> + &dev_attr_eol_info.attr,
> + &dev_attr_life_time_estimation_a.attr,
> + &dev_attr_life_time_estimation_b.attr,
> + NULL,
> +};
> +
> +static const struct attribute_group ufs_sysfs_health_descriptor_group = {
> + .name = "health_descriptor",
> + .attrs = ufs_sysfs_health_descriptor,
> +};
> +
> static const struct attribute_group *ufs_sysfs_groups[] = {
> &ufs_sysfs_device_descriptor_group,
> &ufs_sysfs_interconnect_descriptor_group,
> &ufs_sysfs_geometry_descriptor_group,
> + &ufs_sysfs_health_descriptor_group,
> NULL,
> };
>
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index 04d41c8..6bfeedb 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -154,6 +154,7 @@ enum desc_idn {
> QUERY_DESC_IDN_RFU_1 = 0x6,
> QUERY_DESC_IDN_GEOMETRY = 0x7,
> QUERY_DESC_IDN_POWER = 0x8,
> + QUERY_DESC_IDN_HEALTH = 0x9,
> QUERY_DESC_IDN_MAX,
> };
>
> @@ -169,6 +170,7 @@ enum ufs_desc_def_size {
> QUERY_DESC_INTERCONNECT_DEF_SIZE = 0x06,
> QUERY_DESC_GEOMETRY_DEF_SIZE = 0x44,
> QUERY_DESC_POWER_DEF_SIZE = 0x62,
> + QUERY_DESC_HEALTH_DEF_SIZE = 0x25,
> };
>
> /* Unit descriptor parameters offsets in bytes*/
> @@ -274,6 +276,15 @@ enum geometry_desc_param {
> GEOMETRY_DESC_PARAM_OPT_LOG_BLK_SIZE = 0x44,
> };
>
> +/* Health descriptor parameters offsets in bytes*/
> +enum health_desc_param {
> + HEALTH_DESC_PARAM_LEN = 0x0,
> + HEALTH_DESC_PARAM_TYPE = 0x1,
> + HEALTH_DESC_PARAM_EOL_INFO = 0x2,
> + HEALTH_DESC_PARAM_LIFE_TIME_EST_A = 0x3,
> + HEALTH_DESC_PARAM_LIFE_TIME_EST_B = 0x4,
> +};
> +
> /*
> * Logical Unit Write Protect
> * 00h: LU not write protected
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 97dcb52..6ed31ca 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -2987,6 +2987,9 @@ int ufshcd_map_desc_id_to_length(struct ufs_hba *hba,
> case QUERY_DESC_IDN_STRING:
> *desc_len = QUERY_DESC_MAX_SIZE;
> break;
> + case QUERY_DESC_IDN_HEALTH:
> + *desc_len = hba->desc_size.hlth_desc;
> + break;
> case QUERY_DESC_IDN_RFU_0:
> case QUERY_DESC_IDN_RFU_1:
> *desc_len = 0;
> @@ -6298,6 +6301,10 @@ static void ufshcd_init_desc_sizes(struct ufs_hba *hba)
> &hba->desc_size.geom_desc);
> if (err)
> hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE;
> + err = ufshcd_read_desc_length(hba, QUERY_DESC_IDN_HEALTH, 0,
> + &hba->desc_size.hlth_desc);
> + if (err)
> + hba->desc_size.hlth_desc = QUERY_DESC_HEALTH_DEF_SIZE;
> }
>
> static void ufshcd_def_desc_sizes(struct ufs_hba *hba)
> @@ -6308,6 +6315,7 @@ static void ufshcd_def_desc_sizes(struct ufs_hba *hba)
> hba->desc_size.conf_desc = QUERY_DESC_CONFIGURATION_DEF_SIZE;
> hba->desc_size.unit_desc = QUERY_DESC_UNIT_DEF_SIZE;
> hba->desc_size.geom_desc = QUERY_DESC_GEOMETRY_DEF_SIZE;
> + hba->desc_size.hlth_desc = QUERY_DESC_HEALTH_DEF_SIZE;
> }
>
> /**
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 6a0ec4b..2235e7d 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -229,6 +229,7 @@ struct ufs_desc_size {
> int interc_desc;
> int unit_desc;
> int conf_desc;
> + int hlth_desc;
> };
>
> /**
> --
> 2.7.4

2017-12-28 19:52:26

by Jaegeuk Kim

[permalink] [raw]
Subject: Re: [PATCH v3 9/9] ufs: sysfs: attributes

On 12/28, Stanislav Nijnikov wrote:
> This patch introduces a sysfs group entry for the UFS attributes. The
> group adds "attributes" folder under the UFS driver sysfs entry
> (/sys/bus/platform/drivers/ufshcd/*). The attributes are shown
> as hexadecimal numbers. The full information about the attributes could
> be found at UFS specifications 2.1.
>
> Signed-off-by: Stanislav Nijnikov <[email protected]>
> ---
> Documentation/ABI/testing/sysfs-driver-ufs | 155 +++++++++++++++++++++++++++--
> drivers/scsi/ufs/ufs-sysfs.c | 89 +++++++++++++++++
> drivers/scsi/ufs/ufs-sysfs.h | 1 +
> drivers/scsi/ufs/ufs.h | 27 ++++-
> drivers/scsi/ufs/ufshcd.c | 5 +-
> drivers/scsi/ufs/ufshcd.h | 2 +
> 6 files changed, 265 insertions(+), 14 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
> index 90f8574..f2c3679 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -601,14 +601,14 @@ Description: This file shows the granularity of the LUN. This is one of
>
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/device_init
> -Date: August 2017
> +Date: December 2017

Must be fixed in the original patch.

Thanks,

> Contact: Stanislav Nijnikov <[email protected]>
> Description: This file shows the device init status. The full information
> about the flag could be found at UFS specifications 2.1.
> The file is read only.
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/permanent_wpe
> -Date: August 2017
> +Date: December 2017
> Contact: Stanislav Nijnikov <[email protected]>
> Description: This file shows whether permanent write protection is enabled.
> The full information about the flag could be found at
> @@ -616,7 +616,7 @@ Description: This file shows whether permanent write protection is enabled.
> The file is read only.
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe
> -Date: August 2017
> +Date: December 2017
> Contact: Stanislav Nijnikov <[email protected]>
> Description: This file shows whether write protection is enabled on all
> logical units configured as power on write protected. The
> @@ -625,7 +625,7 @@ Description: This file shows whether write protection is enabled on all
> The file is read only.
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable
> -Date: August 2017
> +Date: December 2017
> Contact: Stanislav Nijnikov <[email protected]>
> Description: This file shows whether the device background operations are
> enabled. The full information about the flag could be
> @@ -633,7 +633,7 @@ Description: This file shows whether the device background operations are
> The file is read only.
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/life_span_mode_enable
> -Date: August 2017
> +Date: December 2017
> Contact: Stanislav Nijnikov <[email protected]>
> Description: This file shows whether the device life span mode is enabled.
> The full information about the flag could be found at
> @@ -641,7 +641,7 @@ Description: This file shows whether the device life span mode is enabled.
> The file is read only.
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal
> -Date: August 2017
> +Date: December 2017
> Contact: Stanislav Nijnikov <[email protected]>
> Description: This file shows whether physical resource removal is enable.
> The full information about the flag could be found at
> @@ -649,7 +649,7 @@ Description: This file shows whether physical resource removal is enable.
> The file is read only.
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/busy_rtc
> -Date: August 2017
> +Date: December 2017
> Contact: Stanislav Nijnikov <[email protected]>
> Description: This file shows whether the device is executing internal
> operation related to real time clock. The full information
> @@ -657,9 +657,148 @@ Description: This file shows whether the device is executing internal
> The file is read only.
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/disable_fw_update
> -Date: August 2017
> +Date: December 2017
> Contact: Stanislav Nijnikov <[email protected]>
> Description: This file shows whether the device FW update is permanently
> disabled. The full information about the flag could be found
> at UFS specifications 2.1.
> The file is read only.
> +
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/boot_lun_enabled
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the boot lun enabled UFS device attribute.
> + The full information about the attribute could be found at
> + UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/current_power_mode
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the current power mode UFS device attribute.
> + The full information about the attribute could be found at
> + UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/active_icc_level
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the active icc level UFS device attribute.
> + The full information about the attribute could be found at
> + UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/ooo_data_enabled
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the out of order data transfer enabled UFS
> + device attribute. The full information about the attribute
> + could be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/bkops_status
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the background operations status UFS device
> + attribute. The full information about the attribute could
> + be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/purge_status
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the purge operation status UFS device
> + attribute. The full information about the attribute could
> + be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_in_size
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file shows the maximum data size in a DATA IN
> + UPIU. The full information about the attribute could
> + be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_data_out_size
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file shows the maximum number of bytes that can be
> + requested with a READY TO TRANSFER UPIU. The full information
> + about the attribute could be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/reference_clock_frequency
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the reference clock frequency UFS device
> + attribute. The full information about the attribute could
> + be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/configuration_descriptor_lock
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file shows whether the configuration descriptor is locked.
> + The full information about the attribute could be found at
> + UFS specifications 2.1. The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/max_number_of_rtt
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the maximum current number of
> + outstanding RTTs in device that is allowed. The full
> + information about the attribute could be found at
> + UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_control
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the exception event control UFS device
> + attribute. The full information about the attribute could
> + be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_status
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the exception event status UFS device
> + attribute. The full information about the attribute could
> + be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/ffu_status
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file provides the ffu status UFS device attribute.
> + The full information about the attribute could be found at
> + UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/psa_state
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file show the PSA feature status. The full information
> + about the attribute could be found at UFS specifications 2.1.
> + The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/attributes/psa_data_size
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file shows the amount of data that the host plans to
> + load to all logical units in pre-soldering state.
> + The full information about the attribute could be found at
> + UFS specifications 2.1.
> + The file is read only.
> +
> +
> +What: /sys/class/scsi_device/*/device/dyn_cap_needed
> +Date: December 2017
> +Contact: Stanislav Nijnikov <[email protected]>
> +Description: This file shows the The amount of physical memory needed
> + to be removed from the physical memory resources pool of
> + the particular logical unit. The full information about
> + the attribute could be found at UFS specifications 2.1.
> + The file is read only.
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> index 2095124..f3ec1b0 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -485,6 +485,64 @@ static const struct attribute_group ufs_sysfs_flags_group = {
> .attrs = ufs_sysfs_device_flags,
> };
>
> +#define ufs_sysfs_attribute_show_function(_name, _uname) \
> +static ssize_t _name##_show(struct device *dev, \
> + struct device_attribute *attr, char *buf) \
> +{ \
> + struct ufs_hba *hba = dev_get_drvdata(dev); \
> + u32 value; \
> + if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \
> + QUERY_ATTR_IDN_##_uname, 0, 0, &value)) \
> + return -EINVAL; \
> + return sprintf(buf, "0x%08X\n", value); \
> +}
> +
> +#define UFS_ATTRIBUTE(_name, _uname) \
> + ufs_sysfs_attribute_show_function(_name, _uname) \
> + static DEVICE_ATTR_RO(_name)
> +
> +UFS_ATTRIBUTE(boot_lun_enabled, BOOT_LU_EN);
> +UFS_ATTRIBUTE(current_power_mode, POWER_MODE);
> +UFS_ATTRIBUTE(active_icc_level, ACTIVE_ICC_LVL);
> +UFS_ATTRIBUTE(ooo_data_enabled, OOO_DATA_EN);
> +UFS_ATTRIBUTE(bkops_status, BKOPS_STATUS);
> +UFS_ATTRIBUTE(purge_status, PURGE_STATUS);
> +UFS_ATTRIBUTE(max_data_in_size, MAX_DATA_IN);
> +UFS_ATTRIBUTE(max_data_out_size, MAX_DATA_OUT);
> +UFS_ATTRIBUTE(reference_clock_frequency, REF_CLK_FREQ);
> +UFS_ATTRIBUTE(configuration_descriptor_lock, CONF_DESC_LOCK);
> +UFS_ATTRIBUTE(max_number_of_rtt, MAX_NUM_OF_RTT);
> +UFS_ATTRIBUTE(exception_event_control, EE_CONTROL);
> +UFS_ATTRIBUTE(exception_event_status, EE_STATUS);
> +UFS_ATTRIBUTE(ffu_status, FFU_STATUS);
> +UFS_ATTRIBUTE(psa_state, PSA_STATE);
> +UFS_ATTRIBUTE(psa_data_size, PSA_DATA_SIZE);
> +
> +static struct attribute *ufs_sysfs_attributes[] = {
> + &dev_attr_boot_lun_enabled.attr,
> + &dev_attr_current_power_mode.attr,
> + &dev_attr_active_icc_level.attr,
> + &dev_attr_ooo_data_enabled.attr,
> + &dev_attr_bkops_status.attr,
> + &dev_attr_purge_status.attr,
> + &dev_attr_max_data_in_size.attr,
> + &dev_attr_max_data_out_size.attr,
> + &dev_attr_reference_clock_frequency.attr,
> + &dev_attr_configuration_descriptor_lock.attr,
> + &dev_attr_max_number_of_rtt.attr,
> + &dev_attr_exception_event_control.attr,
> + &dev_attr_exception_event_status.attr,
> + &dev_attr_ffu_status.attr,
> + &dev_attr_psa_state.attr,
> + &dev_attr_psa_data_size.attr,
> + NULL,
> +};
> +
> +static const struct attribute_group ufs_sysfs_attributes_group = {
> + .name = "attributes",
> + .attrs = ufs_sysfs_attributes,
> +};
> +
> static const struct attribute_group *ufs_sysfs_groups[] = {
> &ufs_sysfs_device_descriptor_group,
> &ufs_sysfs_interconnect_descriptor_group,
> @@ -493,6 +551,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
> &ufs_sysfs_power_descriptor_group,
> &ufs_sysfs_string_descriptors_group,
> &ufs_sysfs_flags_group,
> + &ufs_sysfs_attributes_group,
> NULL,
> };
>
> @@ -553,6 +612,36 @@ struct attribute_group ufs_sysfs_unit_descriptor_group = {
> .attrs = ufs_sysfs_unit_descriptor,
> };
>
> +#define ufs_sysfs_lun_attribute_show_function(_name, _uname) \
> +static ssize_t _name##_attribute_show(struct device *dev, \
> + struct device_attribute *attr, char *buf) \
> +{ \
> + u32 value; \
> + struct scsi_device *sdev = to_scsi_device(dev); \
> + struct ufs_hba *hba = shost_priv(sdev->host); \
> + u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun); \
> + if (ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, \
> + QUERY_ATTR_IDN_##_uname, lun, 0, &value)) \
> + return -EINVAL; \
> + return sprintf(buf, "0x%08X\n", value); \
> +}
> +
> +#define UFS_LUN_ATTRIBUTE(_name, _uname) \
> + ufs_sysfs_lun_attribute_show_function(_name, _uname) \
> + static DEVICE_ATTR_RO(_name##_attribute)
> +
> +
> +UFS_LUN_ATTRIBUTE(dyn_cap_needed, DYN_CAP_NEEDED);
> +
> +static struct attribute *ufs_sysfs_lun_attributes[] = {
> + &dev_attr_dyn_cap_needed_attribute.attr,
> + NULL,
> +};
> +
> +struct attribute_group ufs_sysfs_lun_attributes_group = {
> + .attrs = ufs_sysfs_lun_attributes,
> +};
> +
> void ufs_sysfs_add_device_management(struct ufs_hba *hba)
> {
> int ret;
> diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
> index 1ec1217..cff5360 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.h
> +++ b/drivers/scsi/ufs/ufs-sysfs.h
> @@ -25,4 +25,5 @@ void ufs_sysfs_add_device_management(struct ufs_hba *hba);
> void ufs_sysfs_remove_device_management(struct ufs_hba *hba);
>
> extern struct attribute_group ufs_sysfs_unit_descriptor_group;
> +extern struct attribute_group ufs_sysfs_lun_attributes_group;
> #endif
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index df5e73e..14e5bf7 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -145,10 +145,29 @@ enum flag_idn {
>
> /* Attribute idn for Query requests */
> enum attr_idn {
> - QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
> - QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
> - QUERY_ATTR_IDN_EE_CONTROL = 0x0D,
> - QUERY_ATTR_IDN_EE_STATUS = 0x0E,
> + QUERY_ATTR_IDN_BOOT_LU_EN = 0x00,
> + QUERY_ATTR_IDN_RESERVED = 0x01,
> + QUERY_ATTR_IDN_POWER_MODE = 0x02,
> + QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
> + QUERY_ATTR_IDN_OOO_DATA_EN = 0x04,
> + QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
> + QUERY_ATTR_IDN_PURGE_STATUS = 0x06,
> + QUERY_ATTR_IDN_MAX_DATA_IN = 0x07,
> + QUERY_ATTR_IDN_MAX_DATA_OUT = 0x08,
> + QUERY_ATTR_IDN_DYN_CAP_NEEDED = 0x09,
> + QUERY_ATTR_IDN_REF_CLK_FREQ = 0x0A,
> + QUERY_ATTR_IDN_CONF_DESC_LOCK = 0x0B,
> + QUERY_ATTR_IDN_MAX_NUM_OF_RTT = 0x0C,
> + QUERY_ATTR_IDN_EE_CONTROL = 0x0D,
> + QUERY_ATTR_IDN_EE_STATUS = 0x0E,
> + QUERY_ATTR_IDN_SECONDS_PASSED = 0x0F,
> + QUERY_ATTR_IDN_CNTX_CONF = 0x10,
> + QUERY_ATTR_IDN_CORR_PRG_BLK_NUM = 0x11,
> + QUERY_ATTR_IDN_RESERVED2 = 0x12,
> + QUERY_ATTR_IDN_RESERVED3 = 0x13,
> + QUERY_ATTR_IDN_FFU_STATUS = 0x14,
> + QUERY_ATTR_IDN_PSA_STATE = 0x15,
> + QUERY_ATTR_IDN_PSA_DATA_SIZE = 0x16,
> };
>
> /* Descriptor idn for Query requests */
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 3ddab23..6dab9a6 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -2711,8 +2711,8 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
> *
> * Returns 0 for success, non-zero in case of failure
> */
> -static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
> - enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
> +int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
> + enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
> {
> struct ufs_query_req *request = NULL;
> struct ufs_query_res *response = NULL;
> @@ -6489,6 +6489,7 @@ static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd)
>
> static struct attribute_group *ufshcd_driver_groups[] = {
> &ufs_sysfs_unit_descriptor_group,
> + &ufs_sysfs_lun_attributes_group,
> NULL,
> };
>
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 209c563..5a1b21b 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -846,6 +846,8 @@ 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_attr(struct ufs_hba *hba, enum query_opcode opcode,
> + enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
> 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,
> --
> 2.7.4

2017-12-29 09:23:30

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor

On Thu, Dec 28, 2017 at 03:29:06PM +0200, Stanislav Nijnikov wrote:
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -0,0 +1,170 @@
> +/*
> +* UFS Device Management sysfs
> +*
> +* Copyright (C) 2017 Western Digital Corporation
> +*
> +* This program is free software; you can redistribute it and/or
> +* modify it under the terms of the GNU General Public License version
> +* 2 as published by the Free Software Foundation.
> +*
> +* This program is distributed in the hope that it will be useful, but
> +* WITHOUT ANY WARRANTY; without even the implied warranty of
> +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> +* General Public License for more details.

Please use the SPDX format for all of this, like I asked last time :(

thanks,

greg k-h

2018-01-02 13:54:36

by Stanislav Nijnikov

[permalink] [raw]
Subject: RE: [PATCH v3 1/9] ufs: sysfs: device descriptor



> -----Original Message-----
> From: Jaegeuk Kim [mailto:[email protected]]
> Sent: Thursday, December 28, 2017 9:37 PM
> To: Stanislav Nijnikov <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; Alex Lemberg <[email protected]>
> Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor
>
> On 12/28, Stanislav Nijnikov wrote:
> > This patch introduces a sysfs group entry for the UFS device
> > descriptor parameters. The group adds "device_descriptor" folder under
> > the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The
> > parameters are shown as hexadecimal numbers. The full information
> > about the parameters could be found at UFS specifications 2.1.
> >
> > Signed-off-by: Stanislav Nijnikov <[email protected]>
> > ---
> > Documentation/ABI/testing/sysfs-driver-ufs | 223
> +++++++++++++++++++++++++++++
> > drivers/scsi/ufs/Makefile | 3 +-
> > drivers/scsi/ufs/ufs-sysfs.c | 170 ++++++++++++++++++++++
> > drivers/scsi/ufs/ufs-sysfs.h | 25 ++++
> > drivers/scsi/ufs/ufs.h | 8 ++
> > drivers/scsi/ufs/ufshcd.c | 12 +-
> > drivers/scsi/ufs/ufshcd.h | 4 +
> > 7 files changed, 439 insertions(+), 6 deletions(-) create mode
> > 100644 Documentation/ABI/testing/sysfs-driver-ufs
> > create mode 100644 drivers/scsi/ufs/ufs-sysfs.c create mode 100644
> > drivers/scsi/ufs/ufs-sysfs.h
> >
> > diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
> > b/Documentation/ABI/testing/sysfs-driver-ufs
> > new file mode 100644
> > index 0000000..17cc4aa
> > --- /dev/null
> > +++ b/Documentation/ABI/testing/sysfs-driver-ufs
>
> [snip]
>
> > diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> > index 9310c6c..918f579 100644
> > --- a/drivers/scsi/ufs/Makefile
> > +++ b/drivers/scsi/ufs/Makefile
> > @@ -3,6 +3,7 @@
> > obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-
> dwc.o
> > tc-dwc-g210.o
> > obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o
> > ufshcd-dwc.o tc-dwc-g210.o
> > obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
> > -obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
> > +obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o ufshcd-core-objs :=
> > +ufshcd.o ufs-sysfs.o
>
> Why not just adding ufs-sysfs.o in the existing configuration?

The kernel build robot compiles the UFS driver as a separate module.
The existing configuration doesn't allow to add a new file to be compiled
as a part of this module. The line like " obj-$(CONFIG_SCSI_UFSHCD) +=
ufshcd.o ufs-sysfs.o" in the makefile will actually create 2 modules.
This was the reason why I used EXPORT_SYMBOL in the first version.

>
> > obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> > obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git
> > a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c new file
> > mode 100644 index 0000000..1c685f3
> > --- /dev/null
> > +++ b/drivers/scsi/ufs/ufs-sysfs.c
> > @@ -0,0 +1,170 @@
> > +/*
> > +* UFS Device Management sysfs
> > +*
> > +* Copyright (C) 2017 Western Digital Corporation
> > +*
> > +* This program is free software; you can redistribute it and/or
> > +* modify it under the terms of the GNU General Public License version
> > +* 2 as published by the Free Software Foundation.
> > +*
> > +* This program is distributed in the hope that it will be useful, but
> > +* WITHOUT ANY WARRANTY; without even the implied warranty of
> > +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU
> > +* General Public License for more details.
> > +*
> > +*/
> > +
> > +#include <linux/err.h>
> > +#include <linux/string.h>
> > +
> > +#include "ufs.h"
> > +#include "ufs-sysfs.h"
> > +/* collision between the device descriptor parameter and the
> > +definition */ #undef DEVICE_CLASS
>
> Does this make sense? How about attaching "_" for all the macro like
> _DEVICE_CLASS below?
>

It's not just changing the one line that uses "DEVICE_CLASS" to use
"_DEVICE_CLASS". It's will be necessary to add "_" to all descriptor
parameters macros in all patches.

> > +
> > +enum ufs_desc_param_size {
> > + UFS_PARAM_BYTE_SIZE = 1,
> > + UFS_PARAM_WORD_SIZE = 2,
> > + UFS_PARAM_DWORD_SIZE = 4,
> > + UFS_PARAM_QWORD_SIZE = 8,
> > +};
> > +
> > +static inline ssize_t ufs_sysfs_read_desc_param(
> > + struct ufs_hba *hba, u8 desc_idn, u8 index, char *buf, u8 off,
> > + enum ufs_desc_param_size param_size) {
> > + int desc_len;
> > + int ret;
> > + u8 *desc_buf;
> > +
> > + if (ufshcd_map_desc_id_to_length(hba, desc_idn, &desc_len) ||
> > + off >= desc_len)
> > + return -EINVAL;
> > + desc_buf = kzalloc(desc_len, GFP_ATOMIC);
> > + if (!desc_buf)
> > + return -ENOMEM;
> > + ret = ufshcd_query_descriptor_retry(hba,
> UPIU_QUERY_OPCODE_READ_DESC,
> > + desc_idn, index, 0, desc_buf, &desc_len);
> > + if (ret)
>
> Should free desc_buf here.
>
> > + return -EINVAL;
> > + switch (param_size) {
> > + case UFS_PARAM_BYTE_SIZE:
> > + ret = sprintf(buf, "0x%02X\n", desc_buf[off]);
> > + break;
> > + case UFS_PARAM_WORD_SIZE:
> > + ret = sprintf(buf, "0x%04X\n",
> > + be16_to_cpu(*((u16 *)(desc_buf + off))));
> > + break;
> > + case UFS_PARAM_DWORD_SIZE:
> > + ret = sprintf(buf, "0x%08X\n",
> > + be32_to_cpu(*((u32 *)(desc_buf + off))));
> > + break;
> > + case UFS_PARAM_QWORD_SIZE:
> > + ret = sprintf(buf, "0x%016llX\n",
> > + be64_to_cpu(*((u64 *)(desc_buf + off))));
> > + break;
> > + }
> > + kfree(desc_buf);
> > +
> > + return ret;
> > +}
> > +
> > +#define ufs_sysfs_desc_param_show(_name, _puname, _duname,
> _size) \
> > +static ssize_t _name##_show(struct device *dev, \
> > + struct device_attribute *attr, char *buf) \
> > +{ \
> > + struct ufs_hba *hba = dev_get_drvdata(dev); \
> > + return ufs_sysfs_read_desc_param(hba,
> QUERY_DESC_IDN_##_duname, \
> > + 0, buf, _duname##_DESC_PARAM_##_puname, \
> > + UFS_PARAM_##_size##_SIZE); \
> > +}
> > +
> > +#define UFS_DESC_PARAM(_pname, _puname, _duname, _size)
> \
> > + ufs_sysfs_desc_param_show(_pname, _puname, _duname, _size)
> \
> > + static DEVICE_ATTR_RO(_pname)
> > +
> > +#define UFS_DEVICE_DESC_PARAM(_name, _uname, _size)
> \
> > + UFS_DESC_PARAM(_name, _uname, DEVICE, _size)
> > +
> > +UFS_DEVICE_DESC_PARAM(device_type, DEVICE_TYPE, BYTE);
> > +UFS_DEVICE_DESC_PARAM(device_class, DEVICE_CLASS, BYTE);
> > +UFS_DEVICE_DESC_PARAM(device_sub_class, DEVICE_SUB_CLASS,
> BYTE);
> > +UFS_DEVICE_DESC_PARAM(protocol, PRTCL, BYTE);
> > +UFS_DEVICE_DESC_PARAM(number_of_luns, NUM_LU, BYTE);
> > +UFS_DEVICE_DESC_PARAM(number_of_wluns, NUM_WLU, BYTE);
> > +UFS_DEVICE_DESC_PARAM(boot_enable, BOOT_ENBL, BYTE);
> > +UFS_DEVICE_DESC_PARAM(descriptor_access_enable,
> DESC_ACCSS_ENBL,
> > +BYTE); UFS_DEVICE_DESC_PARAM(initial_power_mode,
> INIT_PWR_MODE,
> > +BYTE); UFS_DEVICE_DESC_PARAM(high_priority_lun, HIGH_PR_LUN,
> BYTE);
> > +UFS_DEVICE_DESC_PARAM(secure_removal_type, SEC_RMV_TYPE,
> BYTE);
> > +UFS_DEVICE_DESC_PARAM(support_security_lun, SEC_LU, BYTE);
> > +UFS_DEVICE_DESC_PARAM(bkops_termination_latency,
> BKOP_TERM_LT, BYTE);
> > +UFS_DEVICE_DESC_PARAM(initial_active_icc_level, ACTVE_ICC_LVL,
> BYTE);
> > +UFS_DEVICE_DESC_PARAM(specification_version, SPEC_VER, WORD);
> > +UFS_DEVICE_DESC_PARAM(manufacturing_date, MANF_DATE, WORD);
> > +UFS_DEVICE_DESC_PARAM(manufacturer_id, MANF_ID, WORD);
> > +UFS_DEVICE_DESC_PARAM(rtt_capability, RTT_CAP, BYTE);
> > +UFS_DEVICE_DESC_PARAM(rtc_update, FRQ_RTC, WORD);
> > +UFS_DEVICE_DESC_PARAM(ufs_features, UFS_FEAT, BYTE);
> > +UFS_DEVICE_DESC_PARAM(ffu_timeout, FFU_TMT, BYTE);
> > +UFS_DEVICE_DESC_PARAM(queue_depth, Q_DPTH, BYTE);
> > +UFS_DEVICE_DESC_PARAM(device_version, DEV_VER, WORD);
> > +UFS_DEVICE_DESC_PARAM(number_of_secure_wpa, NUM_SEC_WPA,
> BYTE);
> > +UFS_DEVICE_DESC_PARAM(psa_max_data_size, PSA_MAX_DATA,
> DWORD);
> > +UFS_DEVICE_DESC_PARAM(psa_state_timeout, PSA_TMT, BYTE);
> > +
> > +static struct attribute *ufs_sysfs_device_descriptor[] = {
> > + &dev_attr_device_type.attr,
> > + &dev_attr_device_class.attr,
> > + &dev_attr_device_sub_class.attr,
> > + &dev_attr_protocol.attr,
> > + &dev_attr_number_of_luns.attr,
> > + &dev_attr_number_of_wluns.attr,
> > + &dev_attr_boot_enable.attr,
> > + &dev_attr_descriptor_access_enable.attr,
> > + &dev_attr_initial_power_mode.attr,
> > + &dev_attr_high_priority_lun.attr,
> > + &dev_attr_secure_removal_type.attr,
> > + &dev_attr_support_security_lun.attr,
> > + &dev_attr_bkops_termination_latency.attr,
> > + &dev_attr_initial_active_icc_level.attr,
> > + &dev_attr_specification_version.attr,
> > + &dev_attr_manufacturing_date.attr,
> > + &dev_attr_manufacturer_id.attr,
> > + &dev_attr_rtt_capability.attr,
> > + &dev_attr_rtc_update.attr,
> > + &dev_attr_ufs_features.attr,
> > + &dev_attr_ffu_timeout.attr,
> > + &dev_attr_queue_depth.attr,
> > + &dev_attr_device_version.attr,
> > + &dev_attr_number_of_secure_wpa.attr,
> > + &dev_attr_psa_max_data_size.attr,
> > + &dev_attr_psa_state_timeout.attr,
> > + NULL,
> > +};
> > +
> > +static const struct attribute_group ufs_sysfs_device_descriptor_group = {
> > + .name = "device_descriptor",
> > + .attrs = ufs_sysfs_device_descriptor, };
> > +
> > +static const struct attribute_group *ufs_sysfs_groups[] = {
> > + &ufs_sysfs_device_descriptor_group,
> > + NULL,
> > +};
> > +
> > +void ufs_sysfs_add_device_management(struct ufs_hba *hba) {
> > + int ret;
> > +
> > + ret = sysfs_create_groups(&hba->dev->kobj, ufs_sysfs_groups);
> > + if (ret)
> > + dev_err(hba->dev,
> > + "%s: sysfs groups creation failed (err = %d)\n",
> > + __func__, ret);
> > +}
> > +
> > +void ufs_sysfs_remove_device_management(struct ufs_hba *hba) {
> > + sysfs_remove_groups(&hba->dev->kobj, ufs_sysfs_groups); }
> > diff --git a/drivers/scsi/ufs/ufs-sysfs.h
> > b/drivers/scsi/ufs/ufs-sysfs.h new file mode 100644 index
> > 0000000..a1fc9dc
> > --- /dev/null
> > +++ b/drivers/scsi/ufs/ufs-sysfs.h
> > @@ -0,0 +1,25 @@
> > +/*
> > +* UFS Device Management sysfs
> > +*
> > +* Copyright (C) 2017 Western Digital Corporation
> > +*
> > +* This program is free software; you can redistribute it and/or
> > +* modify it under the terms of the GNU General Public License version
> > +* 2 as published by the Free Software Foundation.
> > +*
> > +* This program is distributed in the hope that it will be useful, but
> > +* WITHOUT ANY WARRANTY; without even the implied warranty of
> > +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU
> > +* General Public License for more details.
> > +*
> > +*/
> > +#ifndef __UFS_SYSFS_H__
> > +#define __UFS_SYSFS_H__
> > +
> > +#include <linux/sysfs.h>
> > +
> > +#include "ufshcd.h"
> > +
> > +void ufs_sysfs_add_device_management(struct ufs_hba *hba); void
> > +ufs_sysfs_remove_device_management(struct ufs_hba *hba); #endif
> > diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index
> > 54deeb7..6ae1e08 100644
> > --- a/drivers/scsi/ufs/ufs.h
> > +++ b/drivers/scsi/ufs/ufs.h
> > @@ -220,6 +220,14 @@ enum device_desc_param {
> > DEVICE_DESC_PARAM_UD_LEN = 0x1B,
> > DEVICE_DESC_PARAM_RTT_CAP = 0x1C,
> > DEVICE_DESC_PARAM_FRQ_RTC = 0x1D,
> > + DEVICE_DESC_PARAM_UFS_FEAT = 0x1F,
> > + DEVICE_DESC_PARAM_FFU_TMT = 0x20,
> > + DEVICE_DESC_PARAM_Q_DPTH = 0x21,
> > + DEVICE_DESC_PARAM_DEV_VER = 0x22,
> > + DEVICE_DESC_PARAM_NUM_SEC_WPA = 0x24,
> > + DEVICE_DESC_PARAM_PSA_MAX_DATA = 0x25,
> > + DEVICE_DESC_PARAM_PSA_TMT = 0x29,
> > + DEVICE_DESC_PARAM_PRDCT_REV = 0x2A,
> > };
> >
> > /*
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index a355d98..97dcb52 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -44,6 +44,7 @@
> > #include "ufshcd.h"
> > #include "ufs_quirks.h"
> > #include "unipro.h"
> > +#include "ufs-sysfs.h"
> >
> > #define CREATE_TRACE_POINTS
> > #include <trace/events/ufs.h>
> > @@ -2894,11 +2895,10 @@ static int __ufshcd_query_descriptor(struct
> ufs_hba *hba,
> > * 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;
> > @@ -7704,10 +7704,12 @@ static inline void
> > ufshcd_add_sysfs_nodes(struct ufs_hba *hba) {
> > ufshcd_add_rpm_lvl_sysfs_nodes(hba);
> > ufshcd_add_spm_lvl_sysfs_nodes(hba);
> > + ufs_sysfs_add_device_management(hba);
>
> IMO, ufs-sysfs.c must have the existing entries above, rpm/spm, as a default
> group first, and then would be better to add device_descriptor_group on top
> of it.
>
> Thanks,
>
> > }
> >
> > static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba) {
> > + ufs_sysfs_remove_device_management(hba);
> > device_remove_file(hba->dev, &hba->rpm_lvl_attr);
> > device_remove_file(hba->dev, &hba->spm_lvl_attr); } diff --git
> > a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index
> > 1332e54..6a0ec4b 100644
> > --- a/drivers/scsi/ufs/ufshcd.h
> > +++ b/drivers/scsi/ufs/ufshcd.h
> > @@ -841,6 +841,10 @@ 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_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
> > enum flag_idn idn, bool *flag_res);
> > int ufshcd_hold(struct ufs_hba *hba, bool async);
> > --
> > 2.7.4

Regards
Happy new year!

2018-01-02 14:04:43

by Stanislav Nijnikov

[permalink] [raw]
Subject: RE: [PATCH v3 1/9] ufs: sysfs: device descriptor



> -----Original Message-----
> From: Greg KH [mailto:[email protected]]
> Sent: Friday, December 29, 2017 11:23 AM
> To: Stanislav Nijnikov <[email protected]>
> Cc: [email protected]; [email protected]; Alex Lemberg
> <[email protected]>
> Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor
>
> On Thu, Dec 28, 2017 at 03:29:06PM +0200, Stanislav Nijnikov wrote:
> > --- /dev/null
> > +++ b/drivers/scsi/ufs/ufs-sysfs.c
> > @@ -0,0 +1,170 @@
> > +/*
> > +* UFS Device Management sysfs
> > +*
> > +* Copyright (C) 2017 Western Digital Corporation
> > +*
> > +* This program is free software; you can redistribute it and/or
> > +* modify it under the terms of the GNU General Public License version
> > +* 2 as published by the Free Software Foundation.
> > +*
> > +* This program is distributed in the hope that it will be useful, but
> > +* WITHOUT ANY WARRANTY; without even the implied warranty of
> > +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU
> > +* General Public License for more details.
>
> Please use the SPDX format for all of this, like I asked last time :(
>
> thanks,
>
> greg k-h

Hi Greg.
Sorry about this.
Is this the proper legal header?

/*
* UFS Device Management sysfs
*
*Copyright (C) 2018 Western Digital Corporation
*This program is free software; you can redistribute it and/or modify it
*under the terms of the GNU General Public License as published by the
*Free Software Foundation; version 2.
*
*This program is distributed in the hope that it will be useful, but
*WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
*General Public License for more details.
*
*You should have received a copy of the GNU General Public License along
*with this program; if not, write to the Free Software Foundation, Inc.,
*51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 , USA.
*/

It was taken from <https://spdx.org/licenses/GPL-2.0-only.html#licenseText>

Thanks and Happy New Year!


2018-01-02 14:22:29

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor

On Tue, Jan 02, 2018 at 02:04:39PM +0000, Stanislav Nijnikov wrote:
>
>
> > -----Original Message-----
> > From: Greg KH [mailto:[email protected]]
> > Sent: Friday, December 29, 2017 11:23 AM
> > To: Stanislav Nijnikov <[email protected]>
> > Cc: [email protected]; [email protected]; Alex Lemberg
> > <[email protected]>
> > Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor
> >
> > On Thu, Dec 28, 2017 at 03:29:06PM +0200, Stanislav Nijnikov wrote:
> > > --- /dev/null
> > > +++ b/drivers/scsi/ufs/ufs-sysfs.c
> > > @@ -0,0 +1,170 @@
> > > +/*
> > > +* UFS Device Management sysfs
> > > +*
> > > +* Copyright (C) 2017 Western Digital Corporation
> > > +*
> > > +* This program is free software; you can redistribute it and/or
> > > +* modify it under the terms of the GNU General Public License version
> > > +* 2 as published by the Free Software Foundation.
> > > +*
> > > +* This program is distributed in the hope that it will be useful, but
> > > +* WITHOUT ANY WARRANTY; without even the implied warranty of
> > > +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > GNU
> > > +* General Public License for more details.
> >
> > Please use the SPDX format for all of this, like I asked last time :(
> >
> > thanks,
> >
> > greg k-h
>
> Hi Greg.
> Sorry about this.
> Is this the proper legal header?

First off, don't as a developer legal questions, ask your lawyers :)

>
> /*
> * UFS Device Management sysfs
> *
> *Copyright (C) 2018 Western Digital Corporation
> *This program is free software; you can redistribute it and/or modify it
> *under the terms of the GNU General Public License as published by the
> *Free Software Foundation; version 2.
> *
> *This program is distributed in the hope that it will be useful, but
> *WITHOUT ANY WARRANTY; without even the implied warranty of
> *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> *General Public License for more details.
> *
> *You should have received a copy of the GNU General Public License along
> *with this program; if not, write to the Free Software Foundation, Inc.,
> *51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 , USA.
> */
>
> It was taken from <https://spdx.org/licenses/GPL-2.0-only.html#licenseText>
>
> Thanks and Happy New Year!

Nope, sorry, see the email thread on lkml from Thomas where he documents
how to properly set the SPDX line and why you don't want any of the
"boiler plate" text in there at all.

thanks,

greg k-h

2018-01-02 15:08:31

by Bart Van Assche

[permalink] [raw]
Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor

On Tue, 2018-01-02 at 13:54 +0000, Stanislav Nijnikov wrote:
> The existing configuration doesn't allow to add a new file to be compiled
> as a part of this module. The line like " obj-$(CONFIG_SCSI_UFSHCD) +=
> ufshcd.o ufs-sysfs.o" in the makefile will actually create 2 modules.
> This was the reason why I used EXPORT_SYMBOL in the first version.

There are plenty of kernel modules that consist of multiple source files, e.g.
the SCSI core. Please make yourself familiar with how to do this.

Thanks,

Bart.

2018-01-03 01:44:03

by Jaegeuk Kim

[permalink] [raw]
Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor

On 01/02, Stanislav Nijnikov wrote:
>
>
> > -----Original Message-----
> > From: Jaegeuk Kim [mailto:[email protected]]
> > Sent: Thursday, December 28, 2017 9:37 PM
> > To: Stanislav Nijnikov <[email protected]>
> > Cc: [email protected]; [email protected];
> > [email protected]; Alex Lemberg <[email protected]>
> > Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor
> >
> > On 12/28, Stanislav Nijnikov wrote:
> > > This patch introduces a sysfs group entry for the UFS device
> > > descriptor parameters. The group adds "device_descriptor" folder under
> > > the UFS driver sysfs entry (/sys/bus/platform/drivers/ufshcd/*). The
> > > parameters are shown as hexadecimal numbers. The full information
> > > about the parameters could be found at UFS specifications 2.1.
> > >
> > > Signed-off-by: Stanislav Nijnikov <[email protected]>
> > > ---
> > > Documentation/ABI/testing/sysfs-driver-ufs | 223
> > +++++++++++++++++++++++++++++
> > > drivers/scsi/ufs/Makefile | 3 +-
> > > drivers/scsi/ufs/ufs-sysfs.c | 170 ++++++++++++++++++++++
> > > drivers/scsi/ufs/ufs-sysfs.h | 25 ++++
> > > drivers/scsi/ufs/ufs.h | 8 ++
> > > drivers/scsi/ufs/ufshcd.c | 12 +-
> > > drivers/scsi/ufs/ufshcd.h | 4 +
> > > 7 files changed, 439 insertions(+), 6 deletions(-) create mode
> > > 100644 Documentation/ABI/testing/sysfs-driver-ufs
> > > create mode 100644 drivers/scsi/ufs/ufs-sysfs.c create mode 100644
> > > drivers/scsi/ufs/ufs-sysfs.h
> > >
> > > diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
> > > b/Documentation/ABI/testing/sysfs-driver-ufs
> > > new file mode 100644
> > > index 0000000..17cc4aa
> > > --- /dev/null
> > > +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> >
> > [snip]
> >
> > > diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> > > index 9310c6c..918f579 100644
> > > --- a/drivers/scsi/ufs/Makefile
> > > +++ b/drivers/scsi/ufs/Makefile
> > > @@ -3,6 +3,7 @@
> > > obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-
> > dwc.o
> > > tc-dwc-g210.o
> > > obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o
> > > ufshcd-dwc.o tc-dwc-g210.o
> > > obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
> > > -obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
> > > +obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o ufshcd-core-objs :=
> > > +ufshcd.o ufs-sysfs.o
> >
> > Why not just adding ufs-sysfs.o in the existing configuration?
>
> The kernel build robot compiles the UFS driver as a separate module.
> The existing configuration doesn't allow to add a new file to be compiled
> as a part of this module. The line like " obj-$(CONFIG_SCSI_UFSHCD) +=
> ufshcd.o ufs-sysfs.o" in the makefile will actually create 2 modules.
> This was the reason why I used EXPORT_SYMBOL in the first version.

Is there a reason to drop the first version?

>
> >
> > > obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> > > obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git
> > > a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c new file
> > > mode 100644 index 0000000..1c685f3
> > > --- /dev/null
> > > +++ b/drivers/scsi/ufs/ufs-sysfs.c
> > > @@ -0,0 +1,170 @@
> > > +/*
> > > +* UFS Device Management sysfs
> > > +*
> > > +* Copyright (C) 2017 Western Digital Corporation
> > > +*
> > > +* This program is free software; you can redistribute it and/or
> > > +* modify it under the terms of the GNU General Public License version
> > > +* 2 as published by the Free Software Foundation.
> > > +*
> > > +* This program is distributed in the hope that it will be useful, but
> > > +* WITHOUT ANY WARRANTY; without even the implied warranty of
> > > +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > GNU
> > > +* General Public License for more details.
> > > +*
> > > +*/
> > > +
> > > +#include <linux/err.h>
> > > +#include <linux/string.h>
> > > +
> > > +#include "ufs.h"
> > > +#include "ufs-sysfs.h"
> > > +/* collision between the device descriptor parameter and the
> > > +definition */ #undef DEVICE_CLASS
> >
> > Does this make sense? How about attaching "_" for all the macro like
> > _DEVICE_CLASS below?
> >
>
> It's not just changing the one line that uses "DEVICE_CLASS" to use
> "_DEVICE_CLASS". It's will be necessary to add "_" to all descriptor
> parameters macros in all patches.

You should be able to do that by moving ufs_sysfs_read_desc_param() into
ufshcd.c, and remaining only the necessary header files for sysfs stuffs.

>
> > > +
> > > +enum ufs_desc_param_size {
> > > + UFS_PARAM_BYTE_SIZE = 1,
> > > + UFS_PARAM_WORD_SIZE = 2,
> > > + UFS_PARAM_DWORD_SIZE = 4,
> > > + UFS_PARAM_QWORD_SIZE = 8,
> > > +};

Must be in header file.

> > > +
> > > +static inline ssize_t ufs_sysfs_read_desc_param(
> > > + struct ufs_hba *hba, u8 desc_idn, u8 index, char *buf, u8 off,
> > > + enum ufs_desc_param_size param_size) {
> > > + int desc_len;
> > > + int ret;
> > > + u8 *desc_buf;
> > > +
> > > + if (ufshcd_map_desc_id_to_length(hba, desc_idn, &desc_len) ||
> > > + off >= desc_len)
> > > + return -EINVAL;
> > > + desc_buf = kzalloc(desc_len, GFP_ATOMIC);
> > > + if (!desc_buf)
> > > + return -ENOMEM;
> > > + ret = ufshcd_query_descriptor_retry(hba,
> > UPIU_QUERY_OPCODE_READ_DESC,
> > > + desc_idn, index, 0, desc_buf, &desc_len);
> > > + if (ret)
> >
> > Should free desc_buf here.
> >
> > > + return -EINVAL;

BTW, the existing ufshcd_read_desc_param() seems the right function for the
above work.

> > > + switch (param_size) {
> > > + case UFS_PARAM_BYTE_SIZE:
> > > + ret = sprintf(buf, "0x%02X\n", desc_buf[off]);
> > > + break;
> > > + case UFS_PARAM_WORD_SIZE:
> > > + ret = sprintf(buf, "0x%04X\n",
> > > + be16_to_cpu(*((u16 *)(desc_buf + off))));
> > > + break;
> > > + case UFS_PARAM_DWORD_SIZE:
> > > + ret = sprintf(buf, "0x%08X\n",
> > > + be32_to_cpu(*((u32 *)(desc_buf + off))));
> > > + break;
> > > + case UFS_PARAM_QWORD_SIZE:
> > > + ret = sprintf(buf, "0x%016llX\n",
> > > + be64_to_cpu(*((u64 *)(desc_buf + off))));
> > > + break;
> > > + }
> > > + kfree(desc_buf);
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +#define ufs_sysfs_desc_param_show(_name, _puname, _duname,

Not a good macro definition. In addition, the patch has some coding style
errors, which requires to pass script/checkpatch.pl.

I didn't test the below fully tho, could you take a look at this change?
IMO, still, making a default group with existing sysfs entries should be done
in prior to this.

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 918f579..1fa74c1 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,7 +3,6 @@
obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o
obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o
obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
-obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
-ufshcd-core-objs := ufshcd.o ufs-sysfs.o
+obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o ufs-sysfs.o
obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 1c685f3..226eb44 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -19,71 +19,22 @@

#include "ufs.h"
#include "ufs-sysfs.h"
-/* collision between the device descriptor parameter and the definition */
-#undef DEVICE_CLASS

-enum ufs_desc_param_size {
- UFS_PARAM_BYTE_SIZE = 1,
- UFS_PARAM_WORD_SIZE = 2,
- UFS_PARAM_DWORD_SIZE = 4,
- UFS_PARAM_QWORD_SIZE = 8,
-};
-
-static inline ssize_t ufs_sysfs_read_desc_param(
- struct ufs_hba *hba, u8 desc_idn, u8 index, char *buf, u8 off,
- enum ufs_desc_param_size param_size)
-{
- int desc_len;
- int ret;
- u8 *desc_buf;
-
- if (ufshcd_map_desc_id_to_length(hba, desc_idn, &desc_len) ||
- off >= desc_len)
- return -EINVAL;
- desc_buf = kzalloc(desc_len, GFP_ATOMIC);
- if (!desc_buf)
- return -ENOMEM;
- ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
- desc_idn, index, 0, desc_buf, &desc_len);
- if (ret)
- return -EINVAL;
- switch (param_size) {
- case UFS_PARAM_BYTE_SIZE:
- ret = sprintf(buf, "0x%02X\n", desc_buf[off]);
- break;
- case UFS_PARAM_WORD_SIZE:
- ret = sprintf(buf, "0x%04X\n",
- be16_to_cpu(*((u16 *)(desc_buf + off))));
- break;
- case UFS_PARAM_DWORD_SIZE:
- ret = sprintf(buf, "0x%08X\n",
- be32_to_cpu(*((u32 *)(desc_buf + off))));
- break;
- case UFS_PARAM_QWORD_SIZE:
- ret = sprintf(buf, "0x%016llX\n",
- be64_to_cpu(*((u64 *)(desc_buf + off))));
- break;
- }
- kfree(desc_buf);
-
- return ret;
-}
-
-#define ufs_sysfs_desc_param_show(_name, _puname, _duname, _size) \
-static ssize_t _name##_show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- struct ufs_hba *hba = dev_get_drvdata(dev); \
- return ufs_sysfs_read_desc_param(hba, QUERY_DESC_IDN_##_duname, \
- 0, buf, _duname##_DESC_PARAM_##_puname, \
- UFS_PARAM_##_size##_SIZE); \
-}
-
-#define UFS_DESC_PARAM(_pname, _puname, _duname, _size) \
- ufs_sysfs_desc_param_show(_pname, _puname, _duname, _size) \
- static DEVICE_ATTR_RO(_pname)
-
-#define UFS_DEVICE_DESC_PARAM(_name, _uname, _size) \
+#define UFS_DESC_PARAM_SHOW(_name, _puname, _duname, _size) \
+static ssize_t _name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ return ufshcd_sysfs_read_desc_param(dev, \
+ QUERY_DESC_IDN_##_duname, \
+ 0, _duname##_DESC_PARAM_##_puname, buf, \
+ UFS_PARAM_##_size##_SIZE); \
+} \
+static DEVICE_ATTR_RO(_name)
+
+#define UFS_DESC_PARAM(_pname, _puname, _duname, _size) \
+ UFS_DESC_PARAM_SHOW(_pname, _puname, _duname, _size)
+
+#define UFS_DEVICE_DESC_PARAM(_name, _uname, _size) \
UFS_DESC_PARAM(_name, _uname, DEVICE, _size)

UFS_DEVICE_DESC_PARAM(device_type, DEVICE_TYPE, BYTE);
@@ -153,18 +104,21 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
NULL,
};

-void ufs_sysfs_add_device_management(struct ufs_hba *hba)
+void ufs_sysfs_add_device_management(struct device *dev)
{
int ret;

- ret = sysfs_create_groups(&hba->dev->kobj, ufs_sysfs_groups);
+ ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_groups);
if (ret)
- dev_err(hba->dev,
+ dev_err(dev,
"%s: sysfs groups creation failed (err = %d)\n",
__func__, ret);
}

-void ufs_sysfs_remove_device_management(struct ufs_hba *hba)
+void ufs_sysfs_remove_device_management(struct device *dev)
{
- sysfs_remove_groups(&hba->dev->kobj, ufs_sysfs_groups);
+ sysfs_remove_groups(&dev->kobj, ufs_sysfs_groups);
}
+
+EXPORT_SYMBOL(ufs_sysfs_add_device_management);
+EXPORT_SYMBOL(ufs_sysfs_remove_device_management);
diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
index a1fc9dc..c857e20 100644
--- a/drivers/scsi/ufs/ufs-sysfs.h
+++ b/drivers/scsi/ufs/ufs-sysfs.h
@@ -16,10 +16,23 @@
#ifndef __UFS_SYSFS_H__
#define __UFS_SYSFS_H__

+#include <linux/device.h>
#include <linux/sysfs.h>

-#include "ufshcd.h"
+enum ufs_desc_param_size {
+ UFS_PARAM_BYTE_SIZE = 1,
+ UFS_PARAM_WORD_SIZE = 2,
+ UFS_PARAM_DWORD_SIZE = 4,
+ UFS_PARAM_QWORD_SIZE = 8,
+};

-void ufs_sysfs_add_device_management(struct ufs_hba *hba);
-void ufs_sysfs_remove_device_management(struct ufs_hba *hba);
+extern void ufs_sysfs_add_device_management(struct device *dev);
+extern void ufs_sysfs_remove_device_management(struct device *dev);
+
+extern ssize_t ufshcd_sysfs_read_desc_param(struct device *dev,
+ enum desc_idn desc_id,
+ u8 desc_index,
+ u8 param_offset,
+ u8 *sysfs_buf,
+ u8 param_size);
#endif
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c1c45c1..7d38e1b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2895,7 +2895,7 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
* The buf_len parameter will contain, on return, the length parameter
* received on the response.
*/
-int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
+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)
@@ -3079,6 +3079,46 @@ static int ufshcd_read_desc_param(struct ufs_hba *hba,
return ret;
}

+ssize_t ufshcd_sysfs_read_desc_param(struct device *dev,
+ enum desc_idn desc_id,
+ u8 desc_index,
+ u8 param_offset,
+ u8 *sysfs_buf,
+ u8 param_size)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ u8 desc_buf[UFS_PARAM_QWORD_SIZE] = {0};
+ int ret;
+
+ if (param_size > UFS_PARAM_QWORD_SIZE)
+ return -EINVAL;
+
+ ret = ufshcd_read_desc_param(hba, desc_id, desc_index,
+ param_offset, desc_buf, param_size);
+ if (ret)
+ return ret;
+
+ switch (param_size) {
+ case UFS_PARAM_BYTE_SIZE:
+ ret = sprintf(sysfs_buf, "0x%02X\n", *desc_buf);
+ break;
+ case UFS_PARAM_WORD_SIZE:
+ ret = sprintf(sysfs_buf, "0x%04X\n",
+ be16_to_cpu(*((u16 *)desc_buf)));
+ break;
+ case UFS_PARAM_DWORD_SIZE:
+ ret = sprintf(sysfs_buf, "0x%08X\n",
+ be32_to_cpu(*((u32 *)desc_buf)));
+ break;
+ case UFS_PARAM_QWORD_SIZE:
+ ret = sprintf(sysfs_buf, "0x%016llX\n",
+ be64_to_cpu(*((u64 *)desc_buf)));
+ break;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(ufshcd_sysfs_read_desc_param);
+
static inline int ufshcd_read_desc(struct ufs_hba *hba,
enum desc_idn desc_id,
int desc_index,
@@ -7701,12 +7741,12 @@ static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba)
{
ufshcd_add_rpm_lvl_sysfs_nodes(hba);
ufshcd_add_spm_lvl_sysfs_nodes(hba);
- ufs_sysfs_add_device_management(hba);
+ ufs_sysfs_add_device_management(hba->dev);
}

static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba)
{
- ufs_sysfs_remove_device_management(hba);
+ ufs_sysfs_remove_device_management(hba->dev);
device_remove_file(hba->dev, &hba->rpm_lvl_attr);
device_remove_file(hba->dev, &hba->spm_lvl_attr);
}
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 6a0ec4b..1332e54 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -841,10 +841,6 @@ 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_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
enum flag_idn idn, bool *flag_res);
int ufshcd_hold(struct ufs_hba *hba, bool async);

2018-01-04 17:46:31

by Stanislav Nijnikov

[permalink] [raw]
Subject: RE: [PATCH v3 1/9] ufs: sysfs: device descriptor



> -----Original Message-----
> From: Jaegeuk Kim [mailto:[email protected]]
> Sent: Wednesday, January 3, 2018 3:44 AM
> To: Stanislav Nijnikov <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; Alex Lemberg <[email protected]>
> Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor
>
> On 01/02, Stanislav Nijnikov wrote:
> >
> >
> > > -----Original Message-----
> > > From: Jaegeuk Kim [mailto:[email protected]]
> > > Sent: Thursday, December 28, 2017 9:37 PM
> > > To: Stanislav Nijnikov <[email protected]>
> > > Cc: [email protected]; [email protected];
> > > [email protected]; Alex Lemberg <[email protected]>
> > > Subject: Re: [PATCH v3 1/9] ufs: sysfs: device descriptor
> > >
> > > On 12/28, Stanislav Nijnikov wrote:
> > > > This patch introduces a sysfs group entry for the UFS device
> > > > descriptor parameters. The group adds "device_descriptor" folder
> > > > under the UFS driver sysfs entry
> > > > (/sys/bus/platform/drivers/ufshcd/*). The parameters are shown as
> > > > hexadecimal numbers. The full information about the parameters could
> be found at UFS specifications 2.1.
> > > >
> > > > Signed-off-by: Stanislav Nijnikov <[email protected]>
> > > > ---
> > > > Documentation/ABI/testing/sysfs-driver-ufs | 223
> > > +++++++++++++++++++++++++++++
> > > > drivers/scsi/ufs/Makefile | 3 +-
> > > > drivers/scsi/ufs/ufs-sysfs.c | 170 ++++++++++++++++++++++
> > > > drivers/scsi/ufs/ufs-sysfs.h | 25 ++++
> > > > drivers/scsi/ufs/ufs.h | 8 ++
> > > > drivers/scsi/ufs/ufshcd.c | 12 +-
> > > > drivers/scsi/ufs/ufshcd.h | 4 +
> > > > 7 files changed, 439 insertions(+), 6 deletions(-) create mode
> > > > 100644 Documentation/ABI/testing/sysfs-driver-ufs
> > > > create mode 100644 drivers/scsi/ufs/ufs-sysfs.c create mode
> > > > 100644 drivers/scsi/ufs/ufs-sysfs.h
> > > >
> > > > diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
> > > > b/Documentation/ABI/testing/sysfs-driver-ufs
> > > > new file mode 100644
> > > > index 0000000..17cc4aa
> > > > --- /dev/null
> > > > +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> > >
> > > [snip]
> > >
> > > > diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> > > > index 9310c6c..918f579 100644
> > > > --- a/drivers/scsi/ufs/Makefile
> > > > +++ b/drivers/scsi/ufs/Makefile
> > > > @@ -3,6 +3,7 @@
> > > > obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-
> > > dwc.o
> > > > tc-dwc-g210.o
> > > > obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-
> pltfrm.o
> > > > ufshcd-dwc.o tc-dwc-g210.o
> > > > obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
> > > > -obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
> > > > +obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o ufshcd-core-objs :=
> > > > +ufshcd.o ufs-sysfs.o
> > >
> > > Why not just adding ufs-sysfs.o in the existing configuration?
> >
> > The kernel build robot compiles the UFS driver as a separate module.
> > The existing configuration doesn't allow to add a new file to be
> > compiled as a part of this module. The line like "
> > obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o ufs-sysfs.o" in the makefile will
> actually create 2 modules.
> > This was the reason why I used EXPORT_SYMBOL in the first version.
>
> Is there a reason to drop the first version?
>
It was updated according to Greg Kroah-Hartman' notes (one of them was what is
a reason to use EXPORT_SYMBOL if functions are used only in one module).
> >
> > >
> > > > obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> > > > obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git
> > > > a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c new
> > > > file mode 100644 index 0000000..1c685f3
> > > > --- /dev/null
> > > > +++ b/drivers/scsi/ufs/ufs-sysfs.c
> > > > @@ -0,0 +1,170 @@
> > > > +/*
> > > > +* UFS Device Management sysfs
> > > > +*
> > > > +* Copyright (C) 2017 Western Digital Corporation
> > > > +*
> > > > +* This program is free software; you can redistribute it and/or
> > > > +* modify it under the terms of the GNU General Public License
> > > > +version
> > > > +* 2 as published by the Free Software Foundation.
> > > > +*
> > > > +* This program is distributed in the hope that it will be useful,
> > > > +but
> > > > +* WITHOUT ANY WARRANTY; without even the implied warranty of
> > > > +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
> the
> > > GNU
> > > > +* General Public License for more details.
> > > > +*
> > > > +*/
> > > > +
> > > > +#include <linux/err.h>
> > > > +#include <linux/string.h>
> > > > +
> > > > +#include "ufs.h"
> > > > +#include "ufs-sysfs.h"
> > > > +/* collision between the device descriptor parameter and the
> > > > +definition */ #undef DEVICE_CLASS
> > >
> > > Does this make sense? How about attaching "_" for all the macro like
> > > _DEVICE_CLASS below?
> > >
> >
> > It's not just changing the one line that uses "DEVICE_CLASS" to use
> > "_DEVICE_CLASS". It's will be necessary to add "_" to all descriptor
> > parameters macros in all patches.
>
> You should be able to do that by moving ufs_sysfs_read_desc_param() into
> ufshcd.c, and remaining only the necessary header files for sysfs stuffs.
>

I see your point but then I'll have to put many sysfs related functions (
reading descriptor parameters, reading string descriptor, reading flags
and attributes) into the "ufshcd.c" file which I would like to avoid. And it
will be necessary to use no definitions from "ufshcd.h" in the "ufs-sysfs.c"
functions.

> >
> > > > +
> > > > +enum ufs_desc_param_size {
> > > > + UFS_PARAM_BYTE_SIZE = 1,
> > > > + UFS_PARAM_WORD_SIZE = 2,
> > > > + UFS_PARAM_DWORD_SIZE = 4,
> > > > + UFS_PARAM_QWORD_SIZE = 8,
> > > > +};
>
> Must be in header file.
>
> > > > +
> > > > +static inline ssize_t ufs_sysfs_read_desc_param(
> > > > + struct ufs_hba *hba, u8 desc_idn, u8 index, char *buf, u8 off,
> > > > + enum ufs_desc_param_size param_size) {
> > > > + int desc_len;
> > > > + int ret;
> > > > + u8 *desc_buf;
> > > > +
> > > > + if (ufshcd_map_desc_id_to_length(hba, desc_idn, &desc_len) ||
> > > > + off >= desc_len)
> > > > + return -EINVAL;
> > > > + desc_buf = kzalloc(desc_len, GFP_ATOMIC);
> > > > + if (!desc_buf)
> > > > + return -ENOMEM;
> > > > + ret = ufshcd_query_descriptor_retry(hba,
> > > UPIU_QUERY_OPCODE_READ_DESC,
> > > > + desc_idn, index, 0, desc_buf, &desc_len);
> > > > + if (ret)
> > >
> > > Should free desc_buf here.
> > >
> > > > + return -EINVAL;
>
> BTW, the existing ufshcd_read_desc_param() seems the right function for
> the above work.
>
> > > > + switch (param_size) {
> > > > + case UFS_PARAM_BYTE_SIZE:
> > > > + ret = sprintf(buf, "0x%02X\n", desc_buf[off]);
> > > > + break;
> > > > + case UFS_PARAM_WORD_SIZE:
> > > > + ret = sprintf(buf, "0x%04X\n",
> > > > + be16_to_cpu(*((u16 *)(desc_buf + off))));
> > > > + break;
> > > > + case UFS_PARAM_DWORD_SIZE:
> > > > + ret = sprintf(buf, "0x%08X\n",
> > > > + be32_to_cpu(*((u32 *)(desc_buf + off))));
> > > > + break;
> > > > + case UFS_PARAM_QWORD_SIZE:
> > > > + ret = sprintf(buf, "0x%016llX\n",
> > > > + be64_to_cpu(*((u64 *)(desc_buf + off))));
> > > > + break;
> > > > + }
> > > > + kfree(desc_buf);
> > > > +
> > > > + return ret;
> > > > +}
> > > > +
> > > > +#define ufs_sysfs_desc_param_show(_name, _puname, _duname,
>
> Not a good macro definition. In addition, the patch has some coding style
> errors, which requires to pass script/checkpatch.pl.
>
> I didn't test the below fully tho, could you take a look at this change?
> IMO, still, making a default group with existing sysfs entries should be done
> in prior to this.
>
> diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index
> 918f579..1fa74c1 100644
> --- a/drivers/scsi/ufs/Makefile
> +++ b/drivers/scsi/ufs/Makefile
> @@ -3,7 +3,6 @@
> obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o
> tc-dwc-g210.o
> obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o
> ufshcd-dwc.o tc-dwc-g210.o
> obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
> -obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o -ufshcd-core-objs :=
> ufshcd.o ufs-sysfs.o
> +obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o ufs-sysfs.o
> obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
> obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git
> a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index
> 1c685f3..226eb44 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -19,71 +19,22 @@
>
> #include "ufs.h"
> #include "ufs-sysfs.h"
> -/* collision between the device descriptor parameter and the definition */ -
> #undef DEVICE_CLASS
>
> -enum ufs_desc_param_size {
> - UFS_PARAM_BYTE_SIZE = 1,
> - UFS_PARAM_WORD_SIZE = 2,
> - UFS_PARAM_DWORD_SIZE = 4,
> - UFS_PARAM_QWORD_SIZE = 8,
> -};
> -
> -static inline ssize_t ufs_sysfs_read_desc_param(
> - struct ufs_hba *hba, u8 desc_idn, u8 index, char *buf, u8 off,
> - enum ufs_desc_param_size param_size)
> -{
> - int desc_len;
> - int ret;
> - u8 *desc_buf;
> -
> - if (ufshcd_map_desc_id_to_length(hba, desc_idn, &desc_len) ||
> - off >= desc_len)
> - return -EINVAL;
> - desc_buf = kzalloc(desc_len, GFP_ATOMIC);
> - if (!desc_buf)
> - return -ENOMEM;
> - ret = ufshcd_query_descriptor_retry(hba,
> UPIU_QUERY_OPCODE_READ_DESC,
> - desc_idn, index, 0, desc_buf, &desc_len);
> - if (ret)
> - return -EINVAL;
> - switch (param_size) {
> - case UFS_PARAM_BYTE_SIZE:
> - ret = sprintf(buf, "0x%02X\n", desc_buf[off]);
> - break;
> - case UFS_PARAM_WORD_SIZE:
> - ret = sprintf(buf, "0x%04X\n",
> - be16_to_cpu(*((u16 *)(desc_buf + off))));
> - break;
> - case UFS_PARAM_DWORD_SIZE:
> - ret = sprintf(buf, "0x%08X\n",
> - be32_to_cpu(*((u32 *)(desc_buf + off))));
> - break;
> - case UFS_PARAM_QWORD_SIZE:
> - ret = sprintf(buf, "0x%016llX\n",
> - be64_to_cpu(*((u64 *)(desc_buf + off))));
> - break;
> - }
> - kfree(desc_buf);
> -
> - return ret;
> -}
> -
> -#define ufs_sysfs_desc_param_show(_name, _puname, _duname, _size)
> \
> -static ssize_t _name##_show(struct device *dev, \
> - struct device_attribute *attr, char *buf) \
> -{ \
> - struct ufs_hba *hba = dev_get_drvdata(dev); \
> - return ufs_sysfs_read_desc_param(hba,
> QUERY_DESC_IDN_##_duname, \
> - 0, buf, _duname##_DESC_PARAM_##_puname, \
> - UFS_PARAM_##_size##_SIZE); \
> -}
> -
> -#define UFS_DESC_PARAM(_pname, _puname, _duname, _size)
> \
> - ufs_sysfs_desc_param_show(_pname, _puname, _duname, _size)
> \
> - static DEVICE_ATTR_RO(_pname)
> -
> -#define UFS_DEVICE_DESC_PARAM(_name, _uname, _size) \
> +#define UFS_DESC_PARAM_SHOW(_name, _puname, _duname, _size)
> \
> +static ssize_t _name##_show(struct device *dev,
> \
> + struct device_attribute *attr, char *buf) \
> +{ \
> + return ufshcd_sysfs_read_desc_param(dev, \
> + QUERY_DESC_IDN_##_duname,
> \
> + 0, _duname##_DESC_PARAM_##_puname, buf,
> \
> + UFS_PARAM_##_size##_SIZE);
> \
> +} \
> +static DEVICE_ATTR_RO(_name)
> +
> +#define UFS_DESC_PARAM(_pname, _puname, _duname, _size)
> \
> + UFS_DESC_PARAM_SHOW(_pname, _puname, _duname, _size)
> +
> +#define UFS_DEVICE_DESC_PARAM(_name, _uname, _size)
> \
> UFS_DESC_PARAM(_name, _uname, DEVICE, _size)
>
> UFS_DEVICE_DESC_PARAM(device_type, DEVICE_TYPE, BYTE); @@ -153,18
> +104,21 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
> NULL,
> };
>
> -void ufs_sysfs_add_device_management(struct ufs_hba *hba)
> +void ufs_sysfs_add_device_management(struct device *dev)
> {
> int ret;
>
> - ret = sysfs_create_groups(&hba->dev->kobj, ufs_sysfs_groups);
> + ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_groups);
> if (ret)
> - dev_err(hba->dev,
> + dev_err(dev,
> "%s: sysfs groups creation failed (err = %d)\n",
> __func__, ret);
> }
>
> -void ufs_sysfs_remove_device_management(struct ufs_hba *hba)
> +void ufs_sysfs_remove_device_management(struct device *dev)
> {
> - sysfs_remove_groups(&hba->dev->kobj, ufs_sysfs_groups);
> + sysfs_remove_groups(&dev->kobj, ufs_sysfs_groups);
> }
> +
> +EXPORT_SYMBOL(ufs_sysfs_add_device_management);
> +EXPORT_SYMBOL(ufs_sysfs_remove_device_management);
> diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h index
> a1fc9dc..c857e20 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.h
> +++ b/drivers/scsi/ufs/ufs-sysfs.h
> @@ -16,10 +16,23 @@
> #ifndef __UFS_SYSFS_H__
> #define __UFS_SYSFS_H__
>
> +#include <linux/device.h>
> #include <linux/sysfs.h>
>
> -#include "ufshcd.h"
> +enum ufs_desc_param_size {
> + UFS_PARAM_BYTE_SIZE = 1,
> + UFS_PARAM_WORD_SIZE = 2,
> + UFS_PARAM_DWORD_SIZE = 4,
> + UFS_PARAM_QWORD_SIZE = 8,
> +};
>
> -void ufs_sysfs_add_device_management(struct ufs_hba *hba); -void
> ufs_sysfs_remove_device_management(struct ufs_hba *hba);
> +extern void ufs_sysfs_add_device_management(struct device *dev);
> extern
> +void ufs_sysfs_remove_device_management(struct device *dev);
> +
> +extern ssize_t ufshcd_sysfs_read_desc_param(struct device *dev,
> + enum desc_idn desc_id,
> + u8 desc_index,
> + u8 param_offset,
> + u8 *sysfs_buf,
> + u8 param_size);
> #endif
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index
> c1c45c1..7d38e1b 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -2895,7 +2895,7 @@ static int __ufshcd_query_descriptor(struct
> ufs_hba *hba,
> * The buf_len parameter will contain, on return, the length parameter
> * received on the response.
> */
> -int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
> +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)
> @@ -3079,6 +3079,46 @@ static int ufshcd_read_desc_param(struct ufs_hba
> *hba,
> return ret;
> }
>
> +ssize_t ufshcd_sysfs_read_desc_param(struct device *dev,
> + enum desc_idn desc_id,
> + u8 desc_index,
> + u8 param_offset,
> + u8 *sysfs_buf,
> + u8 param_size)
> +{
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> + u8 desc_buf[UFS_PARAM_QWORD_SIZE] = {0};
> + int ret;
> +
> + if (param_size > UFS_PARAM_QWORD_SIZE)
> + return -EINVAL;
> +
> + ret = ufshcd_read_desc_param(hba, desc_id, desc_index,
> + param_offset, desc_buf, param_size);
> + if (ret)
> + return ret;
> +
> + switch (param_size) {
> + case UFS_PARAM_BYTE_SIZE:
> + ret = sprintf(sysfs_buf, "0x%02X\n", *desc_buf);
> + break;
> + case UFS_PARAM_WORD_SIZE:
> + ret = sprintf(sysfs_buf, "0x%04X\n",
> + be16_to_cpu(*((u16 *)desc_buf)));
> + break;
> + case UFS_PARAM_DWORD_SIZE:
> + ret = sprintf(sysfs_buf, "0x%08X\n",
> + be32_to_cpu(*((u32 *)desc_buf)));
> + break;
> + case UFS_PARAM_QWORD_SIZE:
> + ret = sprintf(sysfs_buf, "0x%016llX\n",
> + be64_to_cpu(*((u64 *)desc_buf)));
> + break;
> + }
> + return ret;
> +}
> +EXPORT_SYMBOL(ufshcd_sysfs_read_desc_param);
> +
> static inline int ufshcd_read_desc(struct ufs_hba *hba,
> enum desc_idn desc_id,
> int desc_index,
> @@ -7701,12 +7741,12 @@ static inline void ufshcd_add_sysfs_nodes(struct
> ufs_hba *hba) {
> ufshcd_add_rpm_lvl_sysfs_nodes(hba);
> ufshcd_add_spm_lvl_sysfs_nodes(hba);
> - ufs_sysfs_add_device_management(hba);
> + ufs_sysfs_add_device_management(hba->dev);
> }
>
> static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba) {
> - ufs_sysfs_remove_device_management(hba);
> + ufs_sysfs_remove_device_management(hba->dev);
> device_remove_file(hba->dev, &hba->rpm_lvl_attr);
> device_remove_file(hba->dev, &hba->spm_lvl_attr); } diff --git
> a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index
> 6a0ec4b..1332e54 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -841,10 +841,6 @@ 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_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
> enum flag_idn idn, bool *flag_res);
> int ufshcd_hold(struct ufs_hba *hba, bool async);

Thank you a lot for your advice. I'll add the default group for existing sysfs entries
as first patch, update all patches as recommended and test it.