]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: ufs: sysfs: Make max_number_of_rtt read-write
authorAvri Altman <avri.altman@wdc.com>
Thu, 30 May 2024 14:25:09 +0000 (17:25 +0300)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 31 May 2024 00:34:38 +0000 (20:34 -0400)
Given the importance of the RTT parameter, we want to be able to configure
it via sysfs. This is because UFS users should be discouraged from change
UFS device parameters without the UFSHCI driver being aware of these
changes.

Signed-off-by: Avri Altman <avri.altman@wdc.com>
Link: https://lore.kernel.org/r/20240530142510.734-4-avri.altman@wdc.com
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Documentation/ABI/testing/sysfs-driver-ufs
drivers/ufs/core/ufs-sysfs.c

index 5bf7073b4f75be33df7dc1399fd53d79d1b58aa6..fe943ce76c60e433812ab8b1b33fbc9e854e73ba 100644 (file)
@@ -920,14 +920,16 @@ Description:      This file shows whether the configuration descriptor is locked.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/max_number_of_rtt
 What:          /sys/bus/platform/devices/*.ufs/attributes/max_number_of_rtt
-Date:          February 2018
-Contact:       Stanislav Nijnikov <stanislav.nijnikov@wdc.com>
+Date:          May 2024
+Contact:       Avri Altman <avri.altman@wdc.com>
 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.
+               outstanding RTTs in device that is allowed. bMaxNumOfRTT is a
+               read-write persistent attribute and is equal to two after device
+               manufacturing. It shall not be set to a value greater than
+               bDeviceRTTCap value, and it may be set only when the hw queues are
+               empty.
 
-               The file is read only.
+               The file is read write.
 
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/exception_event_control
 What:          /sys/bus/platform/devices/*.ufs/attributes/exception_event_control
index 3d049967f6bc4a089bed6391a3c62e2c0a579fc8..e80a32421a8c4ca4fdfebd3a59fb9ba15a7f79d8 100644 (file)
@@ -1340,6 +1340,78 @@ static const struct attribute_group ufs_sysfs_flags_group = {
        .attrs = ufs_sysfs_device_flags,
 };
 
+static ssize_t max_number_of_rtt_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct ufs_hba *hba = dev_get_drvdata(dev);
+       u32 rtt;
+       int ret;
+
+       down(&hba->host_sem);
+       if (!ufshcd_is_user_access_allowed(hba)) {
+               up(&hba->host_sem);
+               return -EBUSY;
+       }
+
+       ufshcd_rpm_get_sync(hba);
+       ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+               QUERY_ATTR_IDN_MAX_NUM_OF_RTT, 0, 0, &rtt);
+       ufshcd_rpm_put_sync(hba);
+
+       if (ret)
+               goto out;
+
+       ret = sysfs_emit(buf, "0x%08X\n", rtt);
+
+out:
+       up(&hba->host_sem);
+       return ret;
+}
+
+static ssize_t max_number_of_rtt_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count)
+{
+       struct ufs_hba *hba = dev_get_drvdata(dev);
+       struct ufs_dev_info *dev_info = &hba->dev_info;
+       struct scsi_device *sdev;
+       unsigned int rtt;
+       int ret;
+
+       if (kstrtouint(buf, 0, &rtt))
+               return -EINVAL;
+
+       if (rtt > dev_info->rtt_cap) {
+               dev_err(dev, "rtt can be at most bDeviceRTTCap\n");
+               return -EINVAL;
+       }
+
+       down(&hba->host_sem);
+       if (!ufshcd_is_user_access_allowed(hba)) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       ufshcd_rpm_get_sync(hba);
+
+       shost_for_each_device(sdev, hba->host)
+               blk_mq_freeze_queue(sdev->request_queue);
+
+       ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
+               QUERY_ATTR_IDN_MAX_NUM_OF_RTT, 0, 0, &rtt);
+
+       shost_for_each_device(sdev, hba->host)
+               blk_mq_unfreeze_queue(sdev->request_queue);
+
+       ufshcd_rpm_put_sync(hba);
+
+out:
+       up(&hba->host_sem);
+       return ret < 0 ? ret : count;
+}
+
+static DEVICE_ATTR_RW(max_number_of_rtt);
+
 static inline bool ufshcd_is_wb_attrs(enum attr_idn idn)
 {
        return idn >= QUERY_ATTR_IDN_WB_FLUSH_STATUS &&
@@ -1387,7 +1459,6 @@ 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);