linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/5] scsi: ufs: support LU Dedicated buffer type for WriteBooster
@ 2020-05-01 14:38 Stanley Chu
  2020-05-01 14:38 ` [PATCH v3 1/5] scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices Stanley Chu
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Stanley Chu @ 2020-05-01 14:38 UTC (permalink / raw)
  To: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb, asutoshd
  Cc: beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng, Stanley Chu

Hi,

This patchset adds LU dedicated buffer mode support for WriteBooster.

In the meanwhile, enable WriteBooster capability on MediaTek UFS platforms.

v2 -> v3:
  - Introduce a device quirk to support WriteBooster in pre-3.1 UFS devices (Avri Altman)
  - Fix WriteBooster related sysfs nodes. Now all WriteBooster related sysfs nodes are specifically mapped to the LUN with WriteBooster enabled in LU Dedicated buffer mode (Avri Altman)

v1 -> v2:
  - Change the definition name of WriteBooster buffer mode to correspond to specification (Bean Huo)
  - Add patch #5: "scsi: ufs: cleanup WriteBooster feature"

Stanley Chu (5):
  scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices
  scsi: ufs: add "index" in parameter list of ufshcd_query_flag()
  scsi: ufs: add LU Dedicated buffer mode support for WriteBooster
  scsi: ufs-mediatek: enable WriteBooster capability
  scsi: ufs: cleanup WriteBooster feature

 drivers/scsi/ufs/ufs-mediatek.c |   3 +
 drivers/scsi/ufs/ufs-sysfs.c    |  14 ++-
 drivers/scsi/ufs/ufs.h          |   7 ++
 drivers/scsi/ufs/ufs_quirks.h   |   7 ++
 drivers/scsi/ufs/ufshcd.c       | 156 +++++++++++++++++++++-----------
 drivers/scsi/ufs/ufshcd.h       |   3 +-
 6 files changed, 135 insertions(+), 55 deletions(-)

-- 
2.18.0

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3 1/5] scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices
  2020-05-01 14:38 [PATCH v3 0/5] scsi: ufs: support LU Dedicated buffer type for WriteBooster Stanley Chu
@ 2020-05-01 14:38 ` Stanley Chu
  2020-05-02  7:47   ` Can Guo
  2020-05-01 14:38 ` [PATCH v3 2/5] scsi: ufs: add "index" in parameter list of ufshcd_query_flag() Stanley Chu
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Stanley Chu @ 2020-05-01 14:38 UTC (permalink / raw)
  To: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb, asutoshd
  Cc: beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng, Stanley Chu

WriteBooster feature can be supported by some pre-3.1 UFS devices
by upgrading firmware.

To enable WriteBooster feature in such devices, introduce a device
quirk to relax the entrance condition of ufshcd_wb_probe() to allow
host driver to check those devices' WriteBooster capability.

WriteBooster feature can be available if below all conditions are
satisfied,

1. Host enables WriteBooster capability
2. UFS 3.1 device or UFS pre-3.1 device with quirk
   UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES enabled
3. Device descriptor has dExtendedUFSFeaturesSupport field
4. WriteBooster support is specified in above field

Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
---
 drivers/scsi/ufs/ufs_quirks.h |  7 ++++
 drivers/scsi/ufs/ufshcd.c     | 66 ++++++++++++++++++++++-------------
 2 files changed, 48 insertions(+), 25 deletions(-)

diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index df7a1e6805a3..e3175a63c676 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -101,4 +101,11 @@ struct ufs_dev_fix {
  */
 #define UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME	(1 << 9)
 
+/*
+ * Some pre-3.1 UFS devices can support extended features by upgrading
+ * the firmware. Enable this quirk to make UFS core driver probe and enable
+ * supported features on such devices.
+ */
+#define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10)
+
 #endif /* UFS_QUIRKS_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 915e963398c4..c6668799d956 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -229,6 +229,8 @@ static struct ufs_dev_fix ufs_fixups[] = {
 		UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
 	UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/,
 		UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME),
+	UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMZDAR",
+		UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES),
 
 	END_FIX
 };
@@ -6800,9 +6802,19 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
 
 static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf)
 {
+	if (!ufshcd_is_wb_allowed(hba))
+		return;
+
+	if (hba->desc_size.dev_desc <= DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP)
+		goto wb_disabled;
+
 	hba->dev_info.d_ext_ufs_feature_sup =
 		get_unaligned_be32(desc_buf +
 				   DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
+
+	if (!(hba->dev_info.d_ext_ufs_feature_sup & UFS_DEV_WRITE_BOOSTER_SUP))
+		goto wb_disabled;
+
 	/*
 	 * WB may be supported but not configured while provisioning.
 	 * The spec says, in dedicated wb buffer mode,
@@ -6818,11 +6830,29 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf)
 	hba->dev_info.b_presrv_uspc_en =
 		desc_buf[DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN];
 
-	if (!((hba->dev_info.d_ext_ufs_feature_sup &
-		 UFS_DEV_WRITE_BOOSTER_SUP) &&
-		hba->dev_info.b_wb_buffer_type &&
+	if (!(hba->dev_info.b_wb_buffer_type &&
 	      hba->dev_info.d_wb_alloc_units))
-		hba->caps &= ~UFSHCD_CAP_WB_EN;
+		goto wb_disabled;
+
+	return;
+
+wb_disabled:
+	hba->caps &= ~UFSHCD_CAP_WB_EN;
+}
+
+static void ufs_fixup_device_setup(struct ufs_hba *hba)
+{
+	struct ufs_dev_fix *f;
+	struct ufs_dev_info *dev_info = &hba->dev_info;
+
+	for (f = ufs_fixups; f->quirk; f++) {
+		if ((f->wmanufacturerid == dev_info->wmanufacturerid ||
+		     f->wmanufacturerid == UFS_ANY_VENDOR) &&
+		     ((dev_info->model &&
+		       STR_PRFX_EQUAL(f->model, dev_info->model)) ||
+		      !strcmp(f->model, UFS_ANY_MODEL)))
+			hba->dev_quirks |= f->quirk;
+	}
 }
 
 static int ufs_get_device_desc(struct ufs_hba *hba)
@@ -6862,10 +6892,6 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
 
 	model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
 
-	/* Enable WB only for UFS-3.1 */
-	if (dev_info->wspecversion >= 0x310)
-		ufshcd_wb_probe(hba, desc_buf);
-
 	err = ufshcd_read_string_desc(hba, model_index,
 				      &dev_info->model, SD_ASCII_STD);
 	if (err < 0) {
@@ -6874,6 +6900,13 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
 		goto out;
 	}
 
+	ufs_fixup_device_setup(hba);
+
+	/* Enable WB only for UFS-3.1 */
+	if (dev_info->wspecversion >= 0x310 ||
+	    (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES))
+		ufshcd_wb_probe(hba, desc_buf);
+
 	/*
 	 * ufshcd_read_string_desc returns size of the string
 	 * reset the error value
@@ -6893,21 +6926,6 @@ static void ufs_put_device_desc(struct ufs_hba *hba)
 	dev_info->model = NULL;
 }
 
-static void ufs_fixup_device_setup(struct ufs_hba *hba)
-{
-	struct ufs_dev_fix *f;
-	struct ufs_dev_info *dev_info = &hba->dev_info;
-
-	for (f = ufs_fixups; f->quirk; f++) {
-		if ((f->wmanufacturerid == dev_info->wmanufacturerid ||
-		     f->wmanufacturerid == UFS_ANY_VENDOR) &&
-		     ((dev_info->model &&
-		       STR_PRFX_EQUAL(f->model, dev_info->model)) ||
-		      !strcmp(f->model, UFS_ANY_MODEL)))
-			hba->dev_quirks |= f->quirk;
-	}
-}
-
 /**
  * ufshcd_tune_pa_tactivate - Tunes PA_TActivate of local UniPro
  * @hba: per-adapter instance
@@ -7244,8 +7262,6 @@ static int ufshcd_device_params_init(struct ufs_hba *hba)
 
 	ufshcd_get_ref_clk_gating_wait(hba);
 
-	ufs_fixup_device_setup(hba);
-
 	if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
 			QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
 		hba->dev_info.f_power_on_wp_en = flag;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 2/5] scsi: ufs: add "index" in parameter list of ufshcd_query_flag()
  2020-05-01 14:38 [PATCH v3 0/5] scsi: ufs: support LU Dedicated buffer type for WriteBooster Stanley Chu
  2020-05-01 14:38 ` [PATCH v3 1/5] scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices Stanley Chu
@ 2020-05-01 14:38 ` Stanley Chu
  2020-05-02 15:23   ` Avri Altman
  2020-05-03  1:51   ` Can Guo
  2020-05-01 14:38 ` [PATCH v3 3/5] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster Stanley Chu
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 13+ messages in thread
From: Stanley Chu @ 2020-05-01 14:38 UTC (permalink / raw)
  To: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb, asutoshd
  Cc: beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng, Stanley Chu

For preparation of LU Dedicated buffer mode support on WriteBooster
feature, "index" parameter shall be added and allowed to be specified
by callers.

Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
Reviewed-by: Bean Huo <beanhuo@micron.com>
---
 drivers/scsi/ufs/ufs-sysfs.c |  2 +-
 drivers/scsi/ufs/ufshcd.c    | 28 +++++++++++++++-------------
 drivers/scsi/ufs/ufshcd.h    |  2 +-
 3 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 93484408bc40..b86b6a40d7e6 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -631,7 +631,7 @@ static ssize_t _name##_show(struct device *dev,				\
 	struct ufs_hba *hba = dev_get_drvdata(dev);			\
 	pm_runtime_get_sync(hba->dev);					\
 	ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,	\
-		QUERY_FLAG_IDN##_uname, &flag);				\
+		QUERY_FLAG_IDN##_uname, 0, &flag);			\
 	pm_runtime_put_sync(hba->dev);					\
 	if (ret)							\
 		return -EINVAL;						\
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c6668799d956..f23705379b7d 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2784,13 +2784,13 @@ static inline void ufshcd_init_query(struct ufs_hba *hba,
 }
 
 static int ufshcd_query_flag_retry(struct ufs_hba *hba,
-	enum query_opcode opcode, enum flag_idn idn, bool *flag_res)
+	enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res)
 {
 	int ret;
 	int retries;
 
 	for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) {
-		ret = ufshcd_query_flag(hba, opcode, idn, flag_res);
+		ret = ufshcd_query_flag(hba, opcode, idn, index, flag_res);
 		if (ret)
 			dev_dbg(hba->dev,
 				"%s: failed with error %d, retries %d\n",
@@ -2811,16 +2811,17 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba,
  * @hba: per-adapter instance
  * @opcode: flag query to perform
  * @idn: flag idn to access
+ * @index: flag index to access
  * @flag_res: the flag value after the query request completes
  *
  * Returns 0 for success, non-zero in case of failure
  */
 int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
-			enum flag_idn idn, bool *flag_res)
+			enum flag_idn idn, u8 index, bool *flag_res)
 {
 	struct ufs_query_req *request = NULL;
 	struct ufs_query_res *response = NULL;
-	int err, index = 0, selector = 0;
+	int err, selector = 0;
 	int timeout = QUERY_REQ_TIMEOUT;
 
 	BUG_ON(!hba);
@@ -4177,7 +4178,7 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba)
 	bool flag_res = true;
 
 	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
