All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/2] ufs: support various values per device
       [not found] <CGME20200629102343epcas2p4d8f4d92c18c5e692038c7e360ab2d819@epcas2p4.samsung.com>
@ 2020-06-29 10:15 ` Kiwoong Kim
       [not found]   ` <CGME20200629102350epcas2p4f4ef326c55c897479643ebcd3e132f50@epcas2p4.samsung.com>
       [not found]   ` <CGME20200629102355epcas2p13f8714a906291e5444adfb2f5ac2c469@epcas2p1.samsung.com>
  0 siblings, 2 replies; 5+ messages in thread
From: Kiwoong Kim @ 2020-06-29 10:15 UTC (permalink / raw)
  To: linux-scsi; +Cc: Kiwoong Kim

Respective UFS devices have their own characteristics and
many of them could be a form of numbers, such as timeout
and a number of retires. This introduces the way to set
those things per specific device vendor or specific device.

Kiwoong Kim (2):
  ufs: support various values per device
  ufs: change the way to complete fDeviceInit

 drivers/scsi/ufs/ufs_quirks.h | 13 ++++++++
 drivers/scsi/ufs/ufshcd.c     | 75 ++++++++++++++++++++++++++++++++++++-------
 drivers/scsi/ufs/ufshcd.h     |  1 +
 3 files changed, 77 insertions(+), 12 deletions(-)

-- 
2.7.4


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

* [RFC PATCH v2 1/2] ufs: support various values per device
       [not found]   ` <CGME20200629102350epcas2p4f4ef326c55c897479643ebcd3e132f50@epcas2p4.samsung.com>
@ 2020-06-29 10:15     ` Kiwoong Kim
  0 siblings, 0 replies; 5+ messages in thread
From: Kiwoong Kim @ 2020-06-29 10:15 UTC (permalink / raw)
  To: linux-scsi; +Cc: Kiwoong Kim

Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com>

Respective UFS devices have their own characteristics and
many of them could be a form of numbers, such as timeout
and a number of retires. This introduces the way to set
those things per specific device vendor or specific device.

I wrote this like the style of ufs_fixups stuffs.
---
 drivers/scsi/ufs/ufs_quirks.h | 13 +++++++++++++
 drivers/scsi/ufs/ufshcd.c     | 39 +++++++++++++++++++++++++++++++++++++++
 drivers/scsi/ufs/ufshcd.h     |  1 +
 3 files changed, 53 insertions(+)

diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index 2a00414..f074093 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -29,6 +29,19 @@ struct ufs_dev_fix {
 	unsigned int quirk;
 };
 
+enum dev_val_type {
+	DEV_VAL_FDEVICEINIT	= 0x0,
+	DEV_VAL_NUM,
+};
+
+struct ufs_dev_value {
+	u16 wmanufacturerid;
+	u8 *model;
+	u32 key;
+	u32 val;
+	bool enable;
+};
+
 #define END_FIX { }
 
 /* add specific device quirk */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 52abe82..7b6f13a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -207,6 +207,21 @@ static struct ufs_dev_fix ufs_fixups[] = {
 	END_FIX
 };
 
+static const struct ufs_dev_value ufs_dev_values[] = {
+	{0, 0, 0, 0, false},
+};
+
+static inline bool
+ufs_get_dev_specific_value(struct ufs_hba *hba,
+			   enum dev_val_type type, u32 *val)
+{
+	if (!ufs_dev_values[type].enable)
+		return false;
+
+	*val = hba->dev_value[type];
+	return true;
+}
+
 static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba);
 static void ufshcd_async_scan(void *data, async_cookie_t cookie);
 static int ufshcd_reset_and_restore(struct ufs_hba *hba);
@@ -6923,11 +6938,35 @@ void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups)
 }
 EXPORT_SYMBOL_GPL(ufshcd_fixup_dev_quirks);
 
+void ufshcd_set_dev_values(struct ufs_hba *hba, struct ufs_dev_value *value)
+{
+	struct ufs_dev_value *f;
+	struct ufs_dev_info *dev_info = &hba->dev_info;
+
+	if (!value)
+		return;
+
+	for (f = value; f->val; 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))) {
+			f->enable = true;
+			hba->dev_value[f->key] = f->val;
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(ufshcd_set_dev_values);
+
 static void ufs_fixup_device_setup(struct ufs_hba *hba)
 {
 	/* fix by general quirk table */
 	ufshcd_fixup_dev_quirks(hba, ufs_fixups);
 
+	/* set device specific values */
+	ufshcd_set_dev_values(hba, ufs_dev_values);
+
 	/* allow vendors to fix quirks */
 	ufshcd_vops_fixup_dev_quirks(hba);
 }
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index c774012..f221ca7 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -670,6 +670,7 @@ struct ufs_hba {
 
 	/* Device deviations from standard UFS device spec. */
 	unsigned int dev_quirks;
+	u32 dev_value[DEV_VAL_NUM];
 
 	struct blk_mq_tag_set tmf_tag_set;
 	struct request_queue *tmf_queue;
-- 
2.7.4


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

* [RFC PATCH v2 2/2] ufs: change the way to complete fDeviceInit
       [not found]   ` <CGME20200629102355epcas2p13f8714a906291e5444adfb2f5ac2c469@epcas2p1.samsung.com>
