Add sysfs support to trigger ufs provisioning at runtime.
Usage : echo <desc_buf> > /sys/bus/platform/drivers/*/
config_descriptor/ufs_provision
To check provisioning status:
cat /sys/bus/platform/drivers/*/config_descriptor/ufs_provision
1- > Success (Reboot device to check updated provisioning)
Signed-off-by: Sayali Lokhande <[email protected]>
---
Documentation/ABI/testing/sysfs-driver-ufs | 16 ++++
drivers/scsi/ufs/ufs-sysfs.c | 25 ++++++
drivers/scsi/ufs/ufs.h | 2 +
drivers/scsi/ufs/ufshcd.c | 128 +++++++++++++++++++++++++++++
drivers/scsi/ufs/ufshcd.h | 5 ++
5 files changed, 176 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index 016724e..43419b5 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -883,3 +883,19 @@ Contact: Subhash Jadavani <[email protected]>
Description: This entry shows the target state of an UFS UIC link
for the chosen system power management level.
The file is read only.
+
+What: /sys/bus/platform/drivers/ufshcd/*/config_descriptor/ufs_provision
+Date: February 2018
+Contact: Sayali Lokhande <[email protected]>
+Description: This file shows the status of runtime ufs provisioning.
+ This can be used to provision ufs device if bConfigDescrLock is 0.
+ Configuration buffer needs to be written in space separated format
+ specificied as:
+ echo <bNumberLU> <bBootEnable> <bDescrAccessEn> <bInitPowerMode>
+ <bHighPriorityLUN> <bSecureRemovalType> <bInitActiveICCLevel>
+ <wPeriodicRTCUpdate> <bConfigDescrLock> <LUNum> <bLUEnable>
+ <bBootLunID> <size_in_kb> <bDataReliability> <bLUWriteProtect>
+ <bMemoryType> <bLogicalBlockSize> <bProvisioningType>
+ <wContextCapabilities> > ufs_provision
+ To check updated configuration check unit_descriptor and
+ device_descriptor sysfs fields.
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 8d9332b..8b68813 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -252,6 +252,30 @@ static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba,
return ret;
}
+static ssize_t ufs_provision_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return ufshcd_desc_config_show(dev, attr, buf);
+}
+
+static ssize_t ufs_provision_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ return ufshcd_desc_config_store(dev, attr, buf, count);
+}
+
+DEVICE_ATTR_RW(ufs_provision);
+
+static struct attribute *ufs_sysfs_config_descriptor[] = {
+ &dev_attr_ufs_provision.attr,
+ NULL,
+};
+
+static const struct attribute_group ufs_sysfs_config_descriptor_group = {
+ .name = "config_descriptor",
+ .attrs = ufs_sysfs_config_descriptor,
+};
+
#define UFS_DESC_PARAM(_name, _puname, _duname, _size) \
static ssize_t _name##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
@@ -713,6 +737,7 @@ static DEVICE_ATTR_RO(_name)
static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_default_group,
&ufs_sysfs_device_descriptor_group,
+ &ufs_sysfs_config_descriptor_group,
&ufs_sysfs_interconnect_descriptor_group,
&ufs_sysfs_geometry_descriptor_group,
&ufs_sysfs_health_descriptor_group,
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 1f99904..0b497fc 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -427,6 +427,7 @@ enum {
};
struct ufs_unit_desc {
+ u8 LUNum;
u8 bLUEnable; /* 1 for enabled LU */
u8 bBootLunID; /* 0 for using this LU for boot */
u8 bLUWriteProtect; /* 1 = power on WP, 2 = permanent WP */
@@ -451,6 +452,7 @@ struct ufs_config_descr {
u32 qVendorConfigCode; /* Vendor specific configuration code */
struct ufs_unit_desc unit[8];
u8 lun_to_grow;
+ u8 num_luns;
};
/* Task management service response */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 8975449..26b39c8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1581,6 +1581,131 @@ void ufshcd_release(struct ufs_hba *hba)
}
EXPORT_SYMBOL_GPL(ufshcd_release);
+ssize_t ufshcd_desc_config_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "provision_enabled = %d\n",
+ hba->provision_enabled);
+}
+
+ssize_t ufshcd_desc_config_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ struct ufs_config_descr *cfg = &hba->cfgs;
+ char *strbuf;
+ char *strbuf_copy;
+ int desc_buf[count];
+ int *pt;
+ char *token;
+ int i, ret;
+ int value, commit = 0;
+ int num_luns = 0;
+ int KB_per_block = 4;
+
+ /* reserve one byte for null termination */
+ strbuf = kmalloc(count + 1, GFP_KERNEL);
+ if (!strbuf)
+ return -ENOMEM;
+
+ strbuf_copy = strbuf;
+ strlcpy(strbuf, buf, count + 1);
+ memset(desc_buf, 0, count);
+
+ /* Just return if bConfigDescrLock is already set */
+ ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
+ QUERY_ATTR_IDN_CONF_DESC_LOCK, 0, 0, &cfg->bConfigDescrLock);
+ if (ret) {
+ dev_err(hba->dev, "%s: Failed reading bConfigDescrLock %d, cannot re-provision device!\n",
+ __func__, ret);
+ hba->provision_enabled = 0;
+ goto out;
+ }
+ if (cfg->bConfigDescrLock == 1) {
+ dev_err(hba->dev, "%s: bConfigDescrLock already set to %u, cannot re-provision device!\n",
+ __func__, cfg->bConfigDescrLock);
+ hba->provision_enabled = 0;
+ goto out;
+ }
+
+ for (i = 0; i < count; i++) {
+ token = strsep(&strbuf, " ");
+ if (!token && i) {
+ num_luns = desc_buf[i-1];
+ dev_dbg(hba->dev, "%s: token %s, num_luns %d\n",
+ __func__, token, num_luns);
+ if (num_luns > 8) {
+ dev_err(hba->dev, "%s: Invalid num_luns %d\n",
+ __func__, num_luns);
+ hba->provision_enabled = 0;
+ goto out;
+ }
+ break;
+ }
+
+ ret = kstrtoint(token, 0, &value);
+ if (ret) {
+ dev_err(hba->dev, "%s: kstrtoint failed %d %s\n",
+ __func__, ret, token);
+ break;
+ }
+ desc_buf[i] = value;
+ dev_dbg(hba->dev, " desc_buf[%d] 0x%x", i, desc_buf[i]);
+ }
+
+ /* Fill in the descriptors with parsed configuration data */
+ pt = desc_buf;
+ cfg->bNumberLU = *pt++;
+ cfg->bBootEnable = *pt++;
+ cfg->bDescrAccessEn = *pt++;
+ cfg->bInitPowerMode = *pt++;
+ cfg->bHighPriorityLUN = *pt++;
+ cfg->bSecureRemovalType = *pt++;
+ cfg->bInitActiveICCLevel = *pt++;
+ cfg->wPeriodicRTCUpdate = *pt++;
+ cfg->bConfigDescrLock = *pt++;
+ dev_dbg(hba->dev, "%s: %u %u %u %u %u %u %u %u %u\n", __func__,
+ cfg->bNumberLU, cfg->bBootEnable, cfg->bDescrAccessEn,
+ cfg->bInitPowerMode, cfg->bHighPriorityLUN, cfg->bSecureRemovalType,
+ cfg->bInitActiveICCLevel, cfg->wPeriodicRTCUpdate,
+ cfg->bConfigDescrLock);
+
+ for (i = 0; i < num_luns; i++) {
+ cfg->unit[i].LUNum = *pt++;
+ cfg->unit[i].bLUEnable = *pt++;
+ cfg->unit[i].bBootLunID = *pt++;
+ /* dNumAllocUnits = size_in_kb/KB_per_block */
+ cfg->unit[i].dNumAllocUnits = (u32)(*pt++ / KB_per_block);
+ cfg->unit[i].bDataReliability = *pt++;
+ cfg->unit[i].bLUWriteProtect = *pt++;
+ cfg->unit[i].bMemoryType = *pt++;
+ cfg->unit[i].bLogicalBlockSize = *pt++;
+ cfg->unit[i].bProvisioningType = *pt++;
+ cfg->unit[i].wContextCapabilities = *pt++;
+ }
+
+ cfg->lun_to_grow = *pt++;
+ commit = *pt++;
+ cfg->num_luns = *pt;
+ dev_dbg(hba->dev, "%s: lun_to_grow %u, commit %u num_luns %u\n",
+ __func__, cfg->lun_to_grow, commit, cfg->num_luns);
+ if (commit == 1) {
+ ret = ufshcd_do_config_device(hba);
+ if (!ret) {
+ hba->provision_enabled = 1;
+ dev_err(hba->dev,
+ "%s: UFS Provisioning completed,num_luns %u, reboot now !\n",
+ __func__, cfg->num_luns);
+ }
+ } else
+ dev_err(hba->dev, "%s: Invalid commit %u\n", __func__, commit);
+out:
+ kfree(strbuf_copy);
+ return count;
+}
+
static ssize_t ufshcd_clkgate_delay_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -6503,6 +6628,9 @@ static int ufshcd_do_config_device(struct ufs_hba *hba)
pt = pt + 5; // Reserved fields set to 0
}
+ for (i = 0; i < buff_len; i++)
+ dev_dbg(hba->dev, " desc_buf[%d] 0x%x", i, desc_buf[i]);
+
ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_WRITE_DESC,
QUERY_DESC_IDN_CONFIGURATION, 0, 0, desc_buf, &buff_len);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 982bfdf..1b8304f 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -651,6 +651,7 @@ struct ufs_hba {
struct ufs_pwr_mode_info max_pwr_info;
struct ufs_clk_gating clk_gating;
+ bool provision_enabled;
/* Control to enable/disable host capabilities */
u32 caps;
/* Allow dynamic clk gating */
@@ -867,6 +868,10 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index,
int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba);
+ssize_t ufshcd_desc_config_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+ssize_t ufshcd_desc_config_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
int ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
int *desc_length);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
On Fri, Jun 08, 2018 at 04:36:30PM +0530, Sayali Lokhande wrote:
> Add sysfs support to trigger ufs provisioning at runtime.
> Usage : echo <desc_buf> > /sys/bus/platform/drivers/*/
> config_descriptor/ufs_provision
> To check provisioning status:
> cat /sys/bus/platform/drivers/*/config_descriptor/ufs_provision
> 1- > Success (Reboot device to check updated provisioning)
>
> Signed-off-by: Sayali Lokhande <[email protected]>
> ---
> Documentation/ABI/testing/sysfs-driver-ufs | 16 ++++
> drivers/scsi/ufs/ufs-sysfs.c | 25 ++++++
> drivers/scsi/ufs/ufs.h | 2 +
> drivers/scsi/ufs/ufshcd.c | 128 +++++++++++++++++++++++++++++
> drivers/scsi/ufs/ufshcd.h | 5 ++
> 5 files changed, 176 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
> index 016724e..43419b5 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -883,3 +883,19 @@ Contact: Subhash Jadavani <[email protected]>
> Description: This entry shows the target state of an UFS UIC link
> for the chosen system power management level.
> The file is read only.
> +
> +What: /sys/bus/platform/drivers/ufshcd/*/config_descriptor/ufs_provision
> +Date: February 2018
> +Contact: Sayali Lokhande <[email protected]>
> +Description: This file shows the status of runtime ufs provisioning.
> + This can be used to provision ufs device if bConfigDescrLock is 0.
> + Configuration buffer needs to be written in space separated format
> + specificied as:
> + echo <bNumberLU> <bBootEnable> <bDescrAccessEn> <bInitPowerMode>
> + <bHighPriorityLUN> <bSecureRemovalType> <bInitActiveICCLevel>
> + <wPeriodicRTCUpdate> <bConfigDescrLock> <LUNum> <bLUEnable>
> + <bBootLunID> <size_in_kb> <bDataReliability> <bLUWriteProtect>
> + <bMemoryType> <bLogicalBlockSize> <bProvisioningType>
> + <wContextCapabilities> > ufs_provision
That's crazy big, please use configfs for this if you really want to
"provision" hardware with a new api. That is what configfs was created
for, do not abuse sysfs like this, it is not a "single" value.
thanks,
greg k-h
Hi Sayali,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on robh/for-next]
[also build test WARNING on v4.17 next-20180608]
[cannot apply to mkp-scsi/for-next scsi/for-next]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Sayali-Lokhande/Add-ufs-provisioning-support-in-driver/20180609-151315
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
>> drivers/scsi/ufs/ufs-sysfs.c:267:1: sparse: symbol 'dev_attr_ufs_provision' was not declared. Should it be static?
Please review and possibly fold the followup patch.
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Fixes: 2f7e32b8cdc9 ("scsi: ufs: Add sysfs support for ufs provision")
Signed-off-by: kbuild test robot <[email protected]>
---
ufs-sysfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 8b68813..36c28cc 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -264,7 +264,7 @@ static ssize_t ufs_provision_store(struct device *dev,
return ufshcd_desc_config_store(dev, attr, buf, count);
}
-DEVICE_ATTR_RW(ufs_provision);
+static DEVICE_ATTR_RW(ufs_provision);
static struct attribute *ufs_sysfs_config_descriptor[] = {
&dev_attr_ufs_provision.attr,
-----Original Message-----
From: Greg Kroah-Hartman [mailto:[email protected]]
Sent: Saturday, June 09, 2018 12:55 PM
To: Sayali Lokhande <[email protected]>
Cc: [email protected]; [email protected];
[email protected]; [email protected]; [email protected];
[email protected]; [email protected];
[email protected]; [email protected]; [email protected];
Stanislav Nijnikov <[email protected]>; Adrian Hunter
<[email protected]>; open list <[email protected]>
Subject: Re: [PATCH V2 3/3] scsi: ufs: Add sysfs support for ufs provision
On Fri, Jun 08, 2018 at 04:36:30PM +0530, Sayali Lokhande wrote:
> Add sysfs support to trigger ufs provisioning at runtime.
> Usage : echo <desc_buf> > /sys/bus/platform/drivers/*/
> config_descriptor/ufs_provision
> To check provisioning status:
> cat /sys/bus/platform/drivers/*/config_descriptor/ufs_provision
> 1- > Success (Reboot device to check updated provisioning)
>
> Signed-off-by: Sayali Lokhande <[email protected]>
> ---
> Documentation/ABI/testing/sysfs-driver-ufs | 16 ++++
> drivers/scsi/ufs/ufs-sysfs.c | 25 ++++++
> drivers/scsi/ufs/ufs.h | 2 +
> drivers/scsi/ufs/ufshcd.c | 128
+++++++++++++++++++++++++++++
> drivers/scsi/ufs/ufshcd.h | 5 ++
> 5 files changed, 176 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
> b/Documentation/ABI/testing/sysfs-driver-ufs
> index 016724e..43419b5 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -883,3 +883,19 @@ Contact: Subhash Jadavani <[email protected]>
> Description: This entry shows the target state of an UFS UIC link
> for the chosen system power management level.
> The file is read only.
> +
> +What:
/sys/bus/platform/drivers/ufshcd/*/config_descriptor/ufs_provision
> +Date: February 2018
> +Contact: Sayali Lokhande <[email protected]>
> +Description: This file shows the status of runtime ufs provisioning.
> + This can be used to provision ufs device if bConfigDescrLock
is 0.
> + Configuration buffer needs to be written in space separated
format
> + specificied as:
> + echo <bNumberLU> <bBootEnable> <bDescrAccessEn>
<bInitPowerMode>
> + <bHighPriorityLUN> <bSecureRemovalType>
<bInitActiveICCLevel>
> + <wPeriodicRTCUpdate> <bConfigDescrLock> <LUNum> <bLUEnable>
> + <bBootLunID> <size_in_kb> <bDataReliability>
<bLUWriteProtect>
> + <bMemoryType> <bLogicalBlockSize> <bProvisioningType>
> + <wContextCapabilities> > ufs_provision
That's crazy big, please use configfs for this if you really want to
"provision" hardware with a new api. That is what configfs was created for,
do not abuse sysfs like this, it is not a "single" value.
[Sayali] Sure. I will check and update my next patchset accordingly to use
configfs for provisioning at runtime.
thanks,
greg k-h