-		QUERY_FLAG_IDN_FDEVICEINIT, NULL);
+		QUERY_FLAG_IDN_FDEVICEINIT, 0, NULL);
 	if (err) {
 		dev_err(hba->dev,
 			"%s setting fDeviceInit flag failed with error %d\n",
@@ -4188,7 +4189,7 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba)
 	/* poll for max. 1000 iterations for fDeviceInit flag to clear */
 	for (i = 0; i < 1000 && !err && flag_res; i++)
 		err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
-			QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
+			QUERY_FLAG_IDN_FDEVICEINIT, 0, &flag_res);
 
 	if (err)
 		dev_err(hba->dev,
@@ -5003,7 +5004,7 @@ static int ufshcd_enable_auto_bkops(struct ufs_hba *hba)
 		goto out;
 
 	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
-			QUERY_FLAG_IDN_BKOPS_EN, NULL);
+			QUERY_FLAG_IDN_BKOPS_EN, 0, NULL);
 	if (err) {
 		dev_err(hba->dev, "%s: failed to enable bkops %d\n",
 				__func__, err);
@@ -5053,7 +5054,7 @@ static int ufshcd_disable_auto_bkops(struct ufs_hba *hba)
 	}
 
 	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
-			QUERY_FLAG_IDN_BKOPS_EN, NULL);
+			QUERY_FLAG_IDN_BKOPS_EN, 0, NULL);
 	if (err) {
 		dev_err(hba->dev, "%s: failed to disable bkops %d\n",
 				__func__, err);
@@ -5219,7 +5220,7 @@ static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable)
 		opcode = UPIU_QUERY_OPCODE_CLEAR_FLAG;
 
 	ret = ufshcd_query_flag_retry(hba, opcode,
-				      QUERY_FLAG_IDN_WB_EN, NULL);
+				      QUERY_FLAG_IDN_WB_EN, 0, NULL);
 	if (ret) {
 		dev_err(hba->dev, "%s write booster %s failed %d\n",
 			__func__, enable ? "enable" : "disable", ret);
@@ -5243,7 +5244,7 @@ static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set)
 		val = UPIU_QUERY_OPCODE_CLEAR_FLAG;
 
 	return ufshcd_query_flag_retry(hba, val,
-			       QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8,
+			       QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8, 0,
 				       NULL);
 }
 
@@ -5264,7 +5265,8 @@ static int ufshcd_wb_buf_flush_enable(struct ufs_hba *hba)
 		return 0;
 
 	ret = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
-				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, NULL);
+				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN,
+				      0, NULL);
 	if (ret)
 		dev_err(hba->dev, "%s WB - buf flush enable failed %d\n",
 			__func__, ret);
@@ -5283,7 +5285,7 @@ static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba)
 		return 0;
 
 	ret = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
-				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, NULL);
+				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, 0, NULL);
 	if (ret) {
 		dev_warn(hba->dev, "%s: WB - buf flush disable failed %d\n",
 			 __func__, ret);
@@ -7263,7 +7265,7 @@ static int ufshcd_device_params_init(struct ufs_hba *hba)
 	ufshcd_get_ref_clk_gating_wait(hba);
 
 	if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
-			QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
+			QUERY_FLAG_IDN_PWR_ON_WPE, 0, &flag))
 		hba->dev_info.f_power_on_wp_en = flag;
 
 	/* Probe maximum power mode co-supported by both UFS host and device */
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 056537e52c19..e555d794d441 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -946,7 +946,7 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
 int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
 		      enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
 int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
-	enum flag_idn idn, bool *flag_res);
+	enum flag_idn idn, u8 index, bool *flag_res);
 
 void ufshcd_auto_hibern8_enable(struct ufs_hba *hba);
 void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 3/5] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster
  2020-05-01 14:38 [PATCH v3 0/5] scsi: ufs: support LU Dedicated buffer type for WriteBooster Stanley Chu
  2020-05-01 14:38 ` [PATCH v3 1/5] scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices Stanley Chu
  2020-05-01 14:38 ` [PATCH v3 2/5] scsi: ufs: add "index" in parameter list of ufshcd_query_flag() Stanley Chu
@ 2020-05-01 14:38 ` Stanley Chu
  2020-05-02 15:32   ` Avri Altman
  2020-05-01 14:38 ` [PATCH v3 4/5] scsi: ufs-mediatek: enable WriteBooster capability Stanley Chu
  2020-05-01 14:38 ` [PATCH v3 5/5] scsi: ufs: cleanup WriteBooster feature Stanley Chu
  4 siblings, 1 reply; 13+ messages in thread
From: Stanley Chu @ 2020-05-01 14:38 UTC (permalink / raw)
  To: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb, asutoshd
  Cc: beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng, Stanley Chu

According to UFS specification, there are two WriteBooster mode of
operations: "LU dedicated buffer" mode and "shared buffer" mode.
In the "LU dedicated buffer" mode, the WriteBooster Buffer is
dedicated to a logical unit.

If the device supports the "LU dedicated buffer" mode, this mode is
configured by setting bWriteBoosterBufferType to 00h. The logical
unit WriteBooster Buffer size is configured by setting the
dLUNumWriteBoosterBufferAllocUnits field of the related Unit
Descriptor. Only a value greater than zero enables the WriteBooster
feature in the logical unit.

Modify ufshcd_wb_probe() as above description to support LU Dedicated
buffer mode.