@ 2020-06-29 10:15     ` Kiwoong Kim
  2020-06-30  4:23       ` Grant Jung
  0 siblings, 1 reply; 5+ messages in thread
From: Kiwoong Kim @ 2020-06-29 10:15 UTC (permalink / raw)
  To: linux-scsi; +Cc: Kiwoong Kim

Currently, UFS driver checks if fDeviceInit
is cleared at several times, not period. This patch
is to wait its completion with the period, not retrying.
Many device vendors usually provides the specification on
it with just period, not a combination of a number of retrying
and period. So it could be proper to regard to the information
coming from device vendors.

I first added one device specific value regarding the information.

Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com>
---
 drivers/scsi/ufs/ufshcd.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7b6f13a..27afdf0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -208,6 +208,7 @@ static struct ufs_dev_fix ufs_fixups[] = {
 };
 
 static const struct ufs_dev_value ufs_dev_values[] = {
+	{UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL, DEV_VAL_FDEVICEINIT, 2000, false},
 	{0, 0, 0, 0, false},
 };
 
@@ -4162,9 +4163,12 @@ EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode);
  */
 static int ufshcd_complete_dev_init(struct ufs_hba *hba)
 {
-	int i;
+	u32 dev_init_compl_in_ms = 500;
+	unsigned long timeout;
 	int err;
 	bool flag_res = true;
+	bool is_dev_val;
+	u32 val;
 
 	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
 		QUERY_FLAG_IDN_FDEVICEINIT, 0, NULL);
@@ -4175,20 +4179,28 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba)
 		goto out;
 	}
 
-	/* 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, 0, &flag_res);
+	/* Poll fDeviceInit flag to be cleared */
+	is_dev_val = ufs_get_dev_specific_value(hba, DEV_VAL_FDEVICEINIT, &val);
+	dev_init_compl_in_ms = (is_dev_val) ? val : 500;
+	timeout = jiffies + msecs_to_jiffies(dev_init_compl_in_ms);
+	do {
+		err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,
+					QUERY_FLAG_IDN_FDEVICEINIT, 0, &flag_res);
+		if (!flag_res)
+			break;
+		usleep_range(1000, 2000);
+	} while (time_before(jiffies, timeout));
 
-	if (err)
+	if (err) {
 		dev_err(hba->dev,
-			"%s reading fDeviceInit flag failed with error %d\n",
-			__func__, err);
-	else if (flag_res)
+				"%s reading fDeviceInit flag failed with error %d\n",
+				__func__, err);
+	} else if (flag_res) {
 		dev_err(hba->dev,
-			"%s fDeviceInit was not cleared by the device\n",
-			__func__);
-
+				"%s fDeviceInit was not cleared by the device\n",
+				__func__);
+		err = -EBUSY;
+	}
 out:
 	return err;
 }
-- 
2.7.4


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

