Commit 600edc66 authored by Avri Altman's avatar Avri Altman Committed by Martin K. Petersen
Browse files

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: default avatarAvri Altman <avri.altman@wdc.com>
Link: https://lore.kernel.org/r/20240530142510.734-4-avri.altman@wdc.com


Reviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent e75ff633
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -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
+72 −1
Original line number Diff line number Diff line
@@ -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);