Note that according to UFS 3.1 specification, the valid value of
bDeviceMaxWriteBoosterLUs parameter in Geometry Descriptor is 1,
which means at most one LUN can have WriteBooster buffer in "LU
dedicated buffer mode". Therefore this patch supports only one
LUN with WriteBooster enabled. All WriteBooster related sysfs nodes
are specifically mapped to the LUN with WriteBooster enabled in
LU Dedicated buffer mode.

Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
---
 drivers/scsi/ufs/ufs-sysfs.c | 14 ++++++++-
 drivers/scsi/ufs/ufs.h       |  7 +++++
 drivers/scsi/ufs/ufshcd.c    | 60 +++++++++++++++++++++++++++++-------
 drivers/scsi/ufs/ufshcd.h    |  1 +
 4 files changed, 70 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index b86b6a40d7e6..a162f63098e5 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -622,16 +622,28 @@ static const struct attribute_group ufs_sysfs_string_descriptors_group = {
 	.attrs = ufs_sysfs_string_descriptors,
 };
 
+static bool ufshcd_is_wb_flags(enum flag_idn idn)
+{
+	if (idn >= QUERY_FLAG_IDN_WB_EN &&
+	    idn <= QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8)
+		return true;
+	else
+		return false;
+}
+
 #define UFS_FLAG(_name, _uname)						\
 static ssize_t _name##_show(struct device *dev,				\
 	struct device_attribute *attr, char *buf)			\
 {									\
 	bool flag;							\
+	u8 index = 0;							\
 	int ret;							\
 	struct ufs_hba *hba = dev_get_drvdata(dev);			\
+	if (ufshcd_is_wb_flags(QUERY_FLAG_IDN##_uname))			\
+		index = ufshcd_wb_get_flag_index(hba);			\
 	pm_runtime_get_sync(hba->dev);					\
 	ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,	\
-		QUERY_FLAG_IDN##_uname, 0, &flag);			\
+		QUERY_FLAG_IDN##_uname, index, &flag);			\
 	pm_runtime_put_sync(hba->dev);					\
 	if (ret)							\
 		return -EINVAL;						\
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index daac5053b850..eb3d3cebc87d 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -330,6 +330,12 @@ enum health_desc_param {
 	HEALTH_DESC_PARAM_LIFE_TIME_EST_B	= 0x4,
 };
 
+/* WriteBooster buffer mode */
+enum {
+	WB_BUF_MODE_LU_DEDICATED	= 0x0,
+	WB_BUF_MODE_SHARED		= 0x1,
+};
+
 /*
  * Logical Unit Write Protect
  * 00h: LU not write protected
@@ -559,6 +565,7 @@ struct ufs_dev_info {
 	bool is_lu_power_on_wp;
 	/* Maximum number of general LU supported by the UFS device */
 	u8 max_lu_supported;
+	u8 wb_dedicated_lu;
 	u16 wmanufacturerid;
 	/*UFS device Product Name */
 	u8 *model;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f23705379b7d..8c256f6f4a65 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5204,9 +5204,18 @@ static bool ufshcd_wb_sup(struct ufs_hba *hba)
 	return ufshcd_is_wb_allowed(hba);
 }
 
+int ufshcd_wb_get_flag_index(struct ufs_hba *hba)
+{
+	if (hba->dev_info.b_wb_buffer_type == WB_BUF_MODE_LU_DEDICATED)
+		return hba->dev_info.wb_dedicated_lu;
+	else
+		return 0;
+}
+
 static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable)
 {
 	int ret;
+	u8 index;
 	enum query_opcode opcode;
 
 	if (!ufshcd_wb_sup(hba))
@@ -5219,8 +5228,9 @@ static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable)
 	else
 		opcode = UPIU_QUERY_OPCODE_CLEAR_FLAG;
 
+	index = ufshcd_wb_get_flag_index(hba);
 	ret = ufshcd_query_flag_retry(hba, opcode,
-				      QUERY_FLAG_IDN_WB_EN, 0, NULL);
+				      QUERY_FLAG_IDN_WB_EN, index, NULL);
 	if (ret) {
 		dev_err(hba->dev, "%s write booster %s failed %d\n",
 			__func__, enable ? "enable" : "disable", ret);
@@ -5237,15 +5247,17 @@ static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable)
 static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set)
 {
 	int val;
+	u8 index;
 
 	if (set)
 		val =  UPIU_QUERY_OPCODE_SET_FLAG;
 	else
 		val = UPIU_QUERY_OPCODE_CLEAR_FLAG;
 
+	index = ufshcd_wb_get_flag_index(hba);
 	return ufshcd_query_flag_retry(hba, val,
-			       QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8, 0,
-				       NULL);
+				QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8,
+				index, NULL);
 }
 
 static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable)
@@ -5260,13 +5272,15 @@ static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable)
 static int ufshcd_wb_buf_flush_enable(struct ufs_hba *hba)
 {
 	int ret;
+	u8 index;
 
 	if (!ufshcd_wb_sup(hba) || hba->wb_buf_flush_enabled)
 		return 0;
 
+	index = ufshcd_wb_get_flag_index(hba);
 	ret = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
 				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN,
-				      0, NULL);
+				      index, NULL);
 	if (ret)
 		dev_err(hba->dev, "%s WB - buf flush enable failed %d\n",
 			__func__, ret);
@@ -5280,12 +5294,15 @@ static int ufshcd_wb_buf_flush_enable(struct ufs_hba *hba)
 static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba)
 {
 	int ret;
+	u8 index;
 
 	if (!ufshcd_wb_sup(hba) || !hba->wb_buf_flush_enabled)
 		return 0;
 
+	index = ufshcd_wb_get_flag_index(hba);
 	ret = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
-				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, 0, NULL);
+				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN,
+				      index, NULL);
 	if (ret) {
 		dev_warn(hba->dev, "%s: WB - buf flush disable failed %d\n",
 			 __func__, ret);
@@ -6804,6 +6821,10 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
 
 static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf)
 {
+	int ret;
+	u8 lun;
+	u32 d_lu_wb_buf_alloc = 0;
+
 	if (!ufshcd_is_wb_allowed(hba))
 		return;
 
@@ -6826,16 +6847,33 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf)
 	hba->dev_info.b_wb_buffer_type =
 		desc_buf[DEVICE_DESC_PARAM_WB_TYPE];
 
-	hba->dev_info.d_wb_alloc_units =
-		get_unaligned_be32(desc_buf +
-				   DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS);
 	hba->dev_info.b_presrv_uspc_en =
 		desc_buf[DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN];
 
-	if (!(hba->dev_info.b_wb_buffer_type &&
-	      hba->dev_info.d_wb_alloc_units))
-		goto wb_disabled;
+	if (hba->dev_info.b_wb_buffer_type == WB_BUF_MODE_SHARED) {
+		hba->dev_info.d_wb_alloc_units =
+		get_unaligned_be32(desc_buf +
+				   DEVICE_DESC_PARAM_WB_SHARED_ALLOC_UNITS);
+		if (!hba->dev_info.d_wb_alloc_units)
+			goto wb_disabled;
+	} else {
+		for (lun = 0; lun < hba->dev_info.max_lu_supported; lun++) {
+			ret = ufshcd_read_unit_desc_param(hba,
+					lun,
+					UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS,
+					(u8 *)&d_lu_wb_buf_alloc,
+					sizeof(d_lu_wb_buf_alloc));
+			if (ret)
+				goto wb_disabled;
+			if (d_lu_wb_buf_alloc) {
+				hba->dev_info.wb_dedicated_lu = lun;
+				break;
+			}
+		}
 
+		if (!d_lu_wb_buf_alloc)
+			goto wb_disabled;
+	}
 	return;
 
 wb_disabled:
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index e555d794d441..570961ada57c 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -823,6 +823,7 @@ void ufshcd_delay_us(unsigned long us, unsigned long tolerance);
 int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
 				u32 val, unsigned long interval_us,
 				unsigned long timeout_ms, bool can_sleep);
+int ufshcd_wb_get_flag_index(struct ufs_hba *hba);
 void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk);
 void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist,
 			    u32 reg);
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 4/5] scsi: ufs-mediatek: enable WriteBooster capability
  2020-05-01 14:38 [PATCH v3 0/5] scsi: ufs: support LU Dedicated buffer type for WriteBooster Stanley Chu
                   ` (2 preceding siblings ...)
  2020-05-01 14:38 ` [PATCH v3 3/5] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster Stanley Chu