* RE: [RFC PATCH v2 2/2] ufs: change the way to complete fDeviceInit
  2020-06-29 10:15     ` [RFC PATCH v2 2/2] ufs: change the way to complete fDeviceInit Kiwoong Kim
@ 2020-06-30  4:23       ` Grant Jung
  2020-07-02  2:11         ` Kiwoong Kim
  0 siblings, 1 reply; 5+ messages in thread
From: Grant Jung @ 2020-06-30  4:23 UTC (permalink / raw)
  To: 'Kiwoong Kim', linux-scsi

> Currently, UFS driver checks if fDeviceInit is cleared at several times,
> not period. This patch is to wait its completion with the period, not
> retrying.
> Many device vendors usually provides the specification on it with just
> period, not a combination of a number of retrying and period. So it could
> be proper to regard to the information coming from device vendors.
> 
> I first added one device specific value regarding the information.
> 
> Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com>
> ---
>  drivers/scsi/ufs/ufshcd.c | 36 ++++++++++++++++++++++++------------
>  1 file changed, 24 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index
> 7b6f13a..27afdf0 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -208,6 +208,7 @@ static struct ufs_dev_fix ufs_fixups[] = {  };
> 
>  static const struct ufs_dev_value ufs_dev_values[] = {
> +	{UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL, DEV_VAL_FDEVICEINIT, 2000,
> false},
>  	{0, 0, 0, 0, false},
>  };
> 
> @@ -4162,9 +4163,12 @@ EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode);
>   */
>  static int ufshcd_complete_dev_init(struct ufs_hba *hba)  {
> -	int i;
> +	u32 dev_init_compl_in_ms = 500;

I think default timeout value is too small. Most UFS vendors which are Samsung, Kioxia, SKHynix, Micron and WD want to set more than 1 seconds for a worst case of fdeviceinit. We need to add many quirks for every ufs vendors if the default value is 500ms.

> +	unsigned long timeout;
>  	int err;
>  	bool flag_res = true;
> +	bool is_dev_val;
> +	u32 val;
> 
>  	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
>  		QUERY_FLAG_IDN_FDEVICEINIT, 0, NULL); @@ -4175,20 +4179,28
> @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba)
>  		goto out;
>  	}
> 
> -	/* 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, 0, &flag_res);
> +	/* Poll fDeviceInit flag to be cleared */
> +	is_dev_val = ufs_get_dev_specific_value(hba, DEV_VAL_FDEVICEINIT,
> &val);
> +	dev_init_compl_in_ms = (is_dev_val) ? val : 500;
> +	timeout = jiffies + msecs_to_jiffies(dev_init_compl_in_ms);
> +	do {
> +		err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,
> +					QUERY_FLAG_IDN_FDEVICEINIT, 0,
> &flag_res);
> +		if (!flag_res)
> +			break;
> +		usleep_range(1000, 2000);

How about think to increase the value of usleep() to 5 ~ 10ms. I think 1 ~ 2ms is too small.

> +	} while (time_before(jiffies, timeout));
> 
> -	if (err)
> +	if (err) {
>  		dev_err(hba->dev,
> -			"%s reading fDeviceInit flag failed with error %d\n",
> -			__func__, err);
> -	else if (flag_res)
> +				"%s reading fDeviceInit flag failed with
> error %d\n",
> +				__func__, err);
> +	} else if (flag_res) {
>  		dev_err(hba->dev,
> -			"%s fDeviceInit was not cleared by the device\n",
> -			__func__);
> -
> +				"%s fDeviceInit was not cleared by the
> device\n",
> +				__func__);
> +		err = -EBUSY;
> +	}
>  out:
>  	return err;
>  }
> --
> 2.7.4

Thanks for this patch. We are changing this code and value for all projects.
Fdeviceinit fail is one of most frequently happened defects. So it's important to set with proper value.

BR
Grant


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

* RE: [RFC PATCH v2 2/2] ufs: change the way to complete fDeviceInit
  2020-06-30  4:23       ` Grant Jung
