scsi: ufs: sysfs: Make max_number_of_rtt read-write

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>
This commit is contained in:
Avri Altman 2024-05-30 17:25:09 +03:00 committed by Martin K. Petersen
parent e75ff63300
commit 600edc6620
2 changed files with 80 additions and 7 deletions

View 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

View 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);