@ 2020-05-01 14:38 ` Stanley Chu
  2020-05-01 14:38 ` [PATCH v3 5/5] scsi: ufs: cleanup WriteBooster feature Stanley Chu
  4 siblings, 0 replies; 13+ messages in thread
From: Stanley Chu @ 2020-05-01 14:38 UTC (permalink / raw)
  To: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb, asutoshd
  Cc: beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng, Stanley Chu

Enable WriteBooster capability on MediaTek UFS platforms.

Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
Reviewed-by: Bean Huo <beanhuo@micron.com>
---
 drivers/scsi/ufs/ufs-mediatek.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
index 673c16596fb2..15b9c420a3a5 100644
--- a/drivers/scsi/ufs/ufs-mediatek.c
+++ b/drivers/scsi/ufs/ufs-mediatek.c
@@ -263,6 +263,9 @@ static int ufs_mtk_init(struct ufs_hba *hba)
 	/* Enable clock-gating */
 	hba->caps |= UFSHCD_CAP_CLK_GATING;
 
+	/* Enable WriteBooster */
+	hba->caps |= UFSHCD_CAP_WB_EN;
+
 	/*
 	 * ufshcd_vops_init() is invoked after
 	 * ufshcd_setup_clock(true) in ufshcd_hba_init() thus
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 5/5] scsi: ufs: cleanup WriteBooster feature
  2020-05-01 14:38 [PATCH v3 0/5] scsi: ufs: support LU Dedicated buffer type for WriteBooster Stanley Chu
                   ` (3 preceding siblings ...)
  2020-05-01 14:38 ` [PATCH v3 4/5] scsi: ufs-mediatek: enable WriteBooster capability Stanley Chu
@ 2020-05-01 14:38 ` Stanley Chu
  2020-05-02 16:05   ` Avri Altman
  4 siblings, 1 reply; 13+ messages in thread
From: Stanley Chu @ 2020-05-01 14:38 UTC (permalink / raw)
  To: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb, asutoshd
  Cc: beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng, Stanley Chu

Small cleanup as below items,

1. Use ufshcd_is_wb_allowed() directly instead of ufshcd_wb_sup()
   since ufshcd_wb_sup() just returns the result of
   ufshcd_is_wb_allowed().

2. In ufshcd_suspend(), "else if (!ufshcd_is_runtime_pm(pm_op))
   can be simplified to "else" since both have the same meaning.

This patch does not change any functionality.

Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
---
 drivers/scsi/ufs/ufshcd.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 8c256f6f4a65..420d1476b3e1 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -255,7 +255,6 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up);
 static irqreturn_t ufshcd_intr(int irq, void *__hba);
 static int ufshcd_change_power_mode(struct ufs_hba *hba,
 			     struct ufs_pa_layer_attr *pwr_mode);
-static bool ufshcd_wb_sup(struct ufs_hba *hba);
 static int ufshcd_wb_buf_flush_enable(struct ufs_hba *hba);
 static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba);
 static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable);
@@ -287,7 +286,7 @@ static inline void ufshcd_wb_config(struct ufs_hba *hba)
 {
 	int ret;
 
-	if (!ufshcd_wb_sup(hba))
+	if (!ufshcd_is_wb_allowed(hba))
 		return;
 
 	ret = ufshcd_wb_ctrl(hba, true);
@@ -5199,11 +5198,6 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
 				__func__, err);
 }
 
-static bool ufshcd_wb_sup(struct ufs_hba *hba)
-{
-	return ufshcd_is_wb_allowed(hba);
-}
-
 int ufshcd_wb_get_flag_index(struct ufs_hba *hba)
 {
 	if (hba->dev_info.b_wb_buffer_type == WB_BUF_MODE_LU_DEDICATED)
@@ -5218,7 +5212,7 @@ static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable)
 	u8 index;
 	enum query_opcode opcode;
 
-	if (!ufshcd_wb_sup(hba))
+	if (!ufshcd_is_wb_allowed(hba))
 		return 0;
 
 	if (!(enable ^ hba->wb_enabled))
@@ -5274,7 +5268,7 @@ static int ufshcd_wb_buf_flush_enable(struct ufs_hba *hba)
 	int ret;
 	u8 index;
 
-	if (!ufshcd_wb_sup(hba) || hba->wb_buf_flush_enabled)
+	if (!ufshcd_is_wb_allowed(hba) || hba->wb_buf_flush_enabled)
 		return 0;
 
 	index = ufshcd_wb_get_flag_index(hba);
@@ -5296,7 +5290,7 @@ static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba)
 	int ret;
 	u8 index;
 
-	if (!ufshcd_wb_sup(hba) || !hba->wb_buf_flush_enabled)
+	if (!ufshcd_is_wb_allowed(hba) || !hba->wb_buf_flush_enabled)
 		return 0;
 
 	index = ufshcd_wb_get_flag_index(hba);
@@ -5346,7 +5340,7 @@ static bool ufshcd_wb_keep_vcc_on(struct ufs_hba *hba)
 	int ret;
 	u32 avail_buf;
 
-	if (!ufshcd_wb_sup(hba))
+	if (!ufshcd_is_wb_allowed(hba))
 		return false;
 	/*
 	 * The ufs device needs the vcc to be ON to flush.
@@ -8231,12 +8225,12 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 		 * configured WB type is 70% full, keep vcc ON
 		 * for the device to flush the wb buffer
 		 */
