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 3fd29e0..122c119 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1580,6 +1580,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)
{
@@ -6532,6 +6657,9 @@ static int ufshcd_do_config_device(struct ufs_hba *hba)
pt = pt + 3; // 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
Hi Evan,
I am working on upstreaming runtime UFS provisioning patches and have posted
my latest (V1) patches for review.
I have noticed that you are also working on the same and would appreciate if
you could also review my patches.
I believe it will save us all some time and duplicate effort. Let me know if
you have any concern or comments on this.
Thanks,
Sayali
-----Original Message-----
From: Sayali Lokhande [mailto:[email protected]]
Sent: Friday, June 01, 2018 4:13 PM
To: [email protected]; [email protected];
[email protected]; [email protected]; [email protected];
[email protected]; [email protected];
[email protected]; [email protected]
Cc: [email protected]; Sayali Lokhande <[email protected]>;
Stanislav Nijnikov <[email protected]>; Greg Kroah-Hartman
<[email protected]>; Adrian Hunter <[email protected]>; open
list <[email protected]>
Subject: [PATCH V1 3/3] scsi: ufs: Add sysfs support for ufs provision
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
3fd29e0..122c119 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1580,6 +1580,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) { @@ -6532,6
+6657,9 @@ static int ufshcd_do_config_device(struct ufs_hba *hba)
pt = pt + 3; // 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 1, 2018 at 3:49 AM sayali <[email protected]> wrote:
>
> Hi Evan,
>
> I am working on upstreaming runtime UFS provisioning patches and have posted
> my latest (V1) patches for review.
> I have noticed that you are also working on the same and would appreciate if
> you could also review my patches.
> I believe it will save us all some time and duplicate effort. Let me know if
> you have any concern or comments on this.
>
> Thanks,
> Sayali
>
Hi Sayali,
I am currently travelling for work, but will make an effort to review
your patches soon. It looks like we did a bit of duplicate work. Maybe
the maintainers or community at large could let us know which approach
they prefer, or if they want both.
-Evan
On Tue, Jun 05, 2018 at 08:16:50AM +0000, Stanislav Nijnikov wrote:
> Hi Sayali,
>
> I think that passing an array of values in a string is not proper way
> to work with a sysfs entry. There are binary attributes to do such
> things.
No, don't do that, sysfs is for "one value per file", and binary
attributes are for "hardware value pass-through" type stuff. Unless
this is "raw" data straight from the hardware, binary does not work, and
neither does a normal sysfs file either.
So this needs to be reworked please.
thanks,
greg k-h
Hi Greg / Stanislav,
Thank you for your comments.
Updated my comments inline. Please check.
Thanks,
Sayali
-----Original Message-----
From: Greg Kroah-Hartman [mailto:[email protected]]
Sent: Tuesday, June 05, 2018 2:12 PM
To: Stanislav Nijnikov <[email protected]>
Cc: Sayali Lokhande <[email protected]>; [email protected];
[email protected]; [email protected]; [email protected];
[email protected]; [email protected]; [email protected];
[email protected]; [email protected]; Bart Van Assche
<[email protected]>; [email protected]; Adrian Hunter
<[email protected]>; open list <[email protected]>
Subject: Re: [PATCH V1 3/3] scsi: ufs: Add sysfs support for ufs provision
On Tue, Jun 05, 2018 at 08:16:50AM +0000, Stanislav Nijnikov wrote:
> Hi Sayali,
>
> I think that passing an array of values in a string is not proper way
> to work with a sysfs entry. There are binary attributes to do such
> things.
No, don't do that, sysfs is for "one value per file", and binary attributes
are for "hardware value pass-through" type stuff. Unless this is "raw" data
straight from the hardware, binary does not work, and neither does a normal
sysfs file either.
So this needs to be reworked please.
[Sayali] As per Documentation/filesystems/sysfs.txt :
"Attributes should be ASCII text files, preferably with only one
value per file. It is noted that it may not be efficient to contain only one
value per file, so it is socially acceptable to express an array of
values of the same type."
So it seems sysfs can be used to pass more than one value given that
they are of same type (which is ensured as I am passing char string).
Also I have noticed , in scsi_sysfs.c (store_scan() or scsi_scan()),
we do pass char buffer (more than one value) via sysfs .
As sysfs is already being used to read descriptors, I thought of
using sysfs as write interface for configuration descriptor.
Appreciate, if you could suggest me some other interfaces that can
be used here (allow passing more than one value) or
do you think I need to pass each configurable parameter one by one
for provisioning ?
thanks,
greg k-h