Re: [PATCH] scsi: ufs: Make sysfs flags writable

From: Adrian Hunter
Date: Wed Aug 29 2018 - 07:51:49 EST


On 21/08/18 00:34, Evan Green wrote:
> This change makes the UFS controller's sysfs flags writable. This
> will enable users to provision unprovisioned devices, and experiment
> with device features.
>
> Signed-off-by: Evan Green <evgreen@xxxxxxxxxxxx>

Seems like a good idea:

Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>

> ---
> This is a follow-on patch to another patch [1] that makes the UFS attributes
> writable.
>
> [1] https://lore.kernel.org/patchwork/patch/972959/
>
> Documentation/ABI/testing/sysfs-driver-ufs | 18 +++++++---
> drivers/scsi/ufs/ufs-sysfs.c | 54 +++++++++++++++++++++++++-----
> 2 files changed, 58 insertions(+), 14 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
> index 016724ec26d5..6df8ccbc94f3 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -619,7 +619,6 @@ Date: February 2018
> Contact: Stanislav Nijnikov <stanislav.nijnikov@xxxxxxx>
> 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
> @@ -627,7 +626,8 @@ Contact: Stanislav Nijnikov <stanislav.nijnikov@xxxxxxx>
> 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.
> + Warning: This flag can only be written one time within the
> + lifetime of the device. Once set, it cannot be unset.
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/power_on_wpe
> Date: February 2018
> @@ -636,7 +636,7 @@ 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.
> + Once set, this flag cannot be cleared without a device reset.
>
> What: /sys/bus/platform/drivers/ufshcd/*/flags/bkops_enable
> Date: February 2018
> @@ -644,7 +644,6 @@ Contact: Stanislav Nijnikov <stanislav.nijnikov@xxxxxxx>
> 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
> @@ -654,13 +653,22 @@ Description: This file shows whether the device life span mode is enabled.
> UFS specifications 2.1.
> The file is read only.
>
> +What: /sys/bus/platform/drivers/ufshcd/*/flags/purge_enable
> +Date: August 2018
> +Contact: Stanislav Nijnikov <stanislav.nijnikov@xxxxxxx>
> +Description: This file shall only be set when the command queue of all
> + logical units are empty and purge status is idle. This flag is
> + automatically cleared by the UFS device when the operation
> + completes or an error occurs. This flag is write-only, it
> + cannot be read. Complete information about the flag can be
> + found in the UFS specification 2.20A.
> +
> What: /sys/bus/platform/drivers/ufshcd/*/flags/phy_resource_removal
> Date: February 2018
> Contact: Stanislav Nijnikov <stanislav.nijnikov@xxxxxxx>
> 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
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> index 8d9332bb7d0c..2da927f4b7ff 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -616,7 +616,7 @@ static const struct attribute_group ufs_sysfs_string_descriptors_group = {
> .attrs = ufs_sysfs_string_descriptors,
> };
>
> -#define UFS_FLAG(_name, _uname) \
> +#define UFS_FLAG_SHOW(_name, _uname) \
> static ssize_t _name##_show(struct device *dev, \
> struct device_attribute *attr, char *buf) \
> { \
> @@ -626,17 +626,52 @@ static ssize_t _name##_show(struct device *dev, \
> QUERY_FLAG_IDN##_uname, &flag)) \
> return -EINVAL; \
> return sprintf(buf, "%s\n", flag ? "true" : "false"); \
> +}
> +
> +#define UFS_FLAG_STORE(_name, _uname) \
> +static ssize_t _name##_store(struct device *dev, \
> + struct device_attribute *attr, const char *buf, \
> + size_t count) \
> +{ \
> + bool flag; \
> + struct ufs_hba *hba = dev_get_drvdata(dev); \
> + enum query_opcode op; \
> + if (kstrtobool(buf, &flag)) \
> + return -EINVAL; \
> + op = flag ? UPIU_QUERY_OPCODE_SET_FLAG : \
> + UPIU_QUERY_OPCODE_CLEAR_FLAG; \
> + if (ufshcd_query_flag(hba, op, QUERY_FLAG_IDN##_uname, NULL)) \
> + return -EINVAL; \
> + return count; \
> } \
> +
> +#define UFS_FLAG_RO(_name, _uname) \
> +UFS_FLAG_SHOW(_name, _uname) \
> static DEVICE_ATTR_RO(_name)
>
> -UFS_FLAG(device_init, _FDEVICEINIT);
> -UFS_FLAG(permanent_wpe, _PERMANENT_WPE);
> -UFS_FLAG(power_on_wpe, _PWR_ON_WPE);
> -UFS_FLAG(bkops_enable, _BKOPS_EN);
> -UFS_FLAG(life_span_mode_enable, _LIFE_SPAN_MODE_ENABLE);
> -UFS_FLAG(phy_resource_removal, _FPHYRESOURCEREMOVAL);
> -UFS_FLAG(busy_rtc, _BUSY_RTC);
> -UFS_FLAG(disable_fw_update, _PERMANENTLY_DISABLE_FW_UPDATE);
> +#define UFS_FLAG_WO(_name, _uname) \
> +UFS_FLAG_STORE(_name, _uname) \
> +static ssize_t _name##_show(struct device *dev, \
> + struct device_attribute *attr, char *buf) \
> +{ \
> + return -EOPNOTSUPP; \
> +} \
> +static DEVICE_ATTR_RW(_name)
> +
> +#define UFS_FLAG_RW(_name, _uname) \
> +UFS_FLAG_SHOW(_name, _uname) \
> +UFS_FLAG_STORE(_name, _uname) \
> +static DEVICE_ATTR_RW(_name)
> +
> +UFS_FLAG_RW(device_init, _FDEVICEINIT);
> +UFS_FLAG_RW(permanent_wpe, _PERMANENT_WPE);
> +UFS_FLAG_RW(power_on_wpe, _PWR_ON_WPE);
> +UFS_FLAG_RW(bkops_enable, _BKOPS_EN);
> +UFS_FLAG_RO(life_span_mode_enable, _LIFE_SPAN_MODE_ENABLE);
> +UFS_FLAG_WO(purge_enable, _PURGE_ENABLE);
> +UFS_FLAG_RW(phy_resource_removal, _FPHYRESOURCEREMOVAL);
> +UFS_FLAG_RO(busy_rtc, _BUSY_RTC);
> +UFS_FLAG_RO(disable_fw_update, _PERMANENTLY_DISABLE_FW_UPDATE);
>
> static struct attribute *ufs_sysfs_device_flags[] = {
> &dev_attr_device_init.attr,
> @@ -644,6 +679,7 @@ static struct attribute *ufs_sysfs_device_flags[] = {
> &dev_attr_power_on_wpe.attr,
> &dev_attr_bkops_enable.attr,
> &dev_attr_life_span_mode_enable.attr,
> + &dev_attr_purge_enable.attr,
> &dev_attr_phy_resource_removal.attr,
> &dev_attr_busy_rtc.attr,
> &dev_attr_disable_fw_update.attr,
>