-		if ((hba->auto_bkops_enabled && ufshcd_wb_sup(hba)) ||
+		if ((hba->auto_bkops_enabled && ufshcd_is_wb_allowed(hba)) ||
 		    ufshcd_wb_keep_vcc_on(hba))
 			hba->dev_info.keep_vcc_on = true;
 		else
 			hba->dev_info.keep_vcc_on = false;
-	} else if (!ufshcd_is_runtime_pm(pm_op)) {
+	} else {
 		hba->dev_info.keep_vcc_on = false;
 	}
 
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/5] scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices
  2020-05-01 14:38 ` [PATCH v3 1/5] scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices Stanley Chu
@ 2020-05-02  7:47   ` Can Guo
  2020-05-03  6:13     ` Stanley Chu
  0 siblings, 1 reply; 13+ messages in thread
From: Can Guo @ 2020-05-02  7:47 UTC (permalink / raw)
  To: Stanley Chu
  Cc: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb,
	asutoshd, beanhuo, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng

Hi Stanley,

On 2020-05-01 22:38, Stanley Chu wrote:
> WriteBooster feature can be supported by some pre-3.1 UFS devices
> by upgrading firmware.
> 
> To enable WriteBooster feature in such devices, introduce a device
> quirk to relax the entrance condition of ufshcd_wb_probe() to allow
> host driver to check those devices' WriteBooster capability.
> 
> WriteBooster feature can be available if below all conditions are
> satisfied,
> 
> 1. Host enables WriteBooster capability
> 2. UFS 3.1 device or UFS pre-3.1 device with quirk
>    UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES enabled
> 3. Device descriptor has dExtendedUFSFeaturesSupport field
> 4. WriteBooster support is specified in above field
> 
> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
> ---
>  drivers/scsi/ufs/ufs_quirks.h |  7 ++++
>  drivers/scsi/ufs/ufshcd.c     | 66 ++++++++++++++++++++++-------------
>  2 files changed, 48 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs_quirks.h 
> b/drivers/scsi/ufs/ufs_quirks.h
> index df7a1e6805a3..e3175a63c676 100644
> --- a/drivers/scsi/ufs/ufs_quirks.h
> +++ b/drivers/scsi/ufs/ufs_quirks.h
> @@ -101,4 +101,11 @@ struct ufs_dev_fix {
>   */
>  #define UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME	(1 << 9)
> 
> +/*
> + * Some pre-3.1 UFS devices can support extended features by upgrading
> + * the firmware. Enable this quirk to make UFS core driver probe and 
> enable
> + * supported features on such devices.
> + */
> +#define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10)
> +
>  #endif /* UFS_QUIRKS_H_ */
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 915e963398c4..c6668799d956 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -229,6 +229,8 @@ static struct ufs_dev_fix ufs_fixups[] = {
>  		UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
>  	UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/,
>  		UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME),
> +	UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMZDAR",
> +		UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES),
> 
>  	END_FIX
>  };
> @@ -6800,9 +6802,19 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba 
> *hba)
> 
>  static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf)
>  {
> +	if (!ufshcd_is_wb_allowed(hba))
> +		return;
> +
> +	if (hba->desc_size.dev_desc <= DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP)
> +		goto wb_disabled;
> +
>  	hba->dev_info.d_ext_ufs_feature_sup =
>  		get_unaligned_be32(desc_buf +
>  				   DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
> +
> +	if (!(hba->dev_info.d_ext_ufs_feature_sup & 
> UFS_DEV_WRITE_BOOSTER_SUP))
> +		goto wb_disabled;
> +
>  	/*
>  	 * WB may be supported but not configured while provisioning.
>  	 * The spec says, in dedicated wb buffer mode,
> @@ -6818,11 +6830,29 @@ static void ufshcd_wb_probe(struct ufs_hba
> *hba, u8 *desc_buf)
>  	hba->dev_info.b_presrv_uspc_en =
>  		desc_buf[DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN];
> 
> -	if (!((hba->dev_info.d_ext_ufs_feature_sup &
> -		 UFS_DEV_WRITE_BOOSTER_SUP) &&
> -		hba->dev_info.b_wb_buffer_type &&
> +	if (!(hba->dev_info.b_wb_buffer_type &&
>  	      hba->dev_info.d_wb_alloc_units))
> -		hba->caps &= ~UFSHCD_CAP_WB_EN;
> +		goto wb_disabled;
> +
> +	return;
> +
> +wb_disabled:
> +	hba->caps &= ~UFSHCD_CAP_WB_EN;
> +}
> +
> +static void ufs_fixup_device_setup(struct ufs_hba *hba)
> +{
> +	struct ufs_dev_fix *f;
> +	struct ufs_dev_info *dev_info = &hba->dev_info;
> +
> +	for (f = ufs_fixups; f->quirk; f++) {
> +		if ((f->wmanufacturerid == dev_info->wmanufacturerid ||
> +		     f->wmanufacturerid == UFS_ANY_VENDOR) &&
> +		     ((dev_info->model &&
> +		       STR_PRFX_EQUAL(f->model, dev_info->model)) ||
> +		      !strcmp(f->model, UFS_ANY_MODEL)))
> +			hba->dev_quirks |= f->quirk;
> +	}
>  }
> 
>  static int ufs_get_device_desc(struct ufs_hba *hba)
> @@ -6862,10 +6892,6 @@ static int ufs_get_device_desc(struct ufs_hba 
> *hba)
> 
>  	model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
> 
> -	/* Enable WB only for UFS-3.1 */
> -	if (dev_info->wspecversion >= 0x310)
> -		ufshcd_wb_probe(hba, desc_buf);
> -
>  	err = ufshcd_read_string_desc(hba, model_index,
>  				      &dev_info->model, SD_ASCII_STD);
>  	if (err < 0) {
> @@ -6874,6 +6900,13 @@ static int ufs_get_device_desc(struct ufs_hba 
> *hba)
>  		goto out;
>  	}
> 
> +	ufs_fixup_device_setup(hba);
> +
> +	/* Enable WB only for UFS-3.1 */

Also update this comment to reflect your change?

> +	if (dev_info->wspecversion >= 0x310 ||
> +	    (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES))
> +		ufshcd_wb_probe(hba, desc_buf);
> +

Can we somehow move this after ufshcd_tune_unipro_params() or come up 
with
a better way to leverage ufshcd_vops_apply_dev_quirks()? I am asking 
this
because if we only rely on adding quirks to ufs_fixups in ufshcd.c, the
table will keep growing and I am sure it will - as flash vendors are 
trying
to make their UFS2.1 products to be capable of WB (different densities 
and
different NAND processes from different vendors, the combos can be quite 
a
few). Meanwhile, some models are specifically made for some customers to
support WB, meaning having them in the table may not help in a 
generalized
way, and it is not like some hot fixes that we have to take, it is just 
for
a non-standard feature. If we can leverage 
ufshcd_vops_apply_dev_quirks(),
SoC vendors can freely add the quirk without touching ufs_fixups table,
which means you don't need to update ufs_fixups every time just for 
adding
a new model (GKI rules), you can have your own WB white list in vendor
driver. What do you think?

Thanks,

Can Guo.

>  	/*
>  	 * ufshcd_read_string_desc returns size of the string
>  	 * reset the error value
> @@ -6893,21 +6926,6 @@ static void ufs_put_device_desc(struct ufs_hba 
> *hba)
>  	dev_info->model = NULL;
>  }
> 
> -static void ufs_fixup_device_setup(struct ufs_hba *hba)
> -{
> -	struct ufs_dev_fix *f;
> -	struct ufs_dev_info *dev_info = &hba->dev_info;
> -
> -	for (f = ufs_fixups; f->quirk; f++) {
> -		if ((f->wmanufacturerid == dev_info->wmanufacturerid ||
> -		     f->wmanufacturerid == UFS_ANY_VENDOR) &&
> -		     ((dev_info->model &&
> -		       STR_PRFX_EQUAL(f->model, dev_info->model)) ||
> -		      !strcmp(f->model, UFS_ANY_MODEL)))
> -			hba->dev_quirks |= f->quirk;
> -	}
> -}
> -
>  /**
>   * ufshcd_tune_pa_tactivate - Tunes PA_TActivate of local UniPro
>   * @hba: per-adapter instance
> @@ -7244,8 +7262,6 @@ static int ufshcd_device_params_init(struct 
> ufs_hba *hba)
> 
>  	ufshcd_get_ref_clk_gating_wait(hba);
> 
> -	ufs_fixup_device_setup(hba);
> -
>  	if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
>  			QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
>  		hba->dev_info.f_power_on_wp_en = flag;

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v3 2/5] scsi: ufs: add "index" in parameter list of ufshcd_query_flag()
  2020-05-01 14:38 ` [PATCH v3 2/5] scsi: ufs: add "index" in parameter list of ufshcd_query_flag() Stanley Chu
@ 2020-05-02 15:23   ` Avri Altman
  2020-05-03  1:51   ` Can Guo
  1 sibling, 0 replies; 13+ messages in thread
From: Avri Altman @ 2020-05-02 15:23 UTC (permalink / raw)
  To: Stanley Chu, linux-scsi, martin.petersen, alim.akhtar, jejb, asutoshd
  Cc: beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng

 
> 
> For preparation of LU Dedicated buffer mode support on WriteBooster
> feature, "index" parameter shall be added and allowed to be specified
> by callers.
> 
> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
> Reviewed-by: Bean Huo <beanhuo@micron.com>
Reviewed-by: Avri Altman <avri.altman@wdc.com>