@ 2020-07-02  2:11         ` Kiwoong Kim
  0 siblings, 0 replies; 5+ messages in thread
From: Kiwoong Kim @ 2020-07-02  2:11 UTC (permalink / raw)
  To: 'Grant Jung', linux-scsi

> > Currently, UFS driver checks if fDeviceInit is cleared at several
> > times, not period. This patch is to wait its completion with the
> > period, not retrying.
> > Many device vendors usually provides the specification on it with just
> > period, not a combination of a number of retrying and period. So it
> > could be proper to regard to the information coming from device vendors.
> >
> > I first added one device specific value regarding the information.
> >
> > Signed-off-by: Kiwoong Kim <kwmad.kim@samsung.com>
> > ---
> >  drivers/scsi/ufs/ufshcd.c | 36 ++++++++++++++++++++++++------------
> >  1 file changed, 24 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index
> > 7b6f13a..27afdf0 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -208,6 +208,7 @@ static struct ufs_dev_fix ufs_fixups[] = {  };
> >
> >  static const struct ufs_dev_value ufs_dev_values[] = {
> > +	{UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL, DEV_VAL_FDEVICEINIT, 2000,
> > false},
> >  	{0, 0, 0, 0, false},
> >  };
> >
> > @@ -4162,9 +4163,12 @@ EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode);
> >   */
> >  static int ufshcd_complete_dev_init(struct ufs_hba *hba)  {
> > -	int i;
> > +	u32 dev_init_compl_in_ms = 500;
> 
> I think default timeout value is too small. Most UFS vendors which are
> Samsung, Kioxia, SKHynix, Micron and WD want to set more than 1 seconds
> for a worst case of fdeviceinit. We need to add many quirks for every ufs
> vendors if the default value is 500ms.
> 
> > +	unsigned long timeout;
> >  	int err;
> >  	bool flag_res = true;
> > +	bool is_dev_val;
> > +	u32 val;
> >
> >  	err = ufshcd_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG,
> >  		QUERY_FLAG_IDN_FDEVICEINIT, 0, NULL); @@ -4175,20 +4179,28
> @@
> > static int ufshcd_complete_dev_init(struct ufs_hba *hba)
> >  		goto out;
> >  	}
> >
> > -	/* 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, 0, &flag_res);
> > +	/* Poll fDeviceInit flag to be cleared */
> > +	is_dev_val = ufs_get_dev_specific_value(hba, DEV_VAL_FDEVICEINIT,
> > &val);
> > +	dev_init_compl_in_ms = (is_dev_val) ? val : 500;
> > +	timeout = jiffies + msecs_to_jiffies(dev_init_compl_in_ms);
> > +	do {
> > +		err = ufshcd_query_flag(hba, UPIU_QUERY_OPCODE_READ_FLAG,
> > +					QUERY_FLAG_IDN_FDEVICEINIT, 0,
> > &flag_res);
> > +		if (!flag_res)
> > +			break;
> > +		usleep_range(1000, 2000);
> 
> How about think to increase the value of usleep() to 5 ~ 10ms. I think 1 ~
> 2ms is too small.
> 
> > +	} while (time_before(jiffies, timeout));
> >
> > -	if (err)
> > +	if (err) {
> >  		dev_err(hba->dev,
> > -			"%s reading fDeviceInit flag failed with error %d\n",
> > -			__func__, err);
> > -	else if (flag_res)
> > +				"%s reading fDeviceInit flag failed with
> > error %d\n",
> > +				__func__, err);
> > +	} else if (flag_res) {
> >  		dev_err(hba->dev,
> > -			"%s fDeviceInit was not cleared by the device\n",
> > -			__func__);
> > -
> > +				"%s fDeviceInit was not cleared by the
> > device\n",
> > +				__func__);
> > +		err = -EBUSY;
> > +	}
> >  out:
> >  	return err;
> >  }
> > --
> > 2.7.4
> 
> Thanks for this patch. We are changing this code and value for all
> projects.
> Fdeviceinit fail is one of most frequently happened defects. So it's
> important to set with proper value.
> 
> BR
> Grant

Got it.

Thanks.
Kiwoong Kim


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

end of thread, other threads:[~2020-07-02  2:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20200629102343epcas2p4d8f4d92c18c5e692038c7e360ab2d819@epcas2p4.samsung.com>
2020-06-29 10:15 ` [RFC PATCH v2 0/2] ufs: support various values per device Kiwoong Kim
     [not found]   ` <CGME20200629102350epcas2p4f4ef326c55c897479643ebcd3e132f50@epcas2p4.samsung.com>
2020-06-29 10:15     ` [RFC PATCH v2 1/2] " Kiwoong Kim
     [not found]   ` <CGME20200629102355epcas2p13f8714a906291e5444adfb2f5ac2c469@epcas2p1.samsung.com>
2020-06-29 10:15     ` [RFC PATCH v2 2/2] ufs: change the way to complete fDeviceInit Kiwoong Kim
2020-06-30  4:23       ` Grant Jung
2020-07-02  2:11         ` Kiwoong Kim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.