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:
v3 -> v4
Additional patch the introduces default attributes group for the
existing ufs sysfs entries (rpm_lvl and spm_lvl)
The ufs_sysfs_read_desc_param function calls to ufshcd_read_desc_param
insted of ufshcd_query_descriptor_retry to avoid code duplication.
The code was updated to remove the checkpatch error "ERROR: Macros
with complex values should be enclosed in parentheses"
Added "_" to macros parameters to remove "#undef DEVICE_CLASS"
The legal information was updated to satisfy the SPDX requirements
The date in Documentation/ABI/testing/sysfs-driver-ufs was updated.
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 (10):
ufs: sysfs: attribute group for existing sysfs entries.
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 | 757 +++++++++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.h | 25 +
drivers/scsi/ufs/ufs.h | 115 ++++-
drivers/scsi/ufs/ufshcd.c | 218 ++------
drivers/scsi/ufs/ufshcd.h | 34 ++
include/scsi/scsi_host.h | 6 +
9 files changed, 1785 insertions(+), 191 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
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 | 139 +++++++++++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.c | 82 +++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.h | 1 +
drivers/scsi/ufs/ufs.h | 27 +++++-
drivers/scsi/ufs/ufshcd.c | 5 +-
drivers/scsi/ufs/ufshcd.h | 3 +-
6 files changed, 250 insertions(+), 7 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index f4f49e2..07f1c2f 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -663,3 +663,142 @@ 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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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 ab04205..1fb401f 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -592,6 +592,61 @@ static const struct attribute_group ufs_sysfs_flags_group = {
.attrs = ufs_sysfs_device_flags,
};
+#define UFS_ATTRIBUTE(_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); \
+} \
+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_default_group,
&ufs_sysfs_device_descriptor_group,
@@ -601,6 +656,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,
};
@@ -658,6 +714,32 @@ struct attribute_group ufs_sysfs_unit_descriptor_group = {
.attrs = ufs_sysfs_unit_descriptor,
};
+#define UFS_LUN_ATTRIBUTE(_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); \
+} \
+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_nodes(struct device *dev)
{
int ret;
diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
index 4241748..3149bec 100644
--- a/drivers/scsi/ufs/ufs-sysfs.h
+++ b/drivers/scsi/ufs/ufs-sysfs.h
@@ -21,4 +21,5 @@ void ufs_sysfs_add_nodes(struct device *dev);
void ufs_sysfs_remove_nodes(struct device *dev);
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 dcda8ac..f169764 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2689,8 +2689,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;
@@ -6468,6 +6468,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 f4cb31b..deb3c5d 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -847,13 +847,14 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
enum desc_idn idn, u8 index,
u8 selector,
u8 *desc_buf, int *buf_len);
-
int ufshcd_read_desc_param(struct ufs_hba *hba,
enum desc_idn desc_id,
int desc_index,
u8 param_offset,
u8 *param_read_buf,
u8 param_size);
+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
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]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 108 +++++++++++++++++++++++++++++
drivers/scsi/scsi_sysfs.c | 14 ++++
drivers/scsi/ufs/ufs-sysfs.c | 54 +++++++++++++++
drivers/scsi/ufs/ufs-sysfs.h | 2 +
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, 217 insertions(+), 16 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index c17a968..57c6a90 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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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 cbc0fe2..69a6a1f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1309,6 +1309,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;
}
@@ -1326,6 +1334,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 db5d2f8..265eca6 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -565,6 +565,60 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
NULL,
};
+#define UFS_LUN_DESC_PARAM(_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, _duname##_DESC_PARAM##_puname, \
+ buf, UFS_PARAM_##_size##_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_nodes(struct device *dev)
{
int ret;
diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
index c53c039..4241748 100644
--- a/drivers/scsi/ufs/ufs-sysfs.h
+++ b/drivers/scsi/ufs/ufs-sysfs.h
@@ -19,4 +19,6 @@
void ufs_sysfs_add_nodes(struct device *dev);
void ufs_sysfs_remove_nodes(struct device *dev);
+
+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 9cfdd8e..dcda8ac 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2222,21 +2222,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
@@ -3171,7 +3156,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,
@@ -6481,6 +6466,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,
@@ -6500,6 +6490,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 2dad9da..f4cb31b 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -1003,4 +1003,19 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
extern struct ufs_pm_lvl_states ufs_pm_lvl_states[];
+/*
+ * 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
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]>
---
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 6ea7613..ddb012b 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: February 2018
+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: February 2018
+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: February 2018
+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 6427804..1c89009 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -364,11 +364,31 @@ 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_default_group,
&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 540a431..b88fcf7 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2966,6 +2966,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;
@@ -6277,6 +6280,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)
@@ -6287,6 +6294,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 38c307d..515c6e6 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
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]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 39 +++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.c | 55 ++++++++++++++++++++++++++++++
drivers/scsi/ufs/ufshcd.c | 14 ++++----
drivers/scsi/ufs/ufshcd.h | 9 +++++
4 files changed, 110 insertions(+), 7 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index 7460566..c17a968 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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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 d2e6b49..db5d2f8 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -500,6 +500,60 @@ static const struct attribute_group ufs_sysfs_power_descriptor_group = {
.attrs = ufs_sysfs_power_descriptor,
};
+#define UFS_STRING_DESCRIPTOR(_name, _pname) \
+static ssize_t _name##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ u8 index; \
+ struct ufs_hba *hba = dev_get_drvdata(dev); \
+ int ret; \
+ int desc_len = QUERY_DESC_MAX_SIZE; \
+ u8 *desc_buf; \
+ desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_ATOMIC); \
+ if (!desc_buf) \
+ return -ENOMEM; \
+ ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC, \
+ QUERY_DESC_IDN_DEVICE, 0, 0, desc_buf, &desc_len); \
+ if (ret) { \
+ ret = -EINVAL; \
+ goto out; \
+ } \
+ index = desc_buf[DEVICE_DESC_PARAM##_pname]; \
+ memset(desc_buf, 0, QUERY_DESC_MAX_SIZE); \
+ if (ufshcd_read_string_desc(hba, index, desc_buf, \
+ QUERY_DESC_MAX_SIZE, true)) { \
+ ret = -EINVAL; \
+ goto out; \
+ } \
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", \
+ desc_buf + QUERY_DESC_HDR_SIZE); \
+out: \
+ kfree(desc_buf); \
+ return ret; \
+} \
+static DEVICE_ATTR_RO(_name)
+
+UFS_STRING_DESCRIPTOR(manufacturer_name, _MANF_NAME);
+UFS_STRING_DESCRIPTOR(product_name, _PRDCT_NAME);
+UFS_STRING_DESCRIPTOR(oem_id, _OEM_ID);
+UFS_STRING_DESCRIPTOR(serial_number, _SN);
+UFS_STRING_DESCRIPTOR(product_revision, _PRDCT_REV);
+
+static struct attribute *ufs_sysfs_string_descriptors[] = {
+ &dev_attr_manufacturer_name.attr,
+ &dev_attr_product_name.attr,
+ &dev_attr_oem_id.attr,
+ &dev_attr_serial_number.attr,
+ &dev_attr_product_revision.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_string_descriptors_group = {
+ .name = "string_descriptors",
+ .attrs = ufs_sysfs_string_descriptors,
+};
+
+
static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_default_group,
&ufs_sysfs_device_descriptor_group,
@@ -507,6 +561,7 @@ static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_geometry_descriptor_group,
&ufs_sysfs_health_descriptor_group,
&ufs_sysfs_power_descriptor_group,
+ &ufs_sysfs_string_descriptors_group,
NULL,
};
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b88fcf7..9cfdd8e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2873,11 +2873,11 @@ 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;
@@ -3093,8 +3093,8 @@ static int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size)
* Return 0 in case of success, non-zero otherwise
*/
#define ASCII_STD true
-static int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
- u8 *buf, u32 size, bool ascii)
+int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
+ u8 *buf, u32 size, bool ascii)
{
int err = 0;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 515c6e6..2dad9da 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -842,6 +842,12 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
}
/* Expose Query-Request API */
+int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
+ enum query_opcode opcode,
+ enum desc_idn idn, u8 index,
+ u8 selector,
+ u8 *desc_buf, int *buf_len);
+
int ufshcd_read_desc_param(struct ufs_hba *hba,
enum desc_idn desc_id,
int desc_index,
@@ -850,6 +856,9 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
u8 param_size);
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
enum flag_idn idn, bool *flag_res);
+int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
+ u8 *buf, u32 size, bool ascii);
+
int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba);
--
2.7.4
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 | 39 ++++++++++++++++++
drivers/scsi/ufs/ufs.h | 14 +++++--
3 files changed, 115 insertions(+), 3 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index 57c6a90..f4f49e2 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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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 265eca6..ab04205 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -553,6 +553,44 @@ static const struct attribute_group ufs_sysfs_string_descriptors_group = {
.attrs = ufs_sysfs_string_descriptors,
};
+#define UFS_FLAG(_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"); \
+} \
+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_default_group,
@@ -562,6 +600,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
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]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 10 +++
drivers/scsi/ufs/ufs-sysfs.c | 118 +++++++++++++++++++++++++++++
2 files changed, 128 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index ddb012b..7460566 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: February 2018
+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 1c89009..d2e6b49 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -383,12 +383,130 @@ static const struct attribute_group ufs_sysfs_health_descriptor_group = {
.attrs = ufs_sysfs_health_descriptor,
};
+#define UFS_POWER_DESC_PARAM(_name, _uname, _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, \
+ PWR_DESC##_uname##_0 + _index * UFS_PARAM_WORD_SIZE, \
+ buf, UFS_PARAM_WORD_SIZE); \
+} \
+static DEVICE_ATTR_RO(_name##_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_default_group,
&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
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/ufs-sysfs.c | 123 ++++++++++++++++
drivers/scsi/ufs/ufs.h | 8 ++
drivers/scsi/ufs/ufshcd.c | 12 +-
drivers/scsi/ufs/ufshcd.h | 6 +
5 files changed, 366 insertions(+), 6 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-driver-ufs
diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
new file mode 100644
index 0000000..8da7b84
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -0,0 +1,223 @@
+What: /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_type
+Date: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index cc68a90..372e281 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -12,8 +12,16 @@
#include <linux/err.h>
#include <linux/string.h>
+#include "ufs.h"
#include "ufs-sysfs.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,
+};
+
static const char *ufschd_uic_link_state_to_string(
enum uic_link_state state)
{
@@ -142,8 +150,123 @@ static const struct attribute_group ufs_sysfs_default_group = {
.attrs = ufs_sysfs_ufshcd_attrs,
};
+ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba,
+ enum desc_idn desc_id,
+ u8 desc_index,
+ u8 param_offset,
+ u8 *sysfs_buf,
+ u8 param_size)
+{
+ 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 -EINVAL;
+ 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;
+}
+
+#define UFS_DESC_PARAM(_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, _duname##_DESC_PARAM##_puname, \
+ buf, UFS_PARAM_##_size##_SIZE); \
+} \
+static DEVICE_ATTR_RO(_name)
+
+#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_default_group,
+ &ufs_sysfs_device_descriptor_group,
NULL,
};
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 e7621a0a..540a431 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2989,12 +2989,12 @@ EXPORT_SYMBOL(ufshcd_map_desc_id_to_length);
*
* Return 0 in case of success, non-zero otherwise
*/
-static int ufshcd_read_desc_param(struct ufs_hba *hba,
- enum desc_idn desc_id,
- int desc_index,
- u8 param_offset,
- u8 *param_read_buf,
- u8 param_size)
+int ufshcd_read_desc_param(struct ufs_hba *hba,
+ enum desc_idn desc_id,
+ int desc_index,
+ u8 param_offset,
+ u8 *param_read_buf,
+ u8 param_size)
{
int ret;
u8 *desc_buf;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 53e2779..38c307d 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -841,6 +841,12 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
}
/* Expose Query-Request API */
+int ufshcd_read_desc_param(struct ufs_hba *hba,
+ enum desc_idn desc_id,
+ int desc_index,
+ u8 param_offset,
+ u8 *param_read_buf,
+ u8 param_size);
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
This patch introduces attribute group to show existing sysfs entries.
Signed-off-by: Stanislav Nijnikov <[email protected]>
---
drivers/scsi/ufs/Makefile | 3 +-
drivers/scsi/ufs/ufs-sysfs.c | 164 +++++++++++++++++++++++++++++++++++++++++++
drivers/scsi/ufs/ufs-sysfs.h | 22 ++++++
drivers/scsi/ufs/ufshcd.c | 156 ++--------------------------------------
drivers/scsi/ufs/ufshcd.h | 2 +
5 files changed, 194 insertions(+), 153 deletions(-)
create mode 100644 drivers/scsi/ufs/ufs-sysfs.c
create mode 100644 drivers/scsi/ufs/ufs-sysfs.h
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..cc68a90
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -0,0 +1,164 @@
+//SPDX-License-Identifier: GPL-2.0-only
+//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.
+
+#include <linux/err.h>
+#include <linux/string.h>
+
+#include "ufs-sysfs.h"
+
+static const char *ufschd_uic_link_state_to_string(
+ enum uic_link_state state)
+{
+ switch (state) {
+ case UIC_LINK_OFF_STATE: return "OFF";
+ case UIC_LINK_ACTIVE_STATE: return "ACTIVE";
+ case UIC_LINK_HIBERN8_STATE: return "HIBERN8";
+ default: return "UNKNOWN";
+ }
+}
+
+static const char *ufschd_ufs_dev_pwr_mode_to_string(
+ enum ufs_dev_pwr_mode state)
+{
+ switch (state) {
+ case UFS_ACTIVE_PWR_MODE: return "ACTIVE";
+ case UFS_SLEEP_PWR_MODE: return "SLEEP";
+ case UFS_POWERDOWN_PWR_MODE: return "POWERDOWN";
+ default: return "UNKNOWN";
+ }
+}
+
+static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count,
+ bool rpm)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ unsigned long flags, value;
+
+ if (kstrtoul(buf, 0, &value))
+ return -EINVAL;
+
+ if (value >= UFS_PM_LVL_MAX)
+ return -EINVAL;
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ if (rpm)
+ hba->rpm_lvl = value;
+ else
+ hba->spm_lvl = value;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ return count;
+}
+
+static ssize_t rpm_lvl_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ int curr_len;
+ u8 lvl;
+
+ curr_len = snprintf(buf, PAGE_SIZE,
+ "\nCurrent Runtime PM level [%d] => dev_state [%s] link_state [%s]\n",
+ hba->rpm_lvl,
+ ufschd_ufs_dev_pwr_mode_to_string(
+ ufs_pm_lvl_states[hba->rpm_lvl].dev_state),
+ ufschd_uic_link_state_to_string(
+ ufs_pm_lvl_states[hba->rpm_lvl].link_state));
+
+ curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
+ "\nAll available Runtime PM levels info:\n");
+ for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
+ curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
+ "\tRuntime PM level [%d] => dev_state [%s] link_state [%s]\n",
+ lvl,
+ ufschd_ufs_dev_pwr_mode_to_string(
+ ufs_pm_lvl_states[lvl].dev_state),
+ ufschd_uic_link_state_to_string(
+ ufs_pm_lvl_states[lvl].link_state));
+
+ return curr_len;
+}
+
+static ssize_t rpm_lvl_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, true);
+}
+
+static ssize_t spm_lvl_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ int curr_len;
+ u8 lvl;
+
+ curr_len = snprintf(buf, PAGE_SIZE,
+ "\nCurrent System PM level [%d] => dev_state [%s] link_state [%s]\n",
+ hba->spm_lvl,
+ ufschd_ufs_dev_pwr_mode_to_string(
+ ufs_pm_lvl_states[hba->spm_lvl].dev_state),
+ ufschd_uic_link_state_to_string(
+ ufs_pm_lvl_states[hba->spm_lvl].link_state));
+
+ curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
+ "\nAll available System PM levels info:\n");
+ for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
+ curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
+ "\tSystem PM level [%d] => dev_state [%s] link_state [%s]\n",
+ lvl,
+ ufschd_ufs_dev_pwr_mode_to_string(
+ ufs_pm_lvl_states[lvl].dev_state),
+ ufschd_uic_link_state_to_string(
+ ufs_pm_lvl_states[lvl].link_state));
+
+ return curr_len;
+}
+
+static ssize_t spm_lvl_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, false);
+}
+
+static DEVICE_ATTR_RW(rpm_lvl);
+static DEVICE_ATTR_RW(spm_lvl);
+
+static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
+ &dev_attr_rpm_lvl.attr,
+ &dev_attr_spm_lvl.attr,
+ NULL
+};
+
+static const struct attribute_group ufs_sysfs_default_group = {
+ .attrs = ufs_sysfs_ufshcd_attrs,
+};
+
+static const struct attribute_group *ufs_sysfs_groups[] = {
+ &ufs_sysfs_default_group,
+ NULL,
+};
+
+void ufs_sysfs_add_nodes(struct device *dev)
+{
+ int ret;
+
+ ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_groups);
+ if (ret)
+ dev_err(dev,
+ "%s: sysfs groups creation failed (err = %d)\n",
+ __func__, ret);
+}
+
+void ufs_sysfs_remove_nodes(struct device *dev)
+{
+ sysfs_remove_groups(&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..c53c039
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-sysfs.h
@@ -0,0 +1,22 @@
+/*SPDX-License-Identifier: GPL-2.0-only
+ *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.
+ */
+
+#ifndef __UFS_SYSFS_H__
+#define __UFS_SYSFS_H__
+
+#include <linux/sysfs.h>
+
+#include "ufshcd.h"
+
+void ufs_sysfs_add_nodes(struct device *dev);
+void ufs_sysfs_remove_nodes(struct device *dev);
+#endif
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index a355d98..e7621a0a 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>
@@ -150,7 +151,7 @@ enum {
#define ufshcd_is_ufs_dev_poweroff(h) \
((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
-static struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
+struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
{UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE},
{UFS_ACTIVE_PWR_MODE, UIC_LINK_HIBERN8_STATE},
{UFS_SLEEP_PWR_MODE, UIC_LINK_ACTIVE_STATE},
@@ -813,28 +814,6 @@ static inline bool ufshcd_is_hba_active(struct ufs_hba *hba)
? false : true;
}
-static const char *ufschd_uic_link_state_to_string(
- enum uic_link_state state)
-{
- switch (state) {
- case UIC_LINK_OFF_STATE: return "OFF";
- case UIC_LINK_ACTIVE_STATE: return "ACTIVE";
- case UIC_LINK_HIBERN8_STATE: return "HIBERN8";
- default: return "UNKNOWN";
- }
-}
-
-static const char *ufschd_ufs_dev_pwr_mode_to_string(
- enum ufs_dev_pwr_mode state)
-{
- switch (state) {
- case UFS_ACTIVE_PWR_MODE: return "ACTIVE";
- case UFS_SLEEP_PWR_MODE: return "SLEEP";
- case UFS_POWERDOWN_PWR_MODE: return "POWERDOWN";
- default: return "UNKNOWN";
- }
-}
-
u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba)
{
/* HCI version 1.0 and 1.1 supports UniPro 1.41 */
@@ -7585,133 +7564,6 @@ int ufshcd_runtime_idle(struct ufs_hba *hba)
}
EXPORT_SYMBOL(ufshcd_runtime_idle);
-static inline ssize_t ufshcd_pm_lvl_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count,
- bool rpm)
-{
- struct ufs_hba *hba = dev_get_drvdata(dev);
- unsigned long flags, value;
-
- if (kstrtoul(buf, 0, &value))
- return -EINVAL;
-
- if (value >= UFS_PM_LVL_MAX)
- return -EINVAL;
-
- spin_lock_irqsave(hba->host->host_lock, flags);
- if (rpm)
- hba->rpm_lvl = value;
- else
- hba->spm_lvl = value;
- spin_unlock_irqrestore(hba->host->host_lock, flags);
- return count;
-}
-
-static ssize_t ufshcd_rpm_lvl_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ufs_hba *hba = dev_get_drvdata(dev);
- int curr_len;
- u8 lvl;
-
- curr_len = snprintf(buf, PAGE_SIZE,
- "\nCurrent Runtime PM level [%d] => dev_state [%s] link_state [%s]\n",
- hba->rpm_lvl,
- ufschd_ufs_dev_pwr_mode_to_string(
- ufs_pm_lvl_states[hba->rpm_lvl].dev_state),
- ufschd_uic_link_state_to_string(
- ufs_pm_lvl_states[hba->rpm_lvl].link_state));
-
- curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
- "\nAll available Runtime PM levels info:\n");
- for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
- curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
- "\tRuntime PM level [%d] => dev_state [%s] link_state [%s]\n",
- lvl,
- ufschd_ufs_dev_pwr_mode_to_string(
- ufs_pm_lvl_states[lvl].dev_state),
- ufschd_uic_link_state_to_string(
- ufs_pm_lvl_states[lvl].link_state));
-
- return curr_len;
-}
-
-static ssize_t ufshcd_rpm_lvl_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- return ufshcd_pm_lvl_store(dev, attr, buf, count, true);
-}
-
-static void ufshcd_add_rpm_lvl_sysfs_nodes(struct ufs_hba *hba)
-{
- hba->rpm_lvl_attr.show = ufshcd_rpm_lvl_show;
- hba->rpm_lvl_attr.store = ufshcd_rpm_lvl_store;
- sysfs_attr_init(&hba->rpm_lvl_attr.attr);
- hba->rpm_lvl_attr.attr.name = "rpm_lvl";
- hba->rpm_lvl_attr.attr.mode = 0644;
- if (device_create_file(hba->dev, &hba->rpm_lvl_attr))
- dev_err(hba->dev, "Failed to create sysfs for rpm_lvl\n");
-}
-
-static ssize_t ufshcd_spm_lvl_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct ufs_hba *hba = dev_get_drvdata(dev);
- int curr_len;
- u8 lvl;
-
- curr_len = snprintf(buf, PAGE_SIZE,
- "\nCurrent System PM level [%d] => dev_state [%s] link_state [%s]\n",
- hba->spm_lvl,
- ufschd_ufs_dev_pwr_mode_to_string(
- ufs_pm_lvl_states[hba->spm_lvl].dev_state),
- ufschd_uic_link_state_to_string(
- ufs_pm_lvl_states[hba->spm_lvl].link_state));
-
- curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
- "\nAll available System PM levels info:\n");
- for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
- curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
- "\tSystem PM level [%d] => dev_state [%s] link_state [%s]\n",
- lvl,
- ufschd_ufs_dev_pwr_mode_to_string(
- ufs_pm_lvl_states[lvl].dev_state),
- ufschd_uic_link_state_to_string(
- ufs_pm_lvl_states[lvl].link_state));
-
- return curr_len;
-}
-
-static ssize_t ufshcd_spm_lvl_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- return ufshcd_pm_lvl_store(dev, attr, buf, count, false);
-}
-
-static void ufshcd_add_spm_lvl_sysfs_nodes(struct ufs_hba *hba)
-{
- hba->spm_lvl_attr.show = ufshcd_spm_lvl_show;
- hba->spm_lvl_attr.store = ufshcd_spm_lvl_store;
- sysfs_attr_init(&hba->spm_lvl_attr.attr);
- hba->spm_lvl_attr.attr.name = "spm_lvl";
- hba->spm_lvl_attr.attr.mode = 0644;
- if (device_create_file(hba->dev, &hba->spm_lvl_attr))
- dev_err(hba->dev, "Failed to create sysfs for spm_lvl\n");
-}
-
-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);
-}
-
-static inline void ufshcd_remove_sysfs_nodes(struct ufs_hba *hba)
-{
- device_remove_file(hba->dev, &hba->rpm_lvl_attr);
- device_remove_file(hba->dev, &hba->spm_lvl_attr);
-}
-
/**
* ufshcd_shutdown - shutdown routine
* @hba: per adapter instance
@@ -7749,7 +7601,7 @@ EXPORT_SYMBOL(ufshcd_shutdown);
*/
void ufshcd_remove(struct ufs_hba *hba)
{
- ufshcd_remove_sysfs_nodes(hba);
+ ufs_sysfs_remove_nodes(hba->dev);
scsi_remove_host(hba->host);
/* disable interrupts */
ufshcd_disable_intr(hba, hba->intr_mask);
@@ -7996,7 +7848,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
ufshcd_set_ufs_dev_active(hba);
async_schedule(ufshcd_async_scan, hba);
- ufshcd_add_sysfs_nodes(hba);
+ ufs_sysfs_add_nodes(hba->dev);
return 0;
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 1332e54..53e2779 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -985,4 +985,6 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
hba->vops->dbg_register_dump(hba);
}
+extern struct ufs_pm_lvl_states ufs_pm_lvl_states[];
+
#endif /* End of Header */
--
2.7.4
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]>
---
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 099e6fa..6ea7613 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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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: February 2018
+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 460378b..6427804 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -281,10 +281,94 @@ 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_WR_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_default_group,
&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
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]>
---
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 8da7b84..099e6fa 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: February 2018
+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: February 2018
+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 372e281..460378b 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -264,9 +264,27 @@ 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_default_group,
&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
Can you please clarify the naming, at least as far as saying scsi/ufs.
Universal Flash Storage is not the same thing as all as the Unix File
System which has been using the acronym ufs for much longer.
I saw this patchset and I was wondering what in the world does a
filesystem need with sysfs entries.
Eric
Stanislav Nijnikov <[email protected]> writes:
> 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:
> v3 -> v4
> Additional patch the introduces default attributes group for the
> existing ufs sysfs entries (rpm_lvl and spm_lvl)
> The ufs_sysfs_read_desc_param function calls to ufshcd_read_desc_param
> insted of ufshcd_query_descriptor_retry to avoid code duplication.
> The code was updated to remove the checkpatch error "ERROR: Macros
> with complex values should be enclosed in parentheses"
> Added "_" to macros parameters to remove "#undef DEVICE_CLASS"
> The legal information was updated to satisfy the SPDX requirements
> The date in Documentation/ABI/testing/sysfs-driver-ufs was updated.
>
> 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 (10):
> ufs: sysfs: attribute group for existing sysfs entries.
> 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 | 757 +++++++++++++++++++++++++++
> drivers/scsi/ufs/ufs-sysfs.h | 25 +
> drivers/scsi/ufs/ufs.h | 115 ++++-
> drivers/scsi/ufs/ufshcd.c | 218 ++------
> drivers/scsi/ufs/ufshcd.h | 34 ++
> include/scsi/scsi_host.h | 6 +
> 9 files changed, 1785 insertions(+), 191 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
On Thu, Feb 01, 2018 at 06:15:37PM +0200, Stanislav Nijnikov wrote:
> This patch introduces attribute group to show existing sysfs entries.
>
> Signed-off-by: Stanislav Nijnikov <[email protected]>
> ---
> drivers/scsi/ufs/Makefile | 3 +-
> drivers/scsi/ufs/ufs-sysfs.c | 164 +++++++++++++++++++++++++++++++++++++++++++
> drivers/scsi/ufs/ufs-sysfs.h | 22 ++++++
> drivers/scsi/ufs/ufshcd.c | 156 ++--------------------------------------
> drivers/scsi/ufs/ufshcd.h | 2 +
> 5 files changed, 194 insertions(+), 153 deletions(-)
> create mode 100644 drivers/scsi/ufs/ufs-sysfs.c
> create mode 100644 drivers/scsi/ufs/ufs-sysfs.h
>
> 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..cc68a90
> --- /dev/null
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -0,0 +1,164 @@
> +//SPDX-License-Identifier: GPL-2.0-only
> +//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.
No need to put the whole "This program" crud in the file here if you
have the SPDX line already. We are going through the kernel tree and
removing all of the 700+ different ways we have this boilerplate code in
the tree, please do not add new ones.
Also, please put a ' ' after "//", it just looks ugly like this, don't
you think so?
Please fix this for all of the files you add in this patch series.
> +#include <linux/err.h>
> +#include <linux/string.h>
> +
> +#include "ufs-sysfs.h"
> +
> +static const char *ufschd_uic_link_state_to_string(
> + enum uic_link_state state)
> +{
> + switch (state) {
> + case UIC_LINK_OFF_STATE: return "OFF";
> + case UIC_LINK_ACTIVE_STATE: return "ACTIVE";
> + case UIC_LINK_HIBERN8_STATE: return "HIBERN8";
> + default: return "UNKNOWN";
> + }
> +}
> +
> +static const char *ufschd_ufs_dev_pwr_mode_to_string(
> + enum ufs_dev_pwr_mode state)
> +{
> + switch (state) {
> + case UFS_ACTIVE_PWR_MODE: return "ACTIVE";
> + case UFS_SLEEP_PWR_MODE: return "SLEEP";
> + case UFS_POWERDOWN_PWR_MODE: return "POWERDOWN";
> + default: return "UNKNOWN";
> + }
> +}
> +
> +static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count,
> + bool rpm)
> +{
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> + unsigned long flags, value;
> +
> + if (kstrtoul(buf, 0, &value))
> + return -EINVAL;
> +
> + if (value >= UFS_PM_LVL_MAX)
> + return -EINVAL;
> +
> + spin_lock_irqsave(hba->host->host_lock, flags);
> + if (rpm)
> + hba->rpm_lvl = value;
> + else
> + hba->spm_lvl = value;
> + spin_unlock_irqrestore(hba->host->host_lock, flags);
> + return count;
> +}
> +
> +static ssize_t rpm_lvl_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> + int curr_len;
> + u8 lvl;
> +
> + curr_len = snprintf(buf, PAGE_SIZE,
> + "\nCurrent Runtime PM level [%d] => dev_state [%s] link_state [%s]\n",
> + hba->rpm_lvl,
> + ufschd_ufs_dev_pwr_mode_to_string(
> + ufs_pm_lvl_states[hba->rpm_lvl].dev_state),
> + ufschd_uic_link_state_to_string(
> + ufs_pm_lvl_states[hba->rpm_lvl].link_state));
> +
> + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> + "\nAll available Runtime PM levels info:\n");
> + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
> + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> + "\tRuntime PM level [%d] => dev_state [%s] link_state [%s]\n",
> + lvl,
> + ufschd_ufs_dev_pwr_mode_to_string(
> + ufs_pm_lvl_states[lvl].dev_state),
> + ufschd_uic_link_state_to_string(
> + ufs_pm_lvl_states[lvl].link_state));
> +
sysfs if "one value per file", not "random text that someone has to
parse per file" please.
Huge hint, if you ever care about checking the size of the sysfs buffer
you are writing into, you are doing something really really wrong.
> + return curr_len;
> +}
> +
> +static ssize_t rpm_lvl_store(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t count)
> +{
> + return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, true);
> +}
> +
> +static ssize_t spm_lvl_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct ufs_hba *hba = dev_get_drvdata(dev);
> + int curr_len;
> + u8 lvl;
> +
> + curr_len = snprintf(buf, PAGE_SIZE,
> + "\nCurrent System PM level [%d] => dev_state [%s] link_state [%s]\n",
> + hba->spm_lvl,
> + ufschd_ufs_dev_pwr_mode_to_string(
> + ufs_pm_lvl_states[hba->spm_lvl].dev_state),
> + ufschd_uic_link_state_to_string(
> + ufs_pm_lvl_states[hba->spm_lvl].link_state));
> +
> + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> + "\nAll available System PM levels info:\n");
> + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
> + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> + "\tSystem PM level [%d] => dev_state [%s] link_state [%s]\n",
> + lvl,
> + ufschd_ufs_dev_pwr_mode_to_string(
> + ufs_pm_lvl_states[lvl].dev_state),
> + ufschd_uic_link_state_to_string(
> + ufs_pm_lvl_states[lvl].link_state));
> +
Same here, this output is not ok.
> + return curr_len;
> +}
> +
> +static ssize_t spm_lvl_store(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t count)
> +{
> + return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, false);
> +}
> +
> +static DEVICE_ATTR_RW(rpm_lvl);
> +static DEVICE_ATTR_RW(spm_lvl);
> +
> +static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
> + &dev_attr_rpm_lvl.attr,
> + &dev_attr_spm_lvl.attr,
> + NULL
> +};
> +
> +static const struct attribute_group ufs_sysfs_default_group = {
> + .attrs = ufs_sysfs_ufshcd_attrs,
> +};
> +
> +static const struct attribute_group *ufs_sysfs_groups[] = {
> + &ufs_sysfs_default_group,
> + NULL,
> +};
ATTRIBUTE_GROUPS() macro?
> +void ufs_sysfs_add_nodes(struct device *dev)
> +{
> + int ret;
> +
> + ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_groups);
> + if (ret)
> + dev_err(dev,
> + "%s: sysfs groups creation failed (err = %d)\n",
> + __func__, ret);
Why not return 'ret' so you can do something with it?
thanks,
greg k-h
On Thu, Feb 01, 2018 at 06:15:38PM +0200, Stanislav Nijnikov wrote:
> +#define UFS_DESC_PARAM(_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, _duname##_DESC_PARAM##_puname, \
> + buf, UFS_PARAM_##_size##_SIZE); \
> +} \
> +static DEVICE_ATTR_RO(_name)
Nit, use tabs in your lines here to line up the trailing \
Same for other places in this patch series.
thanks,
greg k-h
On Thu, Feb 01, 2018 at 06:15:39PM +0200, Stanislav Nijnikov wrote:
> 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]>
Nit, you should not have blank lines between these two statements,
otherwise tools can get confused.
You do that in later patches as well.
thanks,
greg k-h
On Thu, Feb 01, 2018 at 06:15:46PM +0200, Stanislav Nijnikov wrote:
> +#define UFS_LUN_ATTRIBUTE(_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); \
> +} \
> +static DEVICE_ATTR_RO(_name##_attribute)
> +
> +UFS_LUN_ATTRIBUTE(dyn_cap_needed, _DYN_CAP_NEEDED);
Why create a macro when you only have one instance of its use?
thanks,
greg k-h
On Thu, 2018-02-01 at 18:15 +0200, Stanislav Nijnikov wrote:
> +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,
> +};
Please do not copy bad naming choices from the Windows kernel into the Linux
kernel. Using names like WORD / DWORD / QWORD is much less readable than using
the numeric constants 2, 4, 8. Hence my proposal to leave out the above enum
completely.
Thanks,
Bart.
On Thu, 2018-02-01 at 18:15 +0200, Stanislav Nijnikov wrote:
> +ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba,
> + enum desc_idn desc_id,
> + u8 desc_index,
> + u8 param_offset,
> + u8 *sysfs_buf,
> + u8 param_size)
> +{
> + 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 -EINVAL;
> + 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;
> +}
Seeing code like this makes me wonder whether this patch series has been verified
with sparse? I think sparse will complain about all three be*_to_cpu() casts above.
Please use get_unaligned_be*() instead of open-coding these functions.
Thanks,
Bart.
On Thu, 2018-02-01 at 18:15 +0200, Stanislav Nijnikov wrote:
> diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
> index cbc0fe2..69a6a1f 100644
> --- a/drivers/scsi/scsi_sysfs.c
> +++ b/drivers/scsi/scsi_sysfs.c
> @@ -1309,6 +1309,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;
> }
> @@ -1326,6 +1334,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,
Please split this patch into two patches, namely one patch that introduces
the sdev_groups attribute in the SCSI core and a second patch that does not
modify the SCSI core but only the UFS driver. That will make these changes
easier to review.
Additionally, it seems wrong to me to cast the third argument of
sysfs_create_groups() and sysfs_remove_groups() from a non-const to a const
pointer. Please consider to declare the sdev_groups member const and also
the corresponding data structures in the UFS driver.
Thanks,
Bart.
On Fri, Feb 02, 2018 at 12:25:46AM +0000, Bart Van Assche wrote:
> On Thu, 2018-02-01 at 18:15 +0200, Stanislav Nijnikov wrote:
> > +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,
> > +};
>
> Please do not copy bad naming choices from the Windows kernel into the Linux
> kernel. Using names like WORD / DWORD / QWORD is much less readable than using
> the numeric constants 2, 4, 8. Hence my proposal to leave out the above enum
> completely.
Are you sure those do not come from the spec itself? It's been a while
since I last read it, but for some reason I remember those types of
names being in there. But I might be confusing specs here.
thanks,
greg k-h
On Fri, 2018-02-02 at 08:17 +0100, [email protected] wrote:
> On Fri, Feb 02, 2018 at 12:25:46AM +0000, Bart Van Assche wrote:
> > On Thu, 2018-02-01 at 18:15 +0200, Stanislav Nijnikov wrote:
> > > +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,
> > > +};
> >
> > Please do not copy bad naming choices from the Windows kernel into the Linux
> > kernel. Using names like WORD / DWORD / QWORD is much less readable than using
> > the numeric constants 2, 4, 8. Hence my proposal to leave out the above enum
> > completely.
>
> Are you sure those do not come from the spec itself? It's been a while
> since I last read it, but for some reason I remember those types of
> names being in there. But I might be confusing specs here.
Hello Greg,
That's a good question. However, a quick search on the Internet for the search
phrase "Universal Flash Storage" "qword" did not yield any results about UFS in
the first ten search hits. And I haven't found any references to the DWORD /
QWORD terminology in the "UNIVERSAL FLASH STORAGE HOST CONTROLLER INTERFACE
(UFSHCI), UNIFIED MEMORY EXTENSION, Version 1.1" document either. Maybe that
means that I was looking at the wrong document?
Thanks,
Bart.
> -----Original Message-----
> From: Bart Van Assche
> Sent: Friday, February 2, 2018 6:32 PM
> To: [email protected]
> Cc: [email protected]; [email protected];
> [email protected]; Alex Lemberg <[email protected]>; Stanislav
> Nijnikov <[email protected]>
> Subject: Re: [PATCH v4 02/10] ufs: sysfs: device descriptor
>
> On Fri, 2018-02-02 at 08:17 +0100, [email protected] wrote:
> > On Fri, Feb 02, 2018 at 12:25:46AM +0000, Bart Van Assche wrote:
> > > On Thu, 2018-02-01 at 18:15 +0200, Stanislav Nijnikov wrote:
> > > > +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,
> > > > +};
> > >
> > > Please do not copy bad naming choices from the Windows kernel into
> > > the Linux kernel. Using names like WORD / DWORD / QWORD is much less
> > > readable than using the numeric constants 2, 4, 8. Hence my proposal
> > > to leave out the above enum completely.
> >
> > Are you sure those do not come from the spec itself? It's been a
> > while since I last read it, but for some reason I remember those types
> > of names being in there. But I might be confusing specs here.
>
> Hello Greg,
>
> That's a good question. However, a quick search on the Internet for the
> search phrase "Universal Flash Storage" "qword" did not yield any results
> about UFS in the first ten search hits. And I haven't found any references to
> the DWORD / QWORD terminology in the "UNIVERSAL FLASH STORAGE HOST
> CONTROLLER INTERFACE (UFSHCI), UNIFIED MEMORY EXTENSION, Version
> 1.1" document either. Maybe that means that I was looking at the wrong
> document?
>
> Thanks,
>
> Bart.
>
>
The UFS spec 2.1 specifies size as first letter in names of the descriptor parameters and attributes (e.g. bDeviceClass, wSpecVersion, dPSAMaxDataSize, qTotalRawDeviceCapacity, ...). But usage of the enum could be easily removed.
Regards
Stanislav
On Sun, Feb 04, 2018 at 09:03:25AM +0000, Stanislav Nijnikov wrote:
> > -----Original Message-----
> > From: Bart Van Assche
> > Sent: Friday, February 2, 2018 6:32 PM
> > To: [email protected]
> > Cc: [email protected]; [email protected];
> > [email protected]; Alex Lemberg <[email protected]>; Stanislav
> > Nijnikov <[email protected]>
> > Subject: Re: [PATCH v4 02/10] ufs: sysfs: device descriptor
> >
> > On Fri, 2018-02-02 at 08:17 +0100, [email protected] wrote:
> > > On Fri, Feb 02, 2018 at 12:25:46AM +0000, Bart Van Assche wrote:
> > > > On Thu, 2018-02-01 at 18:15 +0200, Stanislav Nijnikov wrote:
> > > > > +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,
> > > > > +};
> > > >
> > > > Please do not copy bad naming choices from the Windows kernel into
> > > > the Linux kernel. Using names like WORD / DWORD / QWORD is much less
> > > > readable than using the numeric constants 2, 4, 8. Hence my proposal
> > > > to leave out the above enum completely.
> > >
> > > Are you sure those do not come from the spec itself? It's been a
> > > while since I last read it, but for some reason I remember those types
> > > of names being in there. But I might be confusing specs here.
> >
> > Hello Greg,
> >
> > That's a good question. However, a quick search on the Internet for the
> > search phrase "Universal Flash Storage" "qword" did not yield any results
> > about UFS in the first ten search hits. And I haven't found any references to
> > the DWORD / QWORD terminology in the "UNIVERSAL FLASH STORAGE HOST
> > CONTROLLER INTERFACE (UFSHCI), UNIFIED MEMORY EXTENSION, Version
> > 1.1" document either. Maybe that means that I was looking at the wrong
> > document?
> >
> > Thanks,
> >
> > Bart.
> >
> >
> The UFS spec 2.1 specifies size as first letter in names of the descriptor parameters and attributes (e.g. bDeviceClass, wSpecVersion, dPSAMaxDataSize, qTotalRawDeviceCapacity, ...). But usage of the enum could be easily removed.
It matches the naming scheme of the spec, so in my opinion, it's fine
as-is. But as I'm not the author here, it's up to you what you want to
use, you have to maintain this, not me :)
thanks,
greg k-h
> -----Original Message-----
> From: Greg KH [mailto:[email protected]]
> Sent: Thursday, February 1, 2018 6:59 PM
> To: Stanislav Nijnikov <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; Alex Lemberg <[email protected]>
> Subject: Re: [PATCH v4 01/10] ufs: sysfs: attribute group for existing sysfs
> entries.
>
> On Thu, Feb 01, 2018 at 06:15:37PM +0200, Stanislav Nijnikov wrote:
> > This patch introduces attribute group to show existing sysfs entries.
> >
> > Signed-off-by: Stanislav Nijnikov <[email protected]>
> > ---
> > drivers/scsi/ufs/Makefile | 3 +-
> > drivers/scsi/ufs/ufs-sysfs.c | 164
> > +++++++++++++++++++++++++++++++++++++++++++
> > drivers/scsi/ufs/ufs-sysfs.h | 22 ++++++
> > drivers/scsi/ufs/ufshcd.c | 156 ++--------------------------------------
> > drivers/scsi/ufs/ufshcd.h | 2 +
> > 5 files changed, 194 insertions(+), 153 deletions(-) create mode
> > 100644 drivers/scsi/ufs/ufs-sysfs.c create mode 100644
> > drivers/scsi/ufs/ufs-sysfs.h
> >
> > 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..cc68a90
> > --- /dev/null
> > +++ b/drivers/scsi/ufs/ufs-sysfs.c
> > @@ -0,0 +1,164 @@
> > +//SPDX-License-Identifier: GPL-2.0-only //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.
>
> No need to put the whole "This program" crud in the file here if you have the
> SPDX line already. We are going through the kernel tree and removing all of
> the 700+ different ways we have this boilerplate code in the tree, please do
> not add new ones.
>
> Also, please put a ' ' after "//", it just looks ugly like this, don't you think so?
>
> Please fix this for all of the files you add in this patch series.
>
> > +#include <linux/err.h>
> > +#include <linux/string.h>
> > +
> > +#include "ufs-sysfs.h"
> > +
> > +static const char *ufschd_uic_link_state_to_string(
> > + enum uic_link_state state)
> > +{
> > + switch (state) {
> > + case UIC_LINK_OFF_STATE: return "OFF";
> > + case UIC_LINK_ACTIVE_STATE: return "ACTIVE";
> > + case UIC_LINK_HIBERN8_STATE: return "HIBERN8";
> > + default: return "UNKNOWN";
> > + }
> > +}
> > +
> > +static const char *ufschd_ufs_dev_pwr_mode_to_string(
> > + enum ufs_dev_pwr_mode state)
> > +{
> > + switch (state) {
> > + case UFS_ACTIVE_PWR_MODE: return "ACTIVE";
> > + case UFS_SLEEP_PWR_MODE: return "SLEEP";
> > + case UFS_POWERDOWN_PWR_MODE: return "POWERDOWN";
> > + default: return "UNKNOWN";
> > + }
> > +}
> > +
> > +static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
> > + struct device_attribute *attr,
> > + const char *buf, size_t count,
> > + bool rpm)
> > +{
> > + struct ufs_hba *hba = dev_get_drvdata(dev);
> > + unsigned long flags, value;
> > +
> > + if (kstrtoul(buf, 0, &value))
> > + return -EINVAL;
> > +
> > + if (value >= UFS_PM_LVL_MAX)
> > + return -EINVAL;
> > +
> > + spin_lock_irqsave(hba->host->host_lock, flags);
> > + if (rpm)
> > + hba->rpm_lvl = value;
> > + else
> > + hba->spm_lvl = value;
> > + spin_unlock_irqrestore(hba->host->host_lock, flags);
> > + return count;
> > +}
> > +
> > +static ssize_t rpm_lvl_show(struct device *dev,
> > + struct device_attribute *attr, char *buf) {
> > + struct ufs_hba *hba = dev_get_drvdata(dev);
> > + int curr_len;
> > + u8 lvl;
> > +
> > + curr_len = snprintf(buf, PAGE_SIZE,
> > + "\nCurrent Runtime PM level [%d] => dev_state
> [%s] link_state [%s]\n",
> > + hba->rpm_lvl,
> > + ufschd_ufs_dev_pwr_mode_to_string(
> > + ufs_pm_lvl_states[hba-
> >rpm_lvl].dev_state),
> > + ufschd_uic_link_state_to_string(
> > + ufs_pm_lvl_states[hba-
> >rpm_lvl].link_state));
> > +
> > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > + "\nAll available Runtime PM levels info:\n");
> > + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
> > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > + "\tRuntime PM level [%d] => dev_state
> [%s] link_state [%s]\n",
> > + lvl,
> > + ufschd_ufs_dev_pwr_mode_to_string(
> > + ufs_pm_lvl_states[lvl].dev_state),
> > + ufschd_uic_link_state_to_string(
> > + ufs_pm_lvl_states[lvl].link_state));
> > +
>
> sysfs if "one value per file", not "random text that someone has to parse per
> file" please.
>
> Huge hint, if you ever care about checking the size of the sysfs buffer you are
> writing into, you are doing something really really wrong.
>
Hi Greg
It's the existing code, added by:
commit 09690d5a6ae1b7e4cb5ac429c311b99d09352c12
Author: [email protected] <[email protected]>
Date: Thu Dec 22 18:41:00 2016 -0800
scsi: ufs: provide sysfs attribute to select the PM level
This patch provides the sysfs attribute to choose the power management
level for UFS runtime and system suspend.
Reviewed-by: Sujit Reddy Thumma <[email protected]>
Signed-off-by: Subhash Jadavani <[email protected]>
Signed-off-by: Martin K. Petersen <[email protected]>
I just moved it to an another file and changed the sysfs entries creation by
Jaegeuk Kim' request. At the moment the entry shows the PM level, the device
state, the link state and all possible PM levels. Do you want me to change it?
>
> > + return curr_len;
> > +}
> > +
> > +static ssize_t rpm_lvl_store(struct device *dev,
> > + struct device_attribute *attr, const char *buf, size_t count) {
> > + return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, true); }
> > +
> > +static ssize_t spm_lvl_show(struct device *dev,
> > + struct device_attribute *attr, char *buf) {
> > + struct ufs_hba *hba = dev_get_drvdata(dev);
> > + int curr_len;
> > + u8 lvl;
> > +
> > + curr_len = snprintf(buf, PAGE_SIZE,
> > + "\nCurrent System PM level [%d] => dev_state
> [%s] link_state [%s]\n",
> > + hba->spm_lvl,
> > + ufschd_ufs_dev_pwr_mode_to_string(
> > + ufs_pm_lvl_states[hba-
> >spm_lvl].dev_state),
> > + ufschd_uic_link_state_to_string(
> > + ufs_pm_lvl_states[hba-
> >spm_lvl].link_state));
> > +
> > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > + "\nAll available System PM levels info:\n");
> > + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
> > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > + "\tSystem PM level [%d] => dev_state
> [%s] link_state [%s]\n",
> > + lvl,
> > + ufschd_ufs_dev_pwr_mode_to_string(
> > + ufs_pm_lvl_states[lvl].dev_state),
> > + ufschd_uic_link_state_to_string(
> > + ufs_pm_lvl_states[lvl].link_state));
> > +
>
> Same here, this output is not ok.
>
Same here.
> > + return curr_len;
> > +}
> > +
> > +static ssize_t spm_lvl_store(struct device *dev,
> > + struct device_attribute *attr, const char *buf, size_t count) {
> > + return ufs_sysfs_pm_lvl_store(dev, attr, buf, count, false); }
> > +
> > +static DEVICE_ATTR_RW(rpm_lvl);
> > +static DEVICE_ATTR_RW(spm_lvl);
> > +
> > +static struct attribute *ufs_sysfs_ufshcd_attrs[] = {
> > + &dev_attr_rpm_lvl.attr,
> > + &dev_attr_spm_lvl.attr,
> > + NULL
> > +};
> > +
> > +static const struct attribute_group ufs_sysfs_default_group = {
> > + .attrs = ufs_sysfs_ufshcd_attrs,
> > +};
> > +
> > +static const struct attribute_group *ufs_sysfs_groups[] = {
> > + &ufs_sysfs_default_group,
> > + NULL,
> > +};
>
> ATTRIBUTE_GROUPS() macro?
>
> > +void ufs_sysfs_add_nodes(struct device *dev) {
> > + int ret;
> > +
> > + ret = sysfs_create_groups(&dev->kobj, ufs_sysfs_groups);
> > + if (ret)
> > + dev_err(dev,
> > + "%s: sysfs groups creation failed (err = %d)\n",
> > + __func__, ret);
>
> Why not return 'ret' so you can do something with it?
The existing in the driver functions that create the sysfs entries do nothing on
failure, just error message. So I just keep the same logic.
>
> thanks,
>
> greg k-h
Thank you.
Stanislav
On Sun, Feb 04, 2018 at 12:29:06PM +0000, Stanislav Nijnikov wrote:
> > > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > > + "\nAll available Runtime PM levels info:\n");
> > > + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
> > > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > > + "\tRuntime PM level [%d] => dev_state
> > [%s] link_state [%s]\n",
> > > + lvl,
> > > + ufschd_ufs_dev_pwr_mode_to_string(
> > > + ufs_pm_lvl_states[lvl].dev_state),
> > > + ufschd_uic_link_state_to_string(
> > > + ufs_pm_lvl_states[lvl].link_state));
> > > +
> >
> > sysfs if "one value per file", not "random text that someone has to parse per
> > file" please.
> >
> > Huge hint, if you ever care about checking the size of the sysfs buffer you are
> > writing into, you are doing something really really wrong.
> >
> Hi Greg
> It's the existing code, added by:
> commit 09690d5a6ae1b7e4cb5ac429c311b99d09352c12
> Author: [email protected] <[email protected]>
> Date: Thu Dec 22 18:41:00 2016 -0800
>
> scsi: ufs: provide sysfs attribute to select the PM level
>
> This patch provides the sysfs attribute to choose the power management
> level for UFS runtime and system suspend.
>
> Reviewed-by: Sujit Reddy Thumma <[email protected]>
> Signed-off-by: Subhash Jadavani <[email protected]>
> Signed-off-by: Martin K. Petersen <[email protected]>
>
> I just moved it to an another file and changed the sysfs entries creation by
> Jaegeuk Kim' request. At the moment the entry shows the PM level, the device
> state, the link state and all possible PM levels. Do you want me to change it?
Ah, you are just moving this code around. Ok, that's fine for this
patch, but please fix it up as part of this patch series because this
isn't an acceptable sysfs file at all. If it were documented that would
be a lot more obvious as to just how wrong it was :(
And, as it wasn't documented, you can change it as it's obvious no one
used it :)
thanks,
greg k-h
> -----Original Message-----
> From: Greg KH [mailto:[email protected]]
> Sent: Sunday, February 4, 2018 2:34 PM
> To: Stanislav Nijnikov <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; Alex Lemberg <[email protected]>
> Subject: Re: [PATCH v4 01/10] ufs: sysfs: attribute group for existing sysfs
> entries.
>
> On Sun, Feb 04, 2018 at 12:29:06PM +0000, Stanislav Nijnikov wrote:
> > > > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > > > + "\nAll available Runtime PM levels info:\n");
> > > > + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
> > > > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > > > + "\tRuntime PM level [%d] => dev_state
> > > [%s] link_state [%s]\n",
> > > > + lvl,
> > > > + ufschd_ufs_dev_pwr_mode_to_string(
> > > > + ufs_pm_lvl_states[lvl].dev_state),
> > > > + ufschd_uic_link_state_to_string(
> > > > + ufs_pm_lvl_states[lvl].link_state));
> > > > +
> > >
> > > sysfs if "one value per file", not "random text that someone has to
> > > parse per file" please.
> > >
> > > Huge hint, if you ever care about checking the size of the sysfs
> > > buffer you are writing into, you are doing something really really wrong.
> > >
> > Hi Greg
> > It's the existing code, added by:
> > commit 09690d5a6ae1b7e4cb5ac429c311b99d09352c12
> > Author: [email protected] <[email protected]>
> > Date: Thu Dec 22 18:41:00 2016 -0800
> >
> > scsi: ufs: provide sysfs attribute to select the PM level
> >
> > This patch provides the sysfs attribute to choose the power management
> > level for UFS runtime and system suspend.
> >
> > Reviewed-by: Sujit Reddy Thumma <[email protected]>
> > Signed-off-by: Subhash Jadavani <[email protected]>
> > Signed-off-by: Martin K. Petersen <[email protected]>
> >
> > I just moved it to an another file and changed the sysfs entries
> > creation by Jaegeuk Kim' request. At the moment the entry shows the PM
> > level, the device state, the link state and all possible PM levels. Do you
> want me to change it?
>
> Ah, you are just moving this code around. Ok, that's fine for this patch, but
> please fix it up as part of this patch series because this isn't an acceptable
> sysfs file at all. If it were documented that would be a lot more obvious as to
> just how wrong it was :(
>
> And, as it wasn't documented, you can change it as it's obvious no one used it
> :)
>
> thanks,
>
> greg k-h
Can I fix these entries not in this patchset? As long as I know they are used and I
would prefer that change of the existing sysfs entries behavior be related to a
separate patch.
Regards.
Stanislav.
On Sun, Feb 04, 2018 at 01:09:09PM +0000, Stanislav Nijnikov wrote:
>
>
> > -----Original Message-----
> > From: Greg KH [mailto:[email protected]]
> > Sent: Sunday, February 4, 2018 2:34 PM
> > To: Stanislav Nijnikov <[email protected]>
> > Cc: [email protected]; [email protected];
> > [email protected]; Alex Lemberg <[email protected]>
> > Subject: Re: [PATCH v4 01/10] ufs: sysfs: attribute group for existing sysfs
> > entries.
> >
> > On Sun, Feb 04, 2018 at 12:29:06PM +0000, Stanislav Nijnikov wrote:
> > > > > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > > > > + "\nAll available Runtime PM levels info:\n");
> > > > > + for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++)
> > > > > + curr_len += snprintf((buf + curr_len), (PAGE_SIZE - curr_len),
> > > > > + "\tRuntime PM level [%d] => dev_state
> > > > [%s] link_state [%s]\n",
> > > > > + lvl,
> > > > > + ufschd_ufs_dev_pwr_mode_to_string(
> > > > > + ufs_pm_lvl_states[lvl].dev_state),
> > > > > + ufschd_uic_link_state_to_string(
> > > > > + ufs_pm_lvl_states[lvl].link_state));
> > > > > +
> > > >
> > > > sysfs if "one value per file", not "random text that someone has to
> > > > parse per file" please.
> > > >
> > > > Huge hint, if you ever care about checking the size of the sysfs
> > > > buffer you are writing into, you are doing something really really wrong.
> > > >
> > > Hi Greg
> > > It's the existing code, added by:
> > > commit 09690d5a6ae1b7e4cb5ac429c311b99d09352c12
> > > Author: [email protected] <[email protected]>
> > > Date: Thu Dec 22 18:41:00 2016 -0800
> > >
> > > scsi: ufs: provide sysfs attribute to select the PM level
> > >
> > > This patch provides the sysfs attribute to choose the power management
> > > level for UFS runtime and system suspend.
> > >
> > > Reviewed-by: Sujit Reddy Thumma <[email protected]>
> > > Signed-off-by: Subhash Jadavani <[email protected]>
> > > Signed-off-by: Martin K. Petersen <[email protected]>
> > >
> > > I just moved it to an another file and changed the sysfs entries
> > > creation by Jaegeuk Kim' request. At the moment the entry shows the PM
> > > level, the device state, the link state and all possible PM levels. Do you
> > want me to change it?
> >
> > Ah, you are just moving this code around. Ok, that's fine for this patch, but
> > please fix it up as part of this patch series because this isn't an acceptable
> > sysfs file at all. If it were documented that would be a lot more obvious as to
> > just how wrong it was :(
> >
> > And, as it wasn't documented, you can change it as it's obvious no one used it
> > :)
> >
> > thanks,
> >
> > greg k-h
>
> Can I fix these entries not in this patchset? As long as I know they are used and I
> would prefer that change of the existing sysfs entries behavior be related to a
> separate patch.
Ok, but it's nice to at least hope that someone will fix it up soon :)
thanks,
greg k-h