> ---
>  drivers/scsi/ufs/ufs-sysfs.c |  2 +-
>  drivers/scsi/ufs/ufshcd.c    | 28 +++++++++++++++-------------
>  drivers/scsi/ufs/ufshcd.h    |  2 +-
>  3 files changed, 17 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> index 93484408bc40..b86b6a40d7e6 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -631,7 +631,7 @@ static ssize_t _name##_show(struct device *dev,
> \
>         struct ufs_hba *hba = dev_get_drvdata(dev);                     \
>         pm_runtime_get_sync(hba->dev);                                  \
>         ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,       \
> -               QUERY_FLAG_IDN##_uname, &flag);                         \
> +               QUERY_FLAG_IDN##_uname, 0, &flag);                      \
Noticed that you are handling this in patch #3 - that's fine!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v3 3/5] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster
  2020-05-01 14:38 ` [PATCH v3 3/5] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster Stanley Chu
@ 2020-05-02 15:32   ` Avri Altman
  2020-05-03  6:06     ` Stanley Chu
  0 siblings, 1 reply; 13+ messages in thread
From: Avri Altman @ 2020-05-02 15:32 UTC (permalink / raw)
  To: Stanley Chu, linux-scsi, martin.petersen, alim.akhtar, jejb, asutoshd
  Cc: beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng

 Hi Stanley,
Few more nits.
Thanks,
Avri

> 
> According to UFS specification, there are two WriteBooster mode of
> operations: "LU dedicated buffer" mode and "shared buffer" mode.
> In the "LU dedicated buffer" mode, the WriteBooster Buffer is
> dedicated to a logical unit.
> 
> If the device supports the "LU dedicated buffer" mode, this mode is
> configured by setting bWriteBoosterBufferType to 00h. The logical
> unit WriteBooster Buffer size is configured by setting the
> dLUNumWriteBoosterBufferAllocUnits field of the related Unit
> Descriptor. Only a value greater than zero enables the WriteBooster
> feature in the logical unit.
> 
> Modify ufshcd_wb_probe() as above description to support LU Dedicated
> buffer mode.
> 
> Note that according to UFS 3.1 specification, the valid value of
> bDeviceMaxWriteBoosterLUs parameter in Geometry Descriptor is 1,
> which means at most one LUN can have WriteBooster buffer in "LU
> dedicated buffer mode". Therefore this patch supports only one
> LUN with WriteBooster enabled. All WriteBooster related sysfs nodes
> are specifically mapped to the LUN with WriteBooster enabled in
> LU Dedicated buffer mode.
> 
> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
> ---
>  drivers/scsi/ufs/ufs-sysfs.c | 14 ++++++++-
>  drivers/scsi/ufs/ufs.h       |  7 +++++
>  drivers/scsi/ufs/ufshcd.c    | 60 +++++++++++++++++++++++++++++-------
>  drivers/scsi/ufs/ufshcd.h    |  1 +
>  4 files changed, 70 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> index b86b6a40d7e6..a162f63098e5 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -622,16 +622,28 @@ static const struct attribute_group
> ufs_sysfs_string_descriptors_group = {
>         .attrs = ufs_sysfs_string_descriptors,
>  };
> 
> +static bool ufshcd_is_wb_flags(enum flag_idn idn)
Inline?
And just return (idn >= QUERY_FLAG_IDN_WB_EN &&  idn <= QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8)

> +{
> +       if (idn >= QUERY_FLAG_IDN_WB_EN &&
> +           idn <= QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8)
> +               return true;
> +       else
> +               return false;
> +}
> +


> 
> +int ufshcd_wb_get_flag_index(struct ufs_hba *hba)
> +{
> +       if (hba->dev_info.b_wb_buffer_type ==
> WB_BUF_MODE_LU_DEDICATED)
> +               return hba->dev_info.wb_dedicated_lu;
> +       else
No need for else.
Maybe make this static inline in ufshcd.h?

> +               return 0;
> +}
> +

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v3 5/5] scsi: ufs: cleanup WriteBooster feature
  2020-05-01 14:38 ` [PATCH v3 5/5] scsi: ufs: cleanup WriteBooster feature Stanley Chu
@ 2020-05-02 16:05   ` Avri Altman
  0 siblings, 0 replies; 13+ messages in thread
From: Avri Altman @ 2020-05-02 16:05 UTC (permalink / raw)
  To: Stanley Chu, linux-scsi, martin.petersen, alim.akhtar, jejb, asutoshd
  Cc: beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng

 
> 
> Small cleanup as below items,
> 
> 1. Use ufshcd_is_wb_allowed() directly instead of ufshcd_wb_sup()
>    since ufshcd_wb_sup() just returns the result of
>    ufshcd_is_wb_allowed().
> 
> 2. In ufshcd_suspend(), "else if (!ufshcd_is_runtime_pm(pm_op))
>    can be simplified to "else" since both have the same meaning.
> 
> This patch does not change any functionality.
> 
> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
Reviewed-by: Avri Altman <avri.altman@wdc.com>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 2/5] scsi: ufs: add "index" in parameter list of ufshcd_query_flag()
  2020-05-01 14:38 ` [PATCH v3 2/5] scsi: ufs: add "index" in parameter list of ufshcd_query_flag() Stanley Chu
  2020-05-02 15:23   ` Avri Altman
@ 2020-05-03  1:51   ` Can Guo
  1 sibling, 0 replies; 13+ messages in thread
From: Can Guo @ 2020-05-03  1:51 UTC (permalink / raw)
  To: Stanley Chu
  Cc: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb,
	asutoshd, beanhuo, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng

On 2020-05-01 22:38, Stanley Chu wrote:
> For preparation of LU Dedicated buffer mode support on WriteBooster
> feature, "index" parameter shall be added and allowed to be specified
> by callers.
> 
> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
> Reviewed-by: Bean Huo <beanhuo@micron.com>

Reviewed-by: Can Guo <cang@codeaurora.org>

> ---
>  drivers/scsi/ufs/ufs-sysfs.c |  2 +-
>  drivers/scsi/ufs/ufshcd.c    | 28 +++++++++++++++-------------
>  drivers/scsi/ufs/ufshcd.h    |  2 +-
>  3 files changed, 17 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c 
> b/drivers/scsi/ufs/ufs-sysfs.c
> index 93484408bc40..b86b6a40d7e6 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -631,7 +631,7 @@ static ssize_t _name##_show(struct device 
> *dev,				\
>  	struct ufs_hba *hba = dev_get_drvdata(dev);			\
>  	pm_runtime_get_sync(hba->dev);					\
>  	ret = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,	\
> -		QUERY_FLAG_IDN##_uname, &flag);				\
> +		QUERY_FLAG_IDN##_uname, 0, &flag);			\
>  	pm_runtime_put_sync(hba->dev);					\
>  	if (ret)							\
>  		return -EINVAL;						\
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index c6668799d956..f23705379b7d 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -2784,13 +2784,13 @@ static inline void ufshcd_init_query(struct
> ufs_hba *hba,
>  }
> 
>  static int ufshcd_query_flag_retry(struct ufs_hba *hba,
> -	enum query_opcode opcode, enum flag_idn idn, bool *flag_res)
> +	enum query_opcode opcode, enum flag_idn idn, u8 index, bool 
> *flag_res)
>  {
>  	int ret;
>  	int retries;
> 
>  	for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) {
> -		ret = ufshcd_query_flag(hba, opcode, idn, flag_res);
> +		ret = ufshcd_query_flag(hba, opcode, idn, index, flag_res);
>  		if (ret)
>  			dev_dbg(hba->dev,
>  				"%s: failed with error %d, retries %d\n",
> @@ -2811,16 +2811,17 @@ static int ufshcd_query_flag_retry(struct 
> ufs_hba *hba,
>   * @hba: per-adapter instance
>   * @opcode: flag query to perform
>   * @idn: flag idn to access
> + * @index: flag index to access
>   * @flag_res: the flag value after the query request completes
>   *
>   * Returns 0 for success, non-zero in case of failure
>   */
>  int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
> -			enum flag_idn idn, bool *flag_res)
> +			enum flag_idn idn, u8 index, bool *flag_res)
>  {
>  	struct ufs_query_req *request = NULL;
>  	struct ufs_query_res *response = NULL;
> -	int err, index = 0, selector = 0;
> +	int err, selector = 0;
>  	int timeout = QUERY_REQ_TIMEOUT;
> 
>  	BUG_ON(!hba);
> @@ -4177,7 +4178,7 @@ static int ufshcd_complete_dev_init(struct 
> ufs_hba *hba)
>  	bool flag_res = true;
> 
>  	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
> -		QUERY_FLAG_IDN_FDEVICEINIT, NULL);
> +		QUERY_FLAG_IDN_FDEVICEINIT, 0, NULL);
>  	if (err) {
>  		dev_err(hba->dev,
>  			"%s setting fDeviceInit flag failed with error %d\n",
> @@ -4188,7 +4189,7 @@ static int ufshcd_complete_dev_init(struct 
> ufs_hba *hba)
>  	/* poll for max. 1000 iterations for fDeviceInit flag to clear */
>  	for (i = 0; i < 1000 && !err && flag_res; i++)
>  		err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
> -			QUERY_FLAG_IDN_FDEVICEINIT, &flag_res);
> +			QUERY_FLAG_IDN_FDEVICEINIT, 0, &flag_res);
> 
>  	if (err)
>  		dev_err(hba->dev,
> @@ -5003,7 +5004,7 @@ static int ufshcd_enable_auto_bkops(struct 
> ufs_hba *hba)
>  		goto out;
> 
>  	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
> -			QUERY_FLAG_IDN_BKOPS_EN, NULL);
> +			QUERY_FLAG_IDN_BKOPS_EN, 0, NULL);
>  	if (err) {
>  		dev_err(hba->dev, "%s: failed to enable bkops %d\n",
>  				__func__, err);
> @@ -5053,7 +5054,7 @@ static int ufshcd_disable_auto_bkops(struct 
> ufs_hba *hba)
>  	}
> 
>  	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
> -			QUERY_FLAG_IDN_BKOPS_EN, NULL);
> +			QUERY_FLAG_IDN_BKOPS_EN, 0, NULL);
>  	if (err) {
>  		dev_err(hba->dev, "%s: failed to disable bkops %d\n",
>  				__func__, err);
> @@ -5219,7 +5220,7 @@ static int ufshcd_wb_ctrl(struct ufs_hba *hba,
> bool enable)
>  		opcode = UPIU_QUERY_OPCODE_CLEAR_FLAG;
> 
>  	ret = ufshcd_query_flag_retry(hba, opcode,
> -				      QUERY_FLAG_IDN_WB_EN, NULL);
> +				      QUERY_FLAG_IDN_WB_EN, 0, NULL);
>  	if (ret) {
>  		dev_err(hba->dev, "%s write booster %s failed %d\n",
>  			__func__, enable ? "enable" : "disable", ret);
> @@ -5243,7 +5244,7 @@ static int
> ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set)
>  		val = UPIU_QUERY_OPCODE_CLEAR_FLAG;
> 
>  	return ufshcd_query_flag_retry(hba, val,
> -			       QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8,
> +			       QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8, 0,
>  				       NULL);
>  }
> 
> @@ -5264,7 +5265,8 @@ static int ufshcd_wb_buf_flush_enable(struct 
> ufs_hba *hba)
>  		return 0;
> 
>  	ret = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
> -				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, NULL);
> +				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN,
> +				      0, NULL);
>  	if (ret)
>  		dev_err(hba->dev, "%s WB - buf flush enable failed %d\n",
>  			__func__, ret);
> @@ -5283,7 +5285,7 @@ static int ufshcd_wb_buf_flush_disable(struct
> ufs_hba *hba)
>  		return 0;
> 
>  	ret = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG,
> -				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, NULL);
> +				      QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, 0, NULL);
>  	if (ret) {
>  		dev_warn(hba->dev, "%s: WB - buf flush disable failed %d\n",
>  			 __func__, ret);
> @@ -7263,7 +7265,7 @@ static int ufshcd_device_params_init(struct 
> ufs_hba *hba)
>  	ufshcd_get_ref_clk_gating_wait(hba);
> 
>  	if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
> -			QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
> +			QUERY_FLAG_IDN_PWR_ON_WPE, 0, &flag))
>  		hba->dev_info.f_power_on_wp_en = flag;
> 
>  	/* Probe maximum power mode co-supported by both UFS host and device 
> */
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 056537e52c19..e555d794d441 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -946,7 +946,7 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
>  int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
>  		      enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
>  int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
> -	enum flag_idn idn, bool *flag_res);
> +	enum flag_idn idn, u8 index, bool *flag_res);
> 
>  void ufshcd_auto_hibern8_enable(struct ufs_hba *hba);
>  void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v3 3/5] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster
  2020-05-02 15:32   ` Avri Altman
@ 2020-05-03  6:06     ` Stanley Chu
  0 siblings, 0 replies; 13+ messages in thread
