diff mbox

[v2,4/4] scsi: ufs: Enable writing config descriptor

Message ID 20180615210049.126123-5-evgreen@chromium.org (mailing list archive)
State Changes Requested
Headers show

Commit Message

Evan Green June 15, 2018, 9 p.m. UTC
This change enables writing to fields of the config descriptor
via sysfs. It can be used to provision an unprovisioned UFS
device, or reprovision an unlocked device.

Signed-off-by: Evan Green <evgreen@chromium.org>
---
Changes since v2:
        - New common _store function, since I'm using kobj_type now.
        - Tried to make the endianness more explicit as suggested by Bart.
I opted not to go as far as creating rw_desc_param{16,32} and friends,
as those would simply turn around and call the generic function, which
didn't seem all that useful.

 Documentation/ABI/testing/sysfs-driver-ufs | 17 ------
 drivers/scsi/ufs/ufs-sysfs.c               | 83 +++++++++++++++++++++++++++++-
 2 files changed, 81 insertions(+), 19 deletions(-)

Comments

kernel test robot June 15, 2018, 9:33 p.m. UTC | #1
Hi Evan,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mkp-scsi/for-next]
[also build test WARNING on next-20180615]
[cannot apply to scsi/for-next v4.17]
[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/Evan-Green/Enable-UFS-provisioning-via-Linux/20180616-050548
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next
config: x86_64-randconfig-x016-201823 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

Note: it may well be a FALSE warning. FWIW you are at least aware of it now.
http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings

All warnings (new ones prefixed by >>):

   include/linux/huge_mm.h:230:34: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/mm.h:533:24: sparse: constant 0xffffc90000000000 is so big it is unsigned long
   include/linux/mm.h:533:48: sparse: constant 0xffffc90000000000 is so big it is unsigned long
   include/linux/mm.h:624:29: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/mm.h:1098:16: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/mm.h:1796:27: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/mm.h:1888:16: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/scatterlist.h:151:25: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/scatterlist.h:236:16: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/scatterlist.h:387:16: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/scatterlist.h:387:16: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/dma-mapping.h:235:35: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/dma-mapping.h:238:33: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/highmem.h:51:16: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/blkdev.h:1721:14: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/blkdev.h:1721:14: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/blkdev.h:1723:14: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   include/linux/blkdev.h:1723:14: sparse: constant 0xffffea0000000000 is so big it is unsigned long
   drivers/scsi/ufs/ufs-sysfs.c:897:1: sparse: symbol 'dev_attr_current_power_mode' was not declared. Should it be static?
   drivers/scsi/ufs/ufs-sysfs.c:900:1: sparse: symbol 'dev_attr_bkops_status' was not declared. Should it be static?
   drivers/scsi/ufs/ufs-sysfs.c:901:1: sparse: symbol 'dev_attr_purge_status' was not declared. Should it be static?
   drivers/scsi/ufs/ufs-sysfs.c:909:1: sparse: symbol 'dev_attr_ffu_status' was not declared. Should it be static?
   drivers/scsi/ufs/ufs-sysfs.c:910:1: sparse: symbol 'dev_attr_psa_state' was not declared. Should it be static?
   drivers/scsi/ufs/ufs-sysfs.c:911:1: sparse: symbol 'dev_attr_psa_data_size' was not declared. Should it be static?
   drivers/scsi/ufs/ufs-sysfs.c: In function 'ufs_cfg_attr_store':
>> drivers/scsi/ufs/ufs-sysfs.c:296:6: warning: 'valueptr' may be used uninitialized in this function [-Wmaybe-uninitialized]
     ret = ufshcd_rw_desc_param(hba, UPIU_QUERY_OPCODE_WRITE_DESC, desc_id,
     ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        desc_index, param_offset,
        ~~~~~~~~~~~~~~~~~~~~~~~~~
        valueptr, width);
        ~~~~~~~~~~~~~~~~
   drivers/scsi/ufs/ufs-sysfs.c:269:6: note: 'valueptr' was declared here
     u8 *valueptr;
         ^~~~~~~~

vim +/valueptr +296 drivers/scsi/ufs/ufs-sysfs.c

   254	
   255	static ssize_t ufs_sysfs_write_desc_param(struct ufs_hba *hba,
   256					  enum desc_idn desc_id,
   257					  u8 desc_index,
   258					  u8 param_offset,
   259					  const char *buf,
   260					  ssize_t buf_size,
   261					  u8 width)
   262	{
   263		int ret;
   264		unsigned long long value;
   265		u8 value8;
   266		__be16 value16;
   267		__be32 value32;
   268		__be64 value64;
   269		u8 *valueptr;
   270	
   271		if (kstrtoull(buf, 0, &value))
   272			return -EINVAL;
   273	
   274		switch (width) {
   275		case 1:
   276			value8 = (u8)value;
   277			valueptr = &value8;
   278			break;
   279	
   280		case 2:
   281			value16 = cpu_to_be16(value);
   282			valueptr = (u8 *)&value16;
   283			break;
   284	
   285		case 4:
   286			value32 = cpu_to_be32(value);
   287			valueptr = (u8 *)&value32;
   288			break;
   289	
   290		case 8:
   291			value64 = cpu_to_be64(value);
   292			valueptr = (u8 *)&value64;
   293			break;
   294		}
   295	
 > 296		ret = ufshcd_rw_desc_param(hba, UPIU_QUERY_OPCODE_WRITE_DESC, desc_id,
   297					desc_index, param_offset,
   298					valueptr, width);
   299		if (ret)
   300			return -EINVAL;
   301	
   302		return buf_size;
   303	}
   304	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index d7477fffe0d1..fef594d912de 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -244,7 +244,6 @@  Description:	This file shows whether or not the UFS boot feature is enabled.
 		This is one of the UFS configuration descriptor parameters.
 		More information about the descriptor can be found in the UFS
 		2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/descriptor_access_enable
 Date:		May 2018
@@ -254,7 +253,6 @@  Description:	This file shows whether or not access will be permitted to the
 		boot sequence. This is one of the UFS configuration descriptor
 		parameters. More information about the descriptor can be found
 		in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/high_priority_lun
 Date:		May 2018
@@ -263,7 +261,6 @@  Description:	This file shows the identifier of the high priority logical
 		unit. This is one of the UFS configuration descriptor
 		parameters. More information about the descriptor can be found
 		in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/init_active_icc_level
 Date:		May 2018
@@ -272,7 +269,6 @@  Description:	This file shows the ICC level in active mode after device
 		initialization or hardware reset. This is one of the UFS
 		configuration descriptor parameters. More information about the
 		descriptor can be found in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/initial_power_mode
 Date:		May 2018
@@ -281,7 +277,6 @@  Description:	This file shows the power mode after device initialization or
 		hardware reset. This is one of the UFS configuration descriptor
 		parameters. More information about the descriptor can be found
 		in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/number_of_luns
 Date:		May 2018
@@ -290,7 +285,6 @@  Description:	This file shows the number of logical units that the device will
 		support. This is one of the UFS configuration descriptor
 		parameters. More information about the descriptor can be found
 		in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/periodic_rtc_update
 Date:		May 2018
@@ -299,7 +293,6 @@  Description:	This file shows the frequency and method of real time clock
 		updates. This is one of the UFS configuration descriptor
 		parameters. More information about the descriptor can be found
 		in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/secure_removal_type
 Date:		May 2018
@@ -308,7 +301,6 @@  Description:	This file shows the secure removal type of the UFS device. This
 		is one of the UFS configuration descriptor parameters. More
 		information about the descriptor can be found in the UFS 2.1
 		specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/unit*/allocation_units
 Date:		May 2018
@@ -317,7 +309,6 @@  Description:	This file shows the number of allocation units assigned to the
 		particular logical unit. This is one of the UFS configuration
 		unit descriptor parameters. More information about the
 		descriptor can be found in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/unit*/boot_lun_id
 Date:		May 2018
@@ -327,7 +318,6 @@  Description:	This file shows the boot LUN ID for this particular logical
 		This is one of the UFS configuration unit descriptor parameters.
 		More information about the descriptor can be found in the UFS
 		2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/unit*/context_capabilities
 Date:		May 2018
@@ -336,7 +326,6 @@  Description:	This file shows the context capabilities for the particular
 		logical unit. This is one of the UFS configuration unit
 		descriptor parameters. More information about the descriptor
 		can be found in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/unit*/data_reliability
 Date:		May 2018
@@ -345,7 +334,6 @@  Description:	This file shows the data reliability for the particular logical
 		unit. This is one of the UFS configuration unit descriptor
 		parameters. More information about the descriptor can be found
 		in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/unit*/logical_block_size
 Date:		May 2018
@@ -354,7 +342,6 @@  Description:	This file shows the logical block size for the particular
 		logical unit as a power of two. This is one of the UFS
 		configuration unit descriptor parameters. More information
 		about the descriptor can be found in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/unit*/lu_enable
 Date:		May 2018
@@ -363,7 +350,6 @@  Description:	This file shows whether or not the particular logical unit is
 		enabled. This is one of the UFS configuration unit descriptor
 		parameters. More information about the descriptor can be found
 		in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/unit*/lu_write_protect
 Date:		May 2018
@@ -372,7 +358,6 @@  Description:	This file shows the write protect status for the particular
 		logical unit. This is one of the UFS configuration unit
 		descriptor parameters. More information about the descriptor
 		can be found in the UFS 2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/unit*/memory_type
 Date:		May 2018
@@ -381,7 +366,6 @@  Description:	This file shows the memory type for the particular logical unit.
 		This is one of the UFS configuration unit descriptor parameters.
 		More information about the descriptor can be found in the UFS
 		2.1 specification.
-		The file is read only.
 
 What:		/sys/bus/platform/drivers/ufshcd/*/config_descriptor/unit*/provisioning_type
 Date:		May 2018
@@ -390,7 +374,6 @@  Description:	This file shows the provisioning type information for the
 		particular logical unit. This is one of the UFS configuration
 		uint descriptor parameters. More information about the
 		descriptor can be found in the UFS 2.1 specification.
-		The file is read only.
 
 
 What:		/sys/bus/platform/drivers/ufshcd/*/interconnect_descriptor/unipro_version
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index d0365e8bf839..9e6e592280bb 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -252,6 +252,56 @@  static ssize_t ufs_sysfs_read_desc_param(struct ufs_hba *hba,
 	return ret;
 }
 
+static ssize_t ufs_sysfs_write_desc_param(struct ufs_hba *hba,
+				  enum desc_idn desc_id,
+				  u8 desc_index,
+				  u8 param_offset,
+				  const char *buf,
+				  ssize_t buf_size,
+				  u8 width)
+{
+	int ret;
+	unsigned long long value;
+	u8 value8;
+	__be16 value16;
+	__be32 value32;
+	__be64 value64;
+	u8 *valueptr;
+
+	if (kstrtoull(buf, 0, &value))
+		return -EINVAL;
+
+	switch (width) {
+	case 1:
+		value8 = (u8)value;
+		valueptr = &value8;
+		break;
+
+	case 2:
+		value16 = cpu_to_be16(value);
+		valueptr = (u8 *)&value16;
+		break;
+
+	case 4:
+		value32 = cpu_to_be32(value);
+		valueptr = (u8 *)&value32;
+		break;
+
+	case 8:
+		value64 = cpu_to_be64(value);
+		valueptr = (u8 *)&value64;
+		break;
+	}
+
+	ret = ufshcd_rw_desc_param(hba, UPIU_QUERY_OPCODE_WRITE_DESC, desc_id,
+				desc_index, param_offset,
+				valueptr, width);
+	if (ret)
+		return -EINVAL;
+
+	return buf_size;
+}
+
 #define UFS_DESC_PARAM(_name, _puname, _duname, _size)			\
 static ssize_t _name##_show(struct device *dev,				\
 	struct device_attribute *attr, char *buf)			\
@@ -346,7 +396,7 @@  struct ufs_config_desc_attr {
 #define UFS_CONFIG_DESC_PARAM(_name, _uname, _size)			\
 static struct ufs_config_desc_attr ufs_cfg_attr_##_name = {		\
 	.attr = {.name = __stringify(_name),				\
-		 .mode = VERIFY_OCTAL_PERMISSIONS(0444) }, \
+		 .mode = VERIFY_OCTAL_PERMISSIONS(0644) }, 		\
 	.offset = CONFIGURATION_DESC_PARAM##_uname,			\
 	.size = _size							\
 }
@@ -375,7 +425,7 @@  static struct attribute *ufs_sysfs_config_descriptor[] = {
 #define UFS_CONFIG_UNIT_DESC_PARAM(_name, _uname, _size)		\
 static struct ufs_config_desc_attr ufs_cfg_unit_attr_##_name = {	\
 	.attr = {.name = __stringify(_name),				\
-		 .mode = VERIFY_OCTAL_PERMISSIONS(0444) },		\
+		 .mode = VERIFY_OCTAL_PERMISSIONS(0644) },		\
 	.offset = CONFIGURATION_UNIT_DESC_PARAM##_uname,		\
 	.size = _size							\
 }
@@ -430,8 +480,37 @@  static ssize_t ufs_cfg_attr_show(struct kobject *kobj, struct attribute *attr,
 					 offset, buf, cfg_attr->size);
 }
 
+static ssize_t ufs_cfg_attr_store(struct kobject *kobj, struct attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct ufs_config_desc_attr *cfg_attr = to_ufs_cfg_desc_attr(attr);
+	struct ufs_cfg_object *cfg_obj = to_ufs_cfg_obj(kobj);
+	u8 offset = cfg_attr->offset;
+	struct device *dev;
+	struct ufs_hba *hba;
+
+	/*
+	 * For unit config descriptors, add the unit's offset and get the
+	 * device parent two up.
+	 */
+	if (cfg_obj->index >= 0) {
+		offset += CONFIGURATION_DESC_PARAM_UNIT0 +
+			(CONFIGURATION_UNIT_DESC_SIZE * cfg_obj->index);
+
+		dev = kobj_to_dev(cfg_obj->kobj.parent->parent);
+
+	} else {
+		dev = kobj_to_dev(cfg_obj->kobj.parent);
+	}
+
+	hba = dev_get_drvdata(dev);
+	return ufs_sysfs_write_desc_param(hba, QUERY_DESC_IDN_CONFIGURATION, 0,
+					 offset, buf, count, cfg_attr->size);
+}
+
 static const struct sysfs_ops ufs_sysfs_config_descriptor_ops = {
 	.show	= ufs_cfg_attr_show,
+	.store	= ufs_cfg_attr_store,
 };
 
 static void ufs_cfg_kobject_release(struct kobject *kobj)