From: Stanley Chu @ 2020-05-03  6:06 UTC (permalink / raw)
  To: Avri Altman
  Cc: linux-scsi, martin.petersen, alim.akhtar, jejb, asutoshd,
	beanhuo, cang, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng

Hi Avri,

On Sat, 2020-05-02 at 15:32 +0000, Avri Altman wrote:
> Hi Stanley,
> Few more nits.
> Thanks,
> Avri

All fixed in v4.
Thanks for these suggestions.

Stanley Chu

> 
> > 
> > According to UFS specification, there are two WriteBooster mode of
> > operations: "LU dedicated buffer" mode and "shared buffer" mode.
> > In the "LU dedicated buffer" mode, the WriteBooster Buffer is
> > dedicated to a logical unit.
> > 
> > If the device supports the "LU dedicated buffer" mode, this mode is
> > configured by setting bWriteBoosterBufferType to 00h. The logical
> > unit WriteBooster Buffer size is configured by setting the
> > dLUNumWriteBoosterBufferAllocUnits field of the related Unit
> > Descriptor. Only a value greater than zero enables the WriteBooster
> > feature in the logical unit.
> > 
> > Modify ufshcd_wb_probe() as above description to support LU Dedicated
> > buffer mode.
> > 
> > Note that according to UFS 3.1 specification, the valid value of
> > bDeviceMaxWriteBoosterLUs parameter in Geometry Descriptor is 1,
> > which means at most one LUN can have WriteBooster buffer in "LU
> > dedicated buffer mode". Therefore this patch supports only one
> > LUN with WriteBooster enabled. All WriteBooster related sysfs nodes
> > are specifically mapped to the LUN with WriteBooster enabled in
> > LU Dedicated buffer mode.
> > 
> > Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
> > ---
> >  drivers/scsi/ufs/ufs-sysfs.c | 14 ++++++++-
> >  drivers/scsi/ufs/ufs.h       |  7 +++++
> >  drivers/scsi/ufs/ufshcd.c    | 60 +++++++++++++++++++++++++++++-------
> >  drivers/scsi/ufs/ufshcd.h    |  1 +
> >  4 files changed, 70 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> > index b86b6a40d7e6..a162f63098e5 100644
> > --- a/drivers/scsi/ufs/ufs-sysfs.c
> > +++ b/drivers/scsi/ufs/ufs-sysfs.c
> > @@ -622,16 +622,28 @@ static const struct attribute_group
> > ufs_sysfs_string_descriptors_group = {
> >         .attrs = ufs_sysfs_string_descriptors,
> >  };
> > 
> > +static bool ufshcd_is_wb_flags(enum flag_idn idn)
> Inline?
> And just return (idn >= QUERY_FLAG_IDN_WB_EN &&  idn <= QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8)
> 
> > +{
> > +       if (idn >= QUERY_FLAG_IDN_WB_EN &&
> > +           idn <= QUERY_FLAG_IDN_WB_BUFF_FLUSH_DURING_HIBERN8)
> > +               return true;
> > +       else
> > +               return false;
> > +}
> > +
> 
> 
> > 
> > +int ufshcd_wb_get_flag_index(struct ufs_hba *hba)
> > +{
> > +       if (hba->dev_info.b_wb_buffer_type ==
> > WB_BUF_MODE_LU_DEDICATED)
> > +               return hba->dev_info.wb_dedicated_lu;
> > +       else
> No need for else.
> Maybe make this static inline in ufshcd.h?
> 
> > +               return 0;
> > +}
> > +


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/5] scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices
  2020-05-02  7:47   ` Can Guo
@ 2020-05-03  6:13     ` Stanley Chu
  0 siblings, 0 replies; 13+ messages in thread
From: Stanley Chu @ 2020-05-03  6:13 UTC (permalink / raw)
  To: Can Guo
  Cc: linux-scsi, martin.petersen, avri.altman, alim.akhtar, jejb,
	asutoshd, beanhuo, matthias.bgg, bvanassche, linux-mediatek,
	linux-arm-kernel, linux-kernel, kuohong.wang, peter.wang,
	chun-hung.wu, andy.teng

Hi Can,

On Sat, 2020-05-02 at 15:47 +0800, Can Guo wrote:
> Hi Stanley,
> On 2020-05-01 22:38, Stanley Chu wrote:
> > WriteBooster feature can be supported by some pre-3.1 UFS devices
> > by upgrading firmware.
> > 
> > To enable WriteBooster feature in such devices, introduce a device
> > quirk to relax the entrance condition of ufshcd_wb_probe() to allow
> > host driver to check those devices' WriteBooster capability.
> > 
> > WriteBooster feature can be available if below all conditions are
> > satisfied,
> > 
> > 1. Host enables WriteBooster capability
> > 2. UFS 3.1 device or UFS pre-3.1 device with quirk
> >    UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES enabled
> > 3. Device descriptor has dExtendedUFSFeaturesSupport field
> > 4. WriteBooster support is specified in above field
> > 
> > Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
> > ---
> >  drivers/scsi/ufs/ufs_quirks.h |  7 ++++
> >  drivers/scsi/ufs/ufshcd.c     | 66 ++++++++++++++++++++++-------------
> >  2 files changed, 48 insertions(+), 25 deletions(-)
> > 
> > diff --git a/drivers/scsi/ufs/ufs_quirks.h 
> > b/drivers/scsi/ufs/ufs_quirks.h
> > index df7a1e6805a3..e3175a63c676 100644
> > --- a/drivers/scsi/ufs/ufs_quirks.h
> > +++ b/drivers/scsi/ufs/ufs_quirks.h
> > @@ -101,4 +101,11 @@ struct ufs_dev_fix {
> >   */
> >  #define UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME	(1 << 9)
> > 
> > +/*
> > + * Some pre-3.1 UFS devices can support extended features by upgrading
> > + * the firmware. Enable this quirk to make UFS core driver probe and 
> > enable
> > + * supported features on such devices.
> > + */
> > +#define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10)
> > +
> >  #endif /* UFS_QUIRKS_H_ */
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index 915e963398c4..c6668799d956 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -229,6 +229,8 @@ static struct ufs_dev_fix ufs_fixups[] = {
> >  		UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
> >  	UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/,
> >  		UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME),
> > +	UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMZDAR",
> > +		UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES),
> > 
> >  	END_FIX
> >  };
> > @@ -6800,9 +6802,19 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba 
> > *hba)
> > 
> >  static void ufshcd_wb_probe(struct ufs_hba *hba, u8 *desc_buf)
> >  {
> > +	if (!ufshcd_is_wb_allowed(hba))
> > +		return;
> > +
> > +	if (hba->desc_size.dev_desc <= DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP)
> > +		goto wb_disabled;
> > +
> >  	hba->dev_info.d_ext_ufs_feature_sup =
> >  		get_unaligned_be32(desc_buf +
> >  				   DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
> > +
> > +	if (!(hba->dev_info.d_ext_ufs_feature_sup & 
> > UFS_DEV_WRITE_BOOSTER_SUP))
> > +		goto wb_disabled;
> > +
> >  	/*
> >  	 * WB may be supported but not configured while provisioning.
> >  	 * The spec says, in dedicated wb buffer mode,
> > @@ -6818,11 +6830,29 @@ static void ufshcd_wb_probe(struct ufs_hba
> > *hba, u8 *desc_buf)
> >  	hba->dev_info.b_presrv_uspc_en =
> >  		desc_buf[DEVICE_DESC_PARAM_WB_PRESRV_USRSPC_EN];
> > 
> > -	if (!((hba->dev_info.d_ext_ufs_feature_sup &
> > -		 UFS_DEV_WRITE_BOOSTER_SUP) &&
> > -		hba->dev_info.b_wb_buffer_type &&
> > +	if (!(hba->dev_info.b_wb_buffer_type &&
> >  	      hba->dev_info.d_wb_alloc_units))
> > -		hba->caps &= ~UFSHCD_CAP_WB_EN;
> > +		goto wb_disabled;
> > +
> > +	return;
> > +
> > +wb_disabled:
> > +	hba->caps &= ~UFSHCD_CAP_WB_EN;
> > +}
> > +
> > +static void ufs_fixup_device_setup(struct ufs_hba *hba)
> > +{
> > +	struct ufs_dev_fix *f;
> > +	struct ufs_dev_info *dev_info = &hba->dev_info;
> > +
> > +	for (f = ufs_fixups; f->quirk; f++) {
> > +		if ((f->wmanufacturerid == dev_info->wmanufacturerid ||
> > +		     f->wmanufacturerid == UFS_ANY_VENDOR) &&
> > +		     ((dev_info->model &&
> > +		       STR_PRFX_EQUAL(f->model, dev_info->model)) ||
> > +		      !strcmp(f->model, UFS_ANY_MODEL)))
> > +			hba->dev_quirks |= f->quirk;
> > +	}
> >  }
> > 
> >  static int ufs_get_device_desc(struct ufs_hba *hba)
> > @@ -6862,10 +6892,6 @@ static int ufs_get_device_desc(struct ufs_hba 
> > *hba)
> > 
> >  	model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
> > 
> > -	/* Enable WB only for UFS-3.1 */
> > -	if (dev_info->wspecversion >= 0x310)
> > -		ufshcd_wb_probe(hba, desc_buf);
> > -
> >  	err = ufshcd_read_string_desc(hba, model_index,
> >  				      &dev_info->model, SD_ASCII_STD);
> >  	if (err < 0) {
> > @@ -6874,6 +6900,13 @@ static int ufs_get_device_desc(struct ufs_hba 
> > *hba)
> >  		goto out;
> >  	}
> > 
> > +	ufs_fixup_device_setup(hba);
> > +
> > +	/* Enable WB only for UFS-3.1 */
> 
> Also update this comment to reflect your change?
> 
> > +	if (dev_info->wspecversion >= 0x310 ||
> > +	    (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES))
> > +		ufshcd_wb_probe(hba, desc_buf);
> > +
> 
> Can we somehow move this after ufshcd_tune_unipro_params() or come up 
> with
> a better way to leverage ufshcd_vops_apply_dev_quirks()? I am asking 
> this
> because if we only rely on adding quirks to ufs_fixups in ufshcd.c, the
> table will keep growing and I am sure it will - as flash vendors are 
> trying
> to make their UFS2.1 products to be capable of WB (different densities 
> and
> different NAND processes from different vendors, the combos can be quite 
> a
> few). Meanwhile, some models are specifically made for some customers to
> support WB, meaning having them in the table may not help in a 
> generalized
> way, and it is not like some hot fixes that we have to take, it is just 
> for
> a non-standard feature. If we can leverage 
> ufshcd_vops_apply_dev_quirks(),
> SoC vendors can freely add the quirk without touching ufs_fixups table,
> which means you don't need to update ufs_fixups every time just for 
> adding
> a new model (GKI rules), you can have your own WB white list in vendor
> driver. What do you think?
> 
> Thanks,
> 
> Can Guo.

Very appreciate your useful and constructive comments : )

Please take a look at v4. In v4, I introduce a "fixup_dev_quirks" vop to
allow vendors to "fix" device quirks which can be a general solution not
only for newly introduced UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES but
also for other quirks.

Thanks,
Stanley Chu

> 
> >  	/*
> >  	 * ufshcd_read_string_desc returns size of the string
> >  	 * reset the error value
> > @@ -6893,21 +6926,6 @@ static void ufs_put_device_desc(struct ufs_hba 
> > *hba)
> >  	dev_info->model = NULL;
> >  }
> > 
> > -static void ufs_fixup_device_setup(struct ufs_hba *hba)
> > -{
> > -	struct ufs_dev_fix *f;
> > -	struct ufs_dev_info *dev_info = &hba->dev_info;
> > -
> > -	for (f = ufs_fixups; f->quirk; f++) {
> > -		if ((f->wmanufacturerid == dev_info->wmanufacturerid ||
> > -		     f->wmanufacturerid == UFS_ANY_VENDOR) &&
> > -		     ((dev_info->model &&
> > -		       STR_PRFX_EQUAL(f->model, dev_info->model)) ||
> > -		      !strcmp(f->model, UFS_ANY_MODEL)))
> > -			hba->dev_quirks |= f->quirk;
> > -	}
> > -}
> > -
> >  /**
> >   * ufshcd_tune_pa_tactivate - Tunes PA_TActivate of local UniPro
> >   * @hba: per-adapter instance
> > @@ -7244,8 +7262,6 @@ static int ufshcd_device_params_init(struct 
> > ufs_hba *hba)
> > 
> >  	ufshcd_get_ref_clk_gating_wait(hba);
> > 
> > -	ufs_fixup_device_setup(hba);
> > -
> >  	if (!ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_READ_FLAG,
> >  			QUERY_FLAG_IDN_PWR_ON_WPE, &flag))
> >  		hba->dev_info.f_power_on_wp_en = flag;


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2020-05-03  6:13 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-01 14:38 [PATCH v3 0/5] scsi: ufs: support LU Dedicated buffer type for WriteBooster Stanley Chu
2020-05-01 14:38 ` [PATCH v3 1/5] scsi: ufs: enable WriteBooster on some pre-3.1 UFS devices Stanley Chu
2020-05-02  7:47   ` Can Guo
2020-05-03  6:13     ` Stanley Chu
2020-05-01 14:38 ` [PATCH v3 2/5] scsi: ufs: add "index" in parameter list of ufshcd_query_flag() Stanley Chu
2020-05-02 15:23   ` Avri Altman
2020-05-03  1:51   ` Can Guo
2020-05-01 14:38 ` [PATCH v3 3/5] scsi: ufs: add LU Dedicated buffer mode support for WriteBooster Stanley Chu
2020-05-02 15:32   ` Avri Altman
2020-05-03  6:06     ` Stanley Chu
2020-05-01 14:38 ` [PATCH v3 4/5] scsi: ufs-mediatek: enable WriteBooster capability Stanley Chu
2020-05-01 14:38 ` [PATCH v3 5/5] scsi: ufs: cleanup WriteBooster feature Stanley Chu
2020-05-02 16:05   ` Avri Altman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).