linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature
@ 2020-11-03 14:14 Adrian Hunter
  2020-11-03 14:14 ` [PATCH V4 1/2] " Adrian Hunter
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Adrian Hunter @ 2020-11-03 14:14 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, linux-kernel, Alim Akhtar, Avri Altman, Bean Huo,
	Can Guo, Stanley Chu

Hi

Here is V4 of the DeepSleep feature patches.


Changes in V4:
	Rebased
	Added new patch "scsi: ufs: Allow an error return value from ->device_reset()"

Changes in V3:
	Updated sysfs doc for rpm_lvl and spm_lvl

Changes in V2:
	Fix SSU command IMMED setting and consequently drop patch 2.


Adrian Hunter (2):
      scsi: ufs: Add DeepSleep feature
      scsi: ufs: Allow an error return value from ->device_reset()

 Documentation/ABI/testing/sysfs-driver-ufs | 34 +++++++++++++++-----------
 drivers/scsi/ufs/ufs-mediatek.c            |  4 ++-
 drivers/scsi/ufs/ufs-qcom.c                |  6 +++--
 drivers/scsi/ufs/ufs-sysfs.c               |  7 ++++++
 drivers/scsi/ufs/ufs.h                     |  1 +
 drivers/scsi/ufs/ufshcd.c                  | 39 ++++++++++++++++++++++++++++--
 drivers/scsi/ufs/ufshcd.h                  | 28 +++++++++++++++++----
 include/trace/events/ufs.h                 |  3 ++-
 8 files changed, 97 insertions(+), 25 deletions(-)


Regards
Adrian

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

* [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-03 14:14 [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature Adrian Hunter
@ 2020-11-03 14:14 ` Adrian Hunter
  2020-11-04  8:04   ` Can Guo
                     ` (4 more replies)
  2020-11-03 14:14 ` [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset() Adrian Hunter
                   ` (2 subsequent siblings)
  3 siblings, 5 replies; 18+ messages in thread
From: Adrian Hunter @ 2020-11-03 14:14 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, linux-kernel, Alim Akhtar, Avri Altman, Bean Huo,
	Can Guo, Stanley Chu

DeepSleep is a UFS v3.1 feature that achieves the lowest power consumption
of the device, apart from power off.

In DeepSleep mode, no commands are accepted, and the only way to exit is
using a hardware reset or power cycle.

This patch assumes that if a power cycle was an option, then power off
would be preferable, so only exit via a hardware reset is supported.

Drivers that wish to support DeepSleep need to set a new capability flag
UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing
 ->device_reset() callback.

It is assumed that UFS devices with wspecversion >= 0x310 support
DeepSleep.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 Documentation/ABI/testing/sysfs-driver-ufs | 34 +++++++++++--------
 drivers/scsi/ufs/ufs-sysfs.c               |  7 ++++
 drivers/scsi/ufs/ufs.h                     |  1 +
 drivers/scsi/ufs/ufshcd.c                  | 39 ++++++++++++++++++++--
 drivers/scsi/ufs/ufshcd.h                  | 17 +++++++++-
 include/trace/events/ufs.h                 |  3 +-
 6 files changed, 83 insertions(+), 18 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
index adc0d0e91607..e77fa784d6d8 100644
--- a/Documentation/ABI/testing/sysfs-driver-ufs
+++ b/Documentation/ABI/testing/sysfs-driver-ufs
@@ -916,21 +916,24 @@ Date:		September 2014
 Contact:	Subhash Jadavani <subhashj@codeaurora.org>
 Description:	This entry could be used to set or show the UFS device
 		runtime power management level. The current driver
-		implementation supports 6 levels with next target states:
+		implementation supports 7 levels with next target states:
 
 		==  ====================================================
-		0   an UFS device will stay active, an UIC link will
+		0   UFS device will stay active, UIC link will
 		    stay active
-		1   an UFS device will stay active, an UIC link will
+		1   UFS device will stay active, UIC link will
 		    hibernate
-		2   an UFS device will moved to sleep, an UIC link will
+		2   UFS device will be moved to sleep, UIC link will
 		    stay active
-		3   an UFS device will moved to sleep, an UIC link will
+		3   UFS device will be moved to sleep, UIC link will
 		    hibernate
-		4   an UFS device will be powered off, an UIC link will
+		4   UFS device will be powered off, UIC link will
 		    hibernate
-		5   an UFS device will be powered off, an UIC link will
+		5   UFS device will be powered off, UIC link will
 		    be powered off
+		6   UFS device will be moved to deep sleep, UIC link
+		will be powered off. Note, deep sleep might not be
+		supported in which case this value will not be accepted
 		==  ====================================================
 
 What:		/sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
@@ -954,21 +957,24 @@ Date:		September 2014
 Contact:	Subhash Jadavani <subhashj@codeaurora.org>
 Description:	This entry could be used to set or show the UFS device
 		system power management level. The current driver
-		implementation supports 6 levels with next target states:
+		implementation supports 7 levels with next target states:
 
 		==  ====================================================
-		0   an UFS device will stay active, an UIC link will
+		0   UFS device will stay active, UIC link will
 		    stay active
-		1   an UFS device will stay active, an UIC link will
+		1   UFS device will stay active, UIC link will
 		    hibernate
-		2   an UFS device will moved to sleep, an UIC link will
+		2   UFS device will be moved to sleep, UIC link will
 		    stay active
-		3   an UFS device will moved to sleep, an UIC link will
+		3   UFS device will be moved to sleep, UIC link will
 		    hibernate
-		4   an UFS device will be powered off, an UIC link will
+		4   UFS device will be powered off, UIC link will
 		    hibernate
-		5   an UFS device will be powered off, an UIC link will
+		5   UFS device will be powered off, UIC link will
 		    be powered off
+		6   UFS device will be moved to deep sleep, UIC link
+		will be powered off. Note, deep sleep might not be
+		supported in which case this value will not be accepted
 		==  ====================================================
 
 What:		/sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index bdcd27faa054..08e72b7eef6a 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -28,6 +28,7 @@ static const char *ufschd_ufs_dev_pwr_mode_to_string(
 	case UFS_ACTIVE_PWR_MODE:	return "ACTIVE";
 	case UFS_SLEEP_PWR_MODE:	return "SLEEP";
 	case UFS_POWERDOWN_PWR_MODE:	return "POWERDOWN";
+	case UFS_DEEPSLEEP_PWR_MODE:	return "DEEPSLEEP";
 	default:			return "UNKNOWN";
 	}
 }
@@ -38,6 +39,7 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
 					     bool rpm)
 {
 	struct ufs_hba *hba = dev_get_drvdata(dev);
+	struct ufs_dev_info *dev_info = &hba->dev_info;
 	unsigned long flags, value;
 
 	if (kstrtoul(buf, 0, &value))
@@ -46,6 +48,11 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
 	if (value >= UFS_PM_LVL_MAX)
 		return -EINVAL;
 
+	if (ufs_pm_lvl_states[value].dev_state == UFS_DEEPSLEEP_PWR_MODE &&
+	    (!(hba->caps & UFSHCD_CAP_DEEPSLEEP) ||
+	     !(dev_info->wspecversion >= 0x310)))
+		return -EINVAL;
+
 	spin_lock_irqsave(hba->host->host_lock, flags);
 	if (rpm)
 		hba->rpm_lvl = value;
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index f8ab16f30fdc..d593edb48767 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -442,6 +442,7 @@ enum ufs_dev_pwr_mode {
 	UFS_ACTIVE_PWR_MODE	= 1,
 	UFS_SLEEP_PWR_MODE	= 2,
 	UFS_POWERDOWN_PWR_MODE	= 3,
+	UFS_DEEPSLEEP_PWR_MODE	= 4,
 };
 
 #define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2309253d3101..ee083b96e405 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -163,6 +163,11 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
 	{UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE},
 	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE},
 	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE},
+	/*
+	 * For DeepSleep, the link is first put in hibern8 and then off.
+	 * Leaving the link in hibern8 is not supported.
+	 */
+	{UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE},
 };
 
 static inline enum ufs_dev_pwr_mode
@@ -8297,7 +8302,8 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba,
 	}
 	/*
 	 * If autobkops is enabled, link can't be turned off because
-	 * turning off the link would also turn off the device.
+	 * turning off the link would also turn off the device, except in the
+	 * case of DeepSleep where the device is expected to remain powered.
 	 */
 	else if ((req_link_state == UIC_LINK_OFF_STATE) &&
 		 (!check_for_bkops || !hba->auto_bkops_enabled)) {
@@ -8307,6 +8313,9 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba,
 		 * put the link in low power mode is to send the DME end point
 		 * to device and then send the DME reset command to local
 		 * unipro. But putting the link in hibern8 is much faster.
+		 *
+		 * Note also that putting the link in Hibern8 is a requirement
+		 * for entering DeepSleep.
 		 */
 		ret = ufshcd_uic_hibern8_enter(hba);
 		if (ret) {
@@ -8439,6 +8448,7 @@ static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba)
 static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 {
 	int ret = 0;
+	int check_for_bkops;
 	enum ufs_pm_level pm_lvl;
 	enum ufs_dev_pwr_mode req_dev_pwr_mode;
 	enum uic_link_state req_link_state;
@@ -8524,7 +8534,13 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 	}
 
 	flush_work(&hba->eeh_work);
-	ret = ufshcd_link_state_transition(hba, req_link_state, 1);
+
+	/*
+	 * In the case of DeepSleep, the device is expected to remain powered
+	 * with the link off, so do not check for bkops.
+	 */
+	check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
+	ret = ufshcd_link_state_transition(hba, req_link_state, check_for_bkops);
 	if (ret)
 		goto set_dev_active;
 
@@ -8565,11 +8581,25 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 	if (hba->clk_scaling.is_allowed)
 		ufshcd_resume_clkscaling(hba);
 	ufshcd_vreg_set_hpm(hba);
+	/*
+	 * Device hardware reset is required to exit DeepSleep. Also, for
+	 * DeepSleep, the link is off so host reset and restore will be done
+	 * further below.
+	 */
+	if (ufshcd_is_ufs_dev_deepsleep(hba)) {
+		ufshcd_vops_device_reset(hba);
+		WARN_ON(!ufshcd_is_link_off(hba));
+	}
 	if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba))
 		ufshcd_set_link_active(hba);
 	else if (ufshcd_is_link_off(hba))
 		ufshcd_host_reset_and_restore(hba);
 set_dev_active:
+	/* Can also get here needing to exit DeepSleep */
+	if (ufshcd_is_ufs_dev_deepsleep(hba)) {
+		ufshcd_vops_device_reset(hba);
+		ufshcd_host_reset_and_restore(hba);
+	}
 	if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE))
 		ufshcd_disable_auto_bkops(hba);
 enable_gating:
@@ -8631,6 +8661,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 	if (ret)
 		goto disable_vreg;
 
+	/* For DeepSleep, the only supported option is to have the link off */
+	WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && !ufshcd_is_link_off(hba));
+
 	if (ufshcd_is_link_hibern8(hba)) {
 		ret = ufshcd_uic_hibern8_exit(hba);
 		if (!ret) {
@@ -8644,6 +8677,8 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 		/*
 		 * A full initialization of the host and the device is
 		 * required since the link was put to off during suspend.
+		 * Note, in the case of DeepSleep, the device will exit
+		 * DeepSleep due to device reset.
 		 */
 		ret = ufshcd_reset_and_restore(hba);
 		/*
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 0fbb735bb70c..213be0667b59 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -114,16 +114,22 @@ enum uic_link_state {
 	((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
 #define ufshcd_set_ufs_dev_poweroff(h) \
 	((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
+#define ufshcd_set_ufs_dev_deepsleep(h) \
+	((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE)
 #define ufshcd_is_ufs_dev_active(h) \
 	((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
 #define ufshcd_is_ufs_dev_sleep(h) \
 	((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
 #define ufshcd_is_ufs_dev_poweroff(h) \
 	((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
+#define ufshcd_is_ufs_dev_deepsleep(h) \
+	((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE)
 
 /*
  * UFS Power management levels.
- * Each level is in increasing order of power savings.
+ * Each level is in increasing order of power savings, except DeepSleep
+ * which is lower than PowerDown with power on but not PowerDown with
+ * power off.
  */
 enum ufs_pm_level {
 	UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */
@@ -132,6 +138,7 @@ enum ufs_pm_level {
 	UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */
 	UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE */
 	UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */
+	UFS_PM_LVL_6, /* UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE */
 	UFS_PM_LVL_MAX
 };
 
@@ -599,6 +606,14 @@ enum ufshcd_caps {
 	 * This would increase power savings.
 	 */
 	UFSHCD_CAP_AGGR_POWER_COLLAPSE			= 1 << 9,
+
+	/*
+	 * This capability allows the host controller driver to use DeepSleep,
+	 * if it is supported by the UFS device. The host controller driver must
+	 * support device hardware reset via the hba->device_reset() callback,
+	 * in order to exit DeepSleep state.
+	 */
+	UFSHCD_CAP_DEEPSLEEP				= 1 << 10,
 };
 
 struct ufs_hba_variant_params {
diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h
index 84841b3a7ffd..2362244c2a9e 100644
--- a/include/trace/events/ufs.h
+++ b/include/trace/events/ufs.h
@@ -19,7 +19,8 @@
 #define UFS_PWR_MODES			\
 	EM(UFS_ACTIVE_PWR_MODE)		\
 	EM(UFS_SLEEP_PWR_MODE)		\
-	EMe(UFS_POWERDOWN_PWR_MODE)
+	EM(UFS_POWERDOWN_PWR_MODE)	\
+	EMe(UFS_DEEPSLEEP_PWR_MODE)
 
 #define UFSCHD_CLK_GATING_STATES	\
 	EM(CLKS_OFF)			\
-- 
2.17.1


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

* [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset()
  2020-11-03 14:14 [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature Adrian Hunter
  2020-11-03 14:14 ` [PATCH V4 1/2] " Adrian Hunter
@ 2020-11-03 14:14 ` Adrian Hunter
  2020-11-04  2:55   ` Stanley Chu
                     ` (3 more replies)
  2020-11-05  4:06 ` [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature Martin K. Petersen
  2020-11-11  2:58 ` Martin K. Petersen
  3 siblings, 4 replies; 18+ messages in thread
From: Adrian Hunter @ 2020-11-03 14:14 UTC (permalink / raw)
  To: Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, linux-kernel, Alim Akhtar, Avri Altman, Bean Huo,
	Can Guo, Stanley Chu

It is simpler for drivers to provide a ->device_reset() callback
irrespective of whether the GPIO, or firmware interface necessary to do the
reset, is discovered during probe.

Change ->device_reset() to return an error code.  Drivers that provide
the callback, but do not do the reset operation should return -EOPNOTSUPP.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 drivers/scsi/ufs/ufs-mediatek.c |  4 +++-
 drivers/scsi/ufs/ufs-qcom.c     |  6 ++++--
 drivers/scsi/ufs/ufshcd.h       | 11 +++++++----
 3 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
index 8df73bc2f8cb..914a827a93ee 100644
--- a/drivers/scsi/ufs/ufs-mediatek.c
+++ b/drivers/scsi/ufs/ufs-mediatek.c
@@ -743,7 +743,7 @@ static int ufs_mtk_link_startup_notify(struct ufs_hba *hba,
 	return ret;
 }
 
-static void ufs_mtk_device_reset(struct ufs_hba *hba)
+static int ufs_mtk_device_reset(struct ufs_hba *hba)
 {
 	struct arm_smccc_res res;
 
@@ -764,6 +764,8 @@ static void ufs_mtk_device_reset(struct ufs_hba *hba)
 	usleep_range(10000, 15000);
 
 	dev_info(hba->dev, "device reset done\n");
+
+	return 0;
 }
 
 static int ufs_mtk_link_set_hpm(struct ufs_hba *hba)
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 9a19c6d15d3b..357c3b49321d 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -1422,13 +1422,13 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
  *
  * Toggles the (optional) reset line to reset the attached device.
  */
-static void ufs_qcom_device_reset(struct ufs_hba *hba)
+static int ufs_qcom_device_reset(struct ufs_hba *hba)
 {
 	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
 
 	/* reset gpio is optional */
 	if (!host->device_reset)
-		return;
+		return -EOPNOTSUPP;
 
 	/*
 	 * The UFS device shall detect reset pulses of 1us, sleep for 10us to
@@ -1439,6 +1439,8 @@ static void ufs_qcom_device_reset(struct ufs_hba *hba)
 
 	gpiod_set_value_cansleep(host->device_reset, 0);
 	usleep_range(10, 15);
+
+	return 0;
 }
 
 #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 213be0667b59..5191d87f6263 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -323,7 +323,7 @@ struct ufs_hba_variant_ops {
 	int     (*resume)(struct ufs_hba *, enum ufs_pm_op);
 	void	(*dbg_register_dump)(struct ufs_hba *hba);
 	int	(*phy_initialization)(struct ufs_hba *);
-	void	(*device_reset)(struct ufs_hba *hba);
+	int	(*device_reset)(struct ufs_hba *hba);
 	void	(*config_scaling_param)(struct ufs_hba *hba,
 					struct devfreq_dev_profile *profile,
 					void *data);
@@ -1207,9 +1207,12 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
 static inline void ufshcd_vops_device_reset(struct ufs_hba *hba)
 {
 	if (hba->vops && hba->vops->device_reset) {
-		hba->vops->device_reset(hba);
-		ufshcd_set_ufs_dev_active(hba);
-		ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0);
+		int err = hba->vops->device_reset(hba);
+
+		if (!err)
+			ufshcd_set_ufs_dev_active(hba);
+		if (err != -EOPNOTSUPP)
+			ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, err);
 	}
 }
 
-- 
2.17.1


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

* Re: [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset()
  2020-11-03 14:14 ` [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset() Adrian Hunter
@ 2020-11-04  2:55   ` Stanley Chu
  2020-11-04  8:05   ` Can Guo
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 18+ messages in thread
From: Stanley Chu @ 2020-11-04  2:55 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Martin K . Petersen, James E . J . Bottomley, linux-scsi,
	linux-kernel, Alim Akhtar, Avri Altman, Bean Huo, Can Guo

Hi Adrian,

On Tue, 2020-11-03 at 16:14 +0200, Adrian Hunter wrote:
> It is simpler for drivers to provide a ->device_reset() callback
> irrespective of whether the GPIO, or firmware interface necessary to do the
> reset, is discovered during probe.
> 
> Change ->device_reset() to return an error code.  Drivers that provide
> the callback, but do not do the reset operation should return -EOPNOTSUPP.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
>  drivers/scsi/ufs/ufs-mediatek.c |  4 +++-
>  drivers/scsi/ufs/ufs-qcom.c     |  6 ++++--
>  drivers/scsi/ufs/ufshcd.h       | 11 +++++++----
>  3 files changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
> index 8df73bc2f8cb..914a827a93ee 100644
> --- a/drivers/scsi/ufs/ufs-mediatek.c
> +++ b/drivers/scsi/ufs/ufs-mediatek.c
> @@ -743,7 +743,7 @@ static int ufs_mtk_link_startup_notify(struct ufs_hba *hba,
>  	return ret;
>  }
>  
> -static void ufs_mtk_device_reset(struct ufs_hba *hba)
> +static int ufs_mtk_device_reset(struct ufs_hba *hba)
>  {
>  	struct arm_smccc_res res;
>  
> @@ -764,6 +764,8 @@ static void ufs_mtk_device_reset(struct ufs_hba *hba)
>  	usleep_range(10000, 15000);
>  
>  	dev_info(hba->dev, "device reset done\n");
> +
> +	return 0;
>  }
>  
>  static int ufs_mtk_link_set_hpm(struct ufs_hba *hba)
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 9a19c6d15d3b..357c3b49321d 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -1422,13 +1422,13 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
>   *
>   * Toggles the (optional) reset line to reset the attached device.
>   */
> -static void ufs_qcom_device_reset(struct ufs_hba *hba)
> +static int ufs_qcom_device_reset(struct ufs_hba *hba)
>  {
>  	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>  
>  	/* reset gpio is optional */
>  	if (!host->device_reset)
> -		return;
> +		return -EOPNOTSUPP;
>  
>  	/*
>  	 * The UFS device shall detect reset pulses of 1us, sleep for 10us to
> @@ -1439,6 +1439,8 @@ static void ufs_qcom_device_reset(struct ufs_hba *hba)
>  
>  	gpiod_set_value_cansleep(host->device_reset, 0);
>  	usleep_range(10, 15);
> +
> +	return 0;
>  }
>  
>  #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 213be0667b59..5191d87f6263 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -323,7 +323,7 @@ struct ufs_hba_variant_ops {
>  	int     (*resume)(struct ufs_hba *, enum ufs_pm_op);
>  	void	(*dbg_register_dump)(struct ufs_hba *hba);
>  	int	(*phy_initialization)(struct ufs_hba *);
> -	void	(*device_reset)(struct ufs_hba *hba);
> +	int	(*device_reset)(struct ufs_hba *hba);
>  	void	(*config_scaling_param)(struct ufs_hba *hba,
>  					struct devfreq_dev_profile *profile,
>  					void *data);
> @@ -1207,9 +1207,12 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
>  static inline void ufshcd_vops_device_reset(struct ufs_hba *hba)
>  {
>  	if (hba->vops && hba->vops->device_reset) {
> -		hba->vops->device_reset(hba);
> -		ufshcd_set_ufs_dev_active(hba);
> -		ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0);
> +		int err = hba->vops->device_reset(hba);
> +
> +		if (!err)
> +			ufshcd_set_ufs_dev_active(hba);
> +		if (err != -EOPNOTSUPP)
> +			ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, err);
>  	}
>  }

For ufs-mediatek part and related flow,

Reviewed-by: Stanley Chu <stanley.chu@mediatek.com>


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

* Re: [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-03 14:14 ` [PATCH V4 1/2] " Adrian Hunter
@ 2020-11-04  8:04   ` Can Guo
  2020-11-04  8:29   ` Can Guo
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 18+ messages in thread
From: Can Guo @ 2020-11-04  8:04 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Martin K . Petersen, James E . J . Bottomley, linux-scsi,
	linux-kernel, Alim Akhtar, Avri Altman, Bean Huo, Stanley Chu

On 2020-11-03 22:14, Adrian Hunter wrote:
> DeepSleep is a UFS v3.1 feature that achieves the lowest power 
> consumption
> of the device, apart from power off.
> 
> In DeepSleep mode, no commands are accepted, and the only way to exit 
> is
> using a hardware reset or power cycle.
> 
> This patch assumes that if a power cycle was an option, then power off
> would be preferable, so only exit via a hardware reset is supported.
> 
> Drivers that wish to support DeepSleep need to set a new capability 
> flag
> UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing
>  ->device_reset() callback.
> 
> It is assumed that UFS devices with wspecversion >= 0x310 support
> DeepSleep.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>

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

> ---
>  Documentation/ABI/testing/sysfs-driver-ufs | 34 +++++++++++--------
>  drivers/scsi/ufs/ufs-sysfs.c               |  7 ++++
>  drivers/scsi/ufs/ufs.h                     |  1 +
>  drivers/scsi/ufs/ufshcd.c                  | 39 ++++++++++++++++++++--
>  drivers/scsi/ufs/ufshcd.h                  | 17 +++++++++-
>  include/trace/events/ufs.h                 |  3 +-
>  6 files changed, 83 insertions(+), 18 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
> b/Documentation/ABI/testing/sysfs-driver-ufs
> index adc0d0e91607..e77fa784d6d8 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -916,21 +916,24 @@ Date:		September 2014
>  Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>  Description:	This entry could be used to set or show the UFS device
>  		runtime power management level. The current driver
> -		implementation supports 6 levels with next target states:
> +		implementation supports 7 levels with next target states:
> 
>  		==  ====================================================
> -		0   an UFS device will stay active, an UIC link will
> +		0   UFS device will stay active, UIC link will
>  		    stay active
> -		1   an UFS device will stay active, an UIC link will
> +		1   UFS device will stay active, UIC link will
>  		    hibernate
> -		2   an UFS device will moved to sleep, an UIC link will
> +		2   UFS device will be moved to sleep, UIC link will
>  		    stay active
> -		3   an UFS device will moved to sleep, an UIC link will
> +		3   UFS device will be moved to sleep, UIC link will
>  		    hibernate
> -		4   an UFS device will be powered off, an UIC link will
> +		4   UFS device will be powered off, UIC link will
>  		    hibernate
> -		5   an UFS device will be powered off, an UIC link will
> +		5   UFS device will be powered off, UIC link will
>  		    be powered off
> +		6   UFS device will be moved to deep sleep, UIC link
> +		will be powered off. Note, deep sleep might not be
> +		supported in which case this value will not be accepted
>  		==  ====================================================
> 
>  What:		/sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
> @@ -954,21 +957,24 @@ Date:		September 2014
>  Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>  Description:	This entry could be used to set or show the UFS device
>  		system power management level. The current driver
> -		implementation supports 6 levels with next target states:
> +		implementation supports 7 levels with next target states:
> 
>  		==  ====================================================
> -		0   an UFS device will stay active, an UIC link will
> +		0   UFS device will stay active, UIC link will
>  		    stay active
> -		1   an UFS device will stay active, an UIC link will
> +		1   UFS device will stay active, UIC link will
>  		    hibernate
> -		2   an UFS device will moved to sleep, an UIC link will
> +		2   UFS device will be moved to sleep, UIC link will
>  		    stay active
> -		3   an UFS device will moved to sleep, an UIC link will
> +		3   UFS device will be moved to sleep, UIC link will
>  		    hibernate
> -		4   an UFS device will be powered off, an UIC link will
> +		4   UFS device will be powered off, UIC link will
>  		    hibernate
> -		5   an UFS device will be powered off, an UIC link will
> +		5   UFS device will be powered off, UIC link will
>  		    be powered off
> +		6   UFS device will be moved to deep sleep, UIC link
> +		will be powered off. Note, deep sleep might not be
> +		supported in which case this value will not be accepted
>  		==  ====================================================
> 
>  What:		/sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c 
> b/drivers/scsi/ufs/ufs-sysfs.c
> index bdcd27faa054..08e72b7eef6a 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -28,6 +28,7 @@ static const char *ufschd_ufs_dev_pwr_mode_to_string(
>  	case UFS_ACTIVE_PWR_MODE:	return "ACTIVE";
>  	case UFS_SLEEP_PWR_MODE:	return "SLEEP";
>  	case UFS_POWERDOWN_PWR_MODE:	return "POWERDOWN";
> +	case UFS_DEEPSLEEP_PWR_MODE:	return "DEEPSLEEP";
>  	default:			return "UNKNOWN";
>  	}
>  }
> @@ -38,6 +39,7 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct
> device *dev,
>  					     bool rpm)
>  {
>  	struct ufs_hba *hba = dev_get_drvdata(dev);
> +	struct ufs_dev_info *dev_info = &hba->dev_info;
>  	unsigned long flags, value;
> 
>  	if (kstrtoul(buf, 0, &value))
> @@ -46,6 +48,11 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct
> device *dev,
>  	if (value >= UFS_PM_LVL_MAX)
>  		return -EINVAL;
> 
> +	if (ufs_pm_lvl_states[value].dev_state == UFS_DEEPSLEEP_PWR_MODE &&
> +	    (!(hba->caps & UFSHCD_CAP_DEEPSLEEP) ||
> +	     !(dev_info->wspecversion >= 0x310)))
> +		return -EINVAL;
> +
>  	spin_lock_irqsave(hba->host->host_lock, flags);
>  	if (rpm)
>  		hba->rpm_lvl = value;
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index f8ab16f30fdc..d593edb48767 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -442,6 +442,7 @@ enum ufs_dev_pwr_mode {
>  	UFS_ACTIVE_PWR_MODE	= 1,
>  	UFS_SLEEP_PWR_MODE	= 2,
>  	UFS_POWERDOWN_PWR_MODE	= 3,
> +	UFS_DEEPSLEEP_PWR_MODE	= 4,
>  };
> 
>  #define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10)
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 2309253d3101..ee083b96e405 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -163,6 +163,11 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
>  	{UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>  	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>  	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE},
> +	/*
> +	 * For DeepSleep, the link is first put in hibern8 and then off.
> +	 * Leaving the link in hibern8 is not supported.
> +	 */
> +	{UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE},
>  };
> 
>  static inline enum ufs_dev_pwr_mode
> @@ -8297,7 +8302,8 @@ static int ufshcd_link_state_transition(struct
> ufs_hba *hba,
>  	}
>  	/*
>  	 * If autobkops is enabled, link can't be turned off because
> -	 * turning off the link would also turn off the device.
> +	 * turning off the link would also turn off the device, except in the
> +	 * case of DeepSleep where the device is expected to remain powered.
>  	 */
>  	else if ((req_link_state == UIC_LINK_OFF_STATE) &&
>  		 (!check_for_bkops || !hba->auto_bkops_enabled)) {
> @@ -8307,6 +8313,9 @@ static int ufshcd_link_state_transition(struct
> ufs_hba *hba,
>  		 * put the link in low power mode is to send the DME end point
>  		 * to device and then send the DME reset command to local
>  		 * unipro. But putting the link in hibern8 is much faster.
> +		 *
> +		 * Note also that putting the link in Hibern8 is a requirement
> +		 * for entering DeepSleep.
>  		 */
>  		ret = ufshcd_uic_hibern8_enter(hba);
>  		if (ret) {
> @@ -8439,6 +8448,7 @@ static void ufshcd_hba_vreg_set_hpm(struct 
> ufs_hba *hba)
>  static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>  {
>  	int ret = 0;
> +	int check_for_bkops;
>  	enum ufs_pm_level pm_lvl;
>  	enum ufs_dev_pwr_mode req_dev_pwr_mode;
>  	enum uic_link_state req_link_state;
> @@ -8524,7 +8534,13 @@ static int ufshcd_suspend(struct ufs_hba *hba,
> enum ufs_pm_op pm_op)
>  	}
> 
>  	flush_work(&hba->eeh_work);
> -	ret = ufshcd_link_state_transition(hba, req_link_state, 1);
> +
> +	/*
> +	 * In the case of DeepSleep, the device is expected to remain powered
> +	 * with the link off, so do not check for bkops.
> +	 */
> +	check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
> +	ret = ufshcd_link_state_transition(hba, req_link_state, 
> check_for_bkops);
>  	if (ret)
>  		goto set_dev_active;
> 
> @@ -8565,11 +8581,25 @@ static int ufshcd_suspend(struct ufs_hba *hba,
> enum ufs_pm_op pm_op)
>  	if (hba->clk_scaling.is_allowed)
>  		ufshcd_resume_clkscaling(hba);
>  	ufshcd_vreg_set_hpm(hba);
> +	/*
> +	 * Device hardware reset is required to exit DeepSleep. Also, for
> +	 * DeepSleep, the link is off so host reset and restore will be done
> +	 * further below.
> +	 */
> +	if (ufshcd_is_ufs_dev_deepsleep(hba)) {
> +		ufshcd_vops_device_reset(hba);
> +		WARN_ON(!ufshcd_is_link_off(hba));
> +	}
>  	if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba))
>  		ufshcd_set_link_active(hba);
>  	else if (ufshcd_is_link_off(hba))
>  		ufshcd_host_reset_and_restore(hba);
>  set_dev_active:
> +	/* Can also get here needing to exit DeepSleep */
> +	if (ufshcd_is_ufs_dev_deepsleep(hba)) {
> +		ufshcd_vops_device_reset(hba);
> +		ufshcd_host_reset_and_restore(hba);
> +	}
>  	if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE))
>  		ufshcd_disable_auto_bkops(hba);
>  enable_gating:
> @@ -8631,6 +8661,9 @@ static int ufshcd_resume(struct ufs_hba *hba,
> enum ufs_pm_op pm_op)
>  	if (ret)
>  		goto disable_vreg;
> 
> +	/* For DeepSleep, the only supported option is to have the link off 
> */
> +	WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && 
> !ufshcd_is_link_off(hba));
> +
>  	if (ufshcd_is_link_hibern8(hba)) {
>  		ret = ufshcd_uic_hibern8_exit(hba);
>  		if (!ret) {
> @@ -8644,6 +8677,8 @@ static int ufshcd_resume(struct ufs_hba *hba,
> enum ufs_pm_op pm_op)
>  		/*
>  		 * A full initialization of the host and the device is
>  		 * required since the link was put to off during suspend.
> +		 * Note, in the case of DeepSleep, the device will exit
> +		 * DeepSleep due to device reset.
>  		 */
>  		ret = ufshcd_reset_and_restore(hba);
>  		/*
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 0fbb735bb70c..213be0667b59 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -114,16 +114,22 @@ enum uic_link_state {
>  	((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
>  #define ufshcd_set_ufs_dev_poweroff(h) \
>  	((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
> +#define ufshcd_set_ufs_dev_deepsleep(h) \
> +	((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE)
>  #define ufshcd_is_ufs_dev_active(h) \
>  	((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
>  #define ufshcd_is_ufs_dev_sleep(h) \
>  	((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
>  #define ufshcd_is_ufs_dev_poweroff(h) \
>  	((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
> +#define ufshcd_is_ufs_dev_deepsleep(h) \
> +	((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE)
> 
>  /*
>   * UFS Power management levels.
> - * Each level is in increasing order of power savings.
> + * Each level is in increasing order of power savings, except 
> DeepSleep
> + * which is lower than PowerDown with power on but not PowerDown with
> + * power off.
>   */
>  enum ufs_pm_level {
>  	UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */
> @@ -132,6 +138,7 @@ enum ufs_pm_level {
>  	UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */
>  	UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE */
>  	UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */
> +	UFS_PM_LVL_6, /* UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE */
>  	UFS_PM_LVL_MAX
>  };
> 
> @@ -599,6 +606,14 @@ enum ufshcd_caps {
>  	 * This would increase power savings.
>  	 */
>  	UFSHCD_CAP_AGGR_POWER_COLLAPSE			= 1 << 9,
> +
> +	/*
> +	 * This capability allows the host controller driver to use 
> DeepSleep,
> +	 * if it is supported by the UFS device. The host controller driver 
> must
> +	 * support device hardware reset via the hba->device_reset() 
> callback,
> +	 * in order to exit DeepSleep state.
> +	 */
> +	UFSHCD_CAP_DEEPSLEEP				= 1 << 10,
>  };
> 
>  struct ufs_hba_variant_params {
> diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h
> index 84841b3a7ffd..2362244c2a9e 100644
> --- a/include/trace/events/ufs.h
> +++ b/include/trace/events/ufs.h
> @@ -19,7 +19,8 @@
>  #define UFS_PWR_MODES			\
>  	EM(UFS_ACTIVE_PWR_MODE)		\
>  	EM(UFS_SLEEP_PWR_MODE)		\
> -	EMe(UFS_POWERDOWN_PWR_MODE)
> +	EM(UFS_POWERDOWN_PWR_MODE)	\
> +	EMe(UFS_DEEPSLEEP_PWR_MODE)
> 
>  #define UFSCHD_CLK_GATING_STATES	\
>  	EM(CLKS_OFF)			\

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

* Re: [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset()
  2020-11-03 14:14 ` [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset() Adrian Hunter
  2020-11-04  2:55   ` Stanley Chu
@ 2020-11-04  8:05   ` Can Guo
  2020-11-04  8:44   ` Bean Huo
  2020-11-04 16:35   ` Asutosh Das (asd)
  3 siblings, 0 replies; 18+ messages in thread
From: Can Guo @ 2020-11-04  8:05 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Martin K . Petersen, James E . J . Bottomley, linux-scsi,
	linux-kernel, Alim Akhtar, Avri Altman, Bean Huo, Stanley Chu

On 2020-11-03 22:14, Adrian Hunter wrote:
> It is simpler for drivers to provide a ->device_reset() callback
> irrespective of whether the GPIO, or firmware interface necessary to do 
> the
> reset, is discovered during probe.
> 
> Change ->device_reset() to return an error code.  Drivers that provide
> the callback, but do not do the reset operation should return 
> -EOPNOTSUPP.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>

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

> ---
>  drivers/scsi/ufs/ufs-mediatek.c |  4 +++-
>  drivers/scsi/ufs/ufs-qcom.c     |  6 ++++--
>  drivers/scsi/ufs/ufshcd.h       | 11 +++++++----
>  3 files changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs-mediatek.c 
> b/drivers/scsi/ufs/ufs-mediatek.c
> index 8df73bc2f8cb..914a827a93ee 100644
> --- a/drivers/scsi/ufs/ufs-mediatek.c
> +++ b/drivers/scsi/ufs/ufs-mediatek.c
> @@ -743,7 +743,7 @@ static int ufs_mtk_link_startup_notify(struct 
> ufs_hba *hba,
>  	return ret;
>  }
> 
> -static void ufs_mtk_device_reset(struct ufs_hba *hba)
> +static int ufs_mtk_device_reset(struct ufs_hba *hba)
>  {
>  	struct arm_smccc_res res;
> 
> @@ -764,6 +764,8 @@ static void ufs_mtk_device_reset(struct ufs_hba 
> *hba)
>  	usleep_range(10000, 15000);
> 
>  	dev_info(hba->dev, "device reset done\n");
> +
> +	return 0;
>  }
> 
>  static int ufs_mtk_link_set_hpm(struct ufs_hba *hba)
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 9a19c6d15d3b..357c3b49321d 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -1422,13 +1422,13 @@ static void ufs_qcom_dump_dbg_regs(struct 
> ufs_hba *hba)
>   *
>   * Toggles the (optional) reset line to reset the attached device.
>   */
> -static void ufs_qcom_device_reset(struct ufs_hba *hba)
> +static int ufs_qcom_device_reset(struct ufs_hba *hba)
>  {
>  	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> 
>  	/* reset gpio is optional */
>  	if (!host->device_reset)
> -		return;
> +		return -EOPNOTSUPP;
> 
>  	/*
>  	 * The UFS device shall detect reset pulses of 1us, sleep for 10us to
> @@ -1439,6 +1439,8 @@ static void ufs_qcom_device_reset(struct ufs_hba 
> *hba)
> 
>  	gpiod_set_value_cansleep(host->device_reset, 0);
>  	usleep_range(10, 15);
> +
> +	return 0;
>  }
> 
>  #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 213be0667b59..5191d87f6263 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -323,7 +323,7 @@ struct ufs_hba_variant_ops {
>  	int     (*resume)(struct ufs_hba *, enum ufs_pm_op);
>  	void	(*dbg_register_dump)(struct ufs_hba *hba);
>  	int	(*phy_initialization)(struct ufs_hba *);
> -	void	(*device_reset)(struct ufs_hba *hba);
> +	int	(*device_reset)(struct ufs_hba *hba);
>  	void	(*config_scaling_param)(struct ufs_hba *hba,
>  					struct devfreq_dev_profile *profile,
>  					void *data);
> @@ -1207,9 +1207,12 @@ static inline void
> ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
>  static inline void ufshcd_vops_device_reset(struct ufs_hba *hba)
>  {
>  	if (hba->vops && hba->vops->device_reset) {
> -		hba->vops->device_reset(hba);
> -		ufshcd_set_ufs_dev_active(hba);
> -		ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0);
> +		int err = hba->vops->device_reset(hba);
> +
> +		if (!err)
> +			ufshcd_set_ufs_dev_active(hba);
> +		if (err != -EOPNOTSUPP)
> +			ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, err);
>  	}
>  }

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

* Re: [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-03 14:14 ` [PATCH V4 1/2] " Adrian Hunter
  2020-11-04  8:04   ` Can Guo
@ 2020-11-04  8:29   ` Can Guo
  2020-11-04  8:37     ` Adrian Hunter
  2020-11-04 10:57   ` Bean Huo
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 18+ messages in thread
From: Can Guo @ 2020-11-04  8:29 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Martin K . Petersen, James E . J . Bottomley, linux-scsi,
	linux-kernel, Alim Akhtar, Avri Altman, Bean Huo, Stanley Chu

Hi Adrian,

On 2020-11-03 22:14, Adrian Hunter wrote:
> DeepSleep is a UFS v3.1 feature that achieves the lowest power 
> consumption
> of the device, apart from power off.
> 
> In DeepSleep mode, no commands are accepted, and the only way to exit 
> is
> using a hardware reset or power cycle.
> 
> This patch assumes that if a power cycle was an option, then power off
> would be preferable, so only exit via a hardware reset is supported.
> 
> Drivers that wish to support DeepSleep need to set a new capability 
> flag
> UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing
>  ->device_reset() callback.
> 
> It is assumed that UFS devices with wspecversion >= 0x310 support
> DeepSleep.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
>  Documentation/ABI/testing/sysfs-driver-ufs | 34 +++++++++++--------
>  drivers/scsi/ufs/ufs-sysfs.c               |  7 ++++
>  drivers/scsi/ufs/ufs.h                     |  1 +
>  drivers/scsi/ufs/ufshcd.c                  | 39 ++++++++++++++++++++--
>  drivers/scsi/ufs/ufshcd.h                  | 17 +++++++++-
>  include/trace/events/ufs.h                 |  3 +-
>  6 files changed, 83 insertions(+), 18 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
> b/Documentation/ABI/testing/sysfs-driver-ufs
> index adc0d0e91607..e77fa784d6d8 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -916,21 +916,24 @@ Date:		September 2014
>  Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>  Description:	This entry could be used to set or show the UFS device
>  		runtime power management level. The current driver
> -		implementation supports 6 levels with next target states:
> +		implementation supports 7 levels with next target states:
> 
>  		==  ====================================================
> -		0   an UFS device will stay active, an UIC link will
> +		0   UFS device will stay active, UIC link will
>  		    stay active
> -		1   an UFS device will stay active, an UIC link will
> +		1   UFS device will stay active, UIC link will
>  		    hibernate
> -		2   an UFS device will moved to sleep, an UIC link will
> +		2   UFS device will be moved to sleep, UIC link will
>  		    stay active
> -		3   an UFS device will moved to sleep, an UIC link will
> +		3   UFS device will be moved to sleep, UIC link will
>  		    hibernate
> -		4   an UFS device will be powered off, an UIC link will
> +		4   UFS device will be powered off, UIC link will
>  		    hibernate
> -		5   an UFS device will be powered off, an UIC link will
> +		5   UFS device will be powered off, UIC link will
>  		    be powered off
> +		6   UFS device will be moved to deep sleep, UIC link
> +		will be powered off. Note, deep sleep might not be
> +		supported in which case this value will not be accepted

Nitpicking, usually higher spm/rpm_lvl means better power saving.
Since POWERDOWN+LINKOFF achieves the lowest power consumption, can
we put DEEPSLEEP_LINKOFF to 5, and POWERDOWN_LINKOFF to 6?

Thanks,

Can Guo.

>  		==  ====================================================
> 
>  What:		/sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
> @@ -954,21 +957,24 @@ Date:		September 2014
>  Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>  Description:	This entry could be used to set or show the UFS device
>  		system power management level. The current driver
> -		implementation supports 6 levels with next target states:
> +		implementation supports 7 levels with next target states:
> 
>  		==  ====================================================
> -		0   an UFS device will stay active, an UIC link will
> +		0   UFS device will stay active, UIC link will
>  		    stay active
> -		1   an UFS device will stay active, an UIC link will
> +		1   UFS device will stay active, UIC link will
>  		    hibernate
> -		2   an UFS device will moved to sleep, an UIC link will
> +		2   UFS device will be moved to sleep, UIC link will
>  		    stay active
> -		3   an UFS device will moved to sleep, an UIC link will
> +		3   UFS device will be moved to sleep, UIC link will
>  		    hibernate
> -		4   an UFS device will be powered off, an UIC link will
> +		4   UFS device will be powered off, UIC link will
>  		    hibernate
> -		5   an UFS device will be powered off, an UIC link will
> +		5   UFS device will be powered off, UIC link will
>  		    be powered off
> +		6   UFS device will be moved to deep sleep, UIC link
> +		will be powered off. Note, deep sleep might not be
> +		supported in which case this value will not be accepted
>  		==  ====================================================
> 
>  What:		/sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c 
> b/drivers/scsi/ufs/ufs-sysfs.c
> index bdcd27faa054..08e72b7eef6a 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -28,6 +28,7 @@ static const char *ufschd_ufs_dev_pwr_mode_to_string(
>  	case UFS_ACTIVE_PWR_MODE:	return "ACTIVE";
>  	case UFS_SLEEP_PWR_MODE:	return "SLEEP";
>  	case UFS_POWERDOWN_PWR_MODE:	return "POWERDOWN";
> +	case UFS_DEEPSLEEP_PWR_MODE:	return "DEEPSLEEP";
>  	default:			return "UNKNOWN";
>  	}
>  }
> @@ -38,6 +39,7 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct
> device *dev,
>  					     bool rpm)
>  {
>  	struct ufs_hba *hba = dev_get_drvdata(dev);
> +	struct ufs_dev_info *dev_info = &hba->dev_info;
>  	unsigned long flags, value;
> 
>  	if (kstrtoul(buf, 0, &value))
> @@ -46,6 +48,11 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct
> device *dev,
>  	if (value >= UFS_PM_LVL_MAX)
>  		return -EINVAL;
> 
> +	if (ufs_pm_lvl_states[value].dev_state == UFS_DEEPSLEEP_PWR_MODE &&
> +	    (!(hba->caps & UFSHCD_CAP_DEEPSLEEP) ||
> +	     !(dev_info->wspecversion >= 0x310)))
> +		return -EINVAL;
> +
>  	spin_lock_irqsave(hba->host->host_lock, flags);
>  	if (rpm)
>  		hba->rpm_lvl = value;
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index f8ab16f30fdc..d593edb48767 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -442,6 +442,7 @@ enum ufs_dev_pwr_mode {
>  	UFS_ACTIVE_PWR_MODE	= 1,
>  	UFS_SLEEP_PWR_MODE	= 2,
>  	UFS_POWERDOWN_PWR_MODE	= 3,
> +	UFS_DEEPSLEEP_PWR_MODE	= 4,
>  };
> 
>  #define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10)
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 2309253d3101..ee083b96e405 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -163,6 +163,11 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
>  	{UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>  	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>  	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE},
> +	/*
> +	 * For DeepSleep, the link is first put in hibern8 and then off.
> +	 * Leaving the link in hibern8 is not supported.
> +	 */
> +	{UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE},
>  };
> 
>  static inline enum ufs_dev_pwr_mode
> @@ -8297,7 +8302,8 @@ static int ufshcd_link_state_transition(struct
> ufs_hba *hba,
>  	}
>  	/*
>  	 * If autobkops is enabled, link can't be turned off because
> -	 * turning off the link would also turn off the device.
> +	 * turning off the link would also turn off the device, except in the
> +	 * case of DeepSleep where the device is expected to remain powered.
>  	 */
>  	else if ((req_link_state == UIC_LINK_OFF_STATE) &&
>  		 (!check_for_bkops || !hba->auto_bkops_enabled)) {
> @@ -8307,6 +8313,9 @@ static int ufshcd_link_state_transition(struct
> ufs_hba *hba,
>  		 * put the link in low power mode is to send the DME end point
>  		 * to device and then send the DME reset command to local
>  		 * unipro. But putting the link in hibern8 is much faster.
> +		 *
> +		 * Note also that putting the link in Hibern8 is a requirement
> +		 * for entering DeepSleep.
>  		 */
>  		ret = ufshcd_uic_hibern8_enter(hba);
>  		if (ret) {
> @@ -8439,6 +8448,7 @@ static void ufshcd_hba_vreg_set_hpm(struct 
> ufs_hba *hba)
>  static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>  {
>  	int ret = 0;
> +	int check_for_bkops;
>  	enum ufs_pm_level pm_lvl;
>  	enum ufs_dev_pwr_mode req_dev_pwr_mode;
>  	enum uic_link_state req_link_state;
> @@ -8524,7 +8534,13 @@ static int ufshcd_suspend(struct ufs_hba *hba,
> enum ufs_pm_op pm_op)
>  	}
> 
>  	flush_work(&hba->eeh_work);
> -	ret = ufshcd_link_state_transition(hba, req_link_state, 1);
> +
> +	/*
> +	 * In the case of DeepSleep, the device is expected to remain powered
> +	 * with the link off, so do not check for bkops.
> +	 */
> +	check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
> +	ret = ufshcd_link_state_transition(hba, req_link_state, 
> check_for_bkops);
>  	if (ret)
>  		goto set_dev_active;
> 
> @@ -8565,11 +8581,25 @@ static int ufshcd_suspend(struct ufs_hba *hba,
> enum ufs_pm_op pm_op)
>  	if (hba->clk_scaling.is_allowed)
>  		ufshcd_resume_clkscaling(hba);
>  	ufshcd_vreg_set_hpm(hba);
> +	/*
> +	 * Device hardware reset is required to exit DeepSleep. Also, for
> +	 * DeepSleep, the link is off so host reset and restore will be done
> +	 * further below.
> +	 */
> +	if (ufshcd_is_ufs_dev_deepsleep(hba)) {
> +		ufshcd_vops_device_reset(hba);
> +		WARN_ON(!ufshcd_is_link_off(hba));
> +	}
>  	if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba))
>  		ufshcd_set_link_active(hba);
>  	else if (ufshcd_is_link_off(hba))
>  		ufshcd_host_reset_and_restore(hba);
>  set_dev_active:
> +	/* Can also get here needing to exit DeepSleep */
> +	if (ufshcd_is_ufs_dev_deepsleep(hba)) {
> +		ufshcd_vops_device_reset(hba);
> +		ufshcd_host_reset_and_restore(hba);
> +	}
>  	if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE))
>  		ufshcd_disable_auto_bkops(hba);
>  enable_gating:
> @@ -8631,6 +8661,9 @@ static int ufshcd_resume(struct ufs_hba *hba,
> enum ufs_pm_op pm_op)
>  	if (ret)
>  		goto disable_vreg;
> 
> +	/* For DeepSleep, the only supported option is to have the link off 
> */
> +	WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && 
> !ufshcd_is_link_off(hba));
> +
>  	if (ufshcd_is_link_hibern8(hba)) {
>  		ret = ufshcd_uic_hibern8_exit(hba);
>  		if (!ret) {
> @@ -8644,6 +8677,8 @@ static int ufshcd_resume(struct ufs_hba *hba,
> enum ufs_pm_op pm_op)
>  		/*
>  		 * A full initialization of the host and the device is
>  		 * required since the link was put to off during suspend.
> +		 * Note, in the case of DeepSleep, the device will exit
> +		 * DeepSleep due to device reset.
>  		 */
>  		ret = ufshcd_reset_and_restore(hba);
>  		/*
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 0fbb735bb70c..213be0667b59 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -114,16 +114,22 @@ enum uic_link_state {
>  	((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
>  #define ufshcd_set_ufs_dev_poweroff(h) \
>  	((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
> +#define ufshcd_set_ufs_dev_deepsleep(h) \
> +	((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE)
>  #define ufshcd_is_ufs_dev_active(h) \
>  	((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
>  #define ufshcd_is_ufs_dev_sleep(h) \
>  	((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
>  #define ufshcd_is_ufs_dev_poweroff(h) \
>  	((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
> +#define ufshcd_is_ufs_dev_deepsleep(h) \
> +	((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE)
> 
>  /*
>   * UFS Power management levels.
> - * Each level is in increasing order of power savings.
> + * Each level is in increasing order of power savings, except 
> DeepSleep
> + * which is lower than PowerDown with power on but not PowerDown with
> + * power off.
>   */
>  enum ufs_pm_level {
>  	UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */
> @@ -132,6 +138,7 @@ enum ufs_pm_level {
>  	UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */
>  	UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE */
>  	UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */
> +	UFS_PM_LVL_6, /* UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE */
>  	UFS_PM_LVL_MAX
>  };
> 
> @@ -599,6 +606,14 @@ enum ufshcd_caps {
>  	 * This would increase power savings.
>  	 */
>  	UFSHCD_CAP_AGGR_POWER_COLLAPSE			= 1 << 9,
> +
> +	/*
> +	 * This capability allows the host controller driver to use 
> DeepSleep,
> +	 * if it is supported by the UFS device. The host controller driver 
> must
> +	 * support device hardware reset via the hba->device_reset() 
> callback,
> +	 * in order to exit DeepSleep state.
> +	 */
> +	UFSHCD_CAP_DEEPSLEEP				= 1 << 10,
>  };
> 
>  struct ufs_hba_variant_params {
> diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h
> index 84841b3a7ffd..2362244c2a9e 100644
> --- a/include/trace/events/ufs.h
> +++ b/include/trace/events/ufs.h
> @@ -19,7 +19,8 @@
>  #define UFS_PWR_MODES			\
>  	EM(UFS_ACTIVE_PWR_MODE)		\
>  	EM(UFS_SLEEP_PWR_MODE)		\
> -	EMe(UFS_POWERDOWN_PWR_MODE)
> +	EM(UFS_POWERDOWN_PWR_MODE)	\
> +	EMe(UFS_DEEPSLEEP_PWR_MODE)
> 
>  #define UFSCHD_CLK_GATING_STATES	\
>  	EM(CLKS_OFF)			\

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

* Re: [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-04  8:29   ` Can Guo
@ 2020-11-04  8:37     ` Adrian Hunter
  2020-11-04  9:03       ` Can Guo
  0 siblings, 1 reply; 18+ messages in thread
From: Adrian Hunter @ 2020-11-04  8:37 UTC (permalink / raw)
  To: Can Guo
  Cc: Martin K . Petersen, James E . J . Bottomley, linux-scsi,
	linux-kernel, Alim Akhtar, Avri Altman, Bean Huo, Stanley Chu

On 4/11/20 10:29 am, Can Guo wrote:
> Hi Adrian,
> 
> On 2020-11-03 22:14, Adrian Hunter wrote:
>> DeepSleep is a UFS v3.1 feature that achieves the lowest power consumption
>> of the device, apart from power off.
>>
>> In DeepSleep mode, no commands are accepted, and the only way to exit is
>> using a hardware reset or power cycle.
>>
>> This patch assumes that if a power cycle was an option, then power off
>> would be preferable, so only exit via a hardware reset is supported.
>>
>> Drivers that wish to support DeepSleep need to set a new capability flag
>> UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing
>>  ->device_reset() callback.
>>
>> It is assumed that UFS devices with wspecversion >= 0x310 support
>> DeepSleep.
>>
>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
>> ---
>>  Documentation/ABI/testing/sysfs-driver-ufs | 34 +++++++++++--------
>>  drivers/scsi/ufs/ufs-sysfs.c               |  7 ++++
>>  drivers/scsi/ufs/ufs.h                     |  1 +
>>  drivers/scsi/ufs/ufshcd.c                  | 39 ++++++++++++++++++++--
>>  drivers/scsi/ufs/ufshcd.h                  | 17 +++++++++-
>>  include/trace/events/ufs.h                 |  3 +-
>>  6 files changed, 83 insertions(+), 18 deletions(-)
>>
>> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
>> b/Documentation/ABI/testing/sysfs-driver-ufs
>> index adc0d0e91607..e77fa784d6d8 100644
>> --- a/Documentation/ABI/testing/sysfs-driver-ufs
>> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
>> @@ -916,21 +916,24 @@ Date:        September 2014
>>  Contact:    Subhash Jadavani <subhashj@codeaurora.org>
>>  Description:    This entry could be used to set or show the UFS device
>>          runtime power management level. The current driver
>> -        implementation supports 6 levels with next target states:
>> +        implementation supports 7 levels with next target states:
>>
>>          ==  ====================================================
>> -        0   an UFS device will stay active, an UIC link will
>> +        0   UFS device will stay active, UIC link will
>>              stay active
>> -        1   an UFS device will stay active, an UIC link will
>> +        1   UFS device will stay active, UIC link will
>>              hibernate
>> -        2   an UFS device will moved to sleep, an UIC link will
>> +        2   UFS device will be moved to sleep, UIC link will
>>              stay active
>> -        3   an UFS device will moved to sleep, an UIC link will
>> +        3   UFS device will be moved to sleep, UIC link will
>>              hibernate
>> -        4   an UFS device will be powered off, an UIC link will
>> +        4   UFS device will be powered off, UIC link will
>>              hibernate
>> -        5   an UFS device will be powered off, an UIC link will
>> +        5   UFS device will be powered off, UIC link will
>>              be powered off
>> +        6   UFS device will be moved to deep sleep, UIC link
>> +        will be powered off. Note, deep sleep might not be
>> +        supported in which case this value will not be accepted
> 
> Nitpicking, usually higher spm/rpm_lvl means better power saving.
> Since POWERDOWN+LINKOFF achieves the lowest power consumption, can
> we put DEEPSLEEP_LINKOFF to 5, and POWERDOWN_LINKOFF to 6?

That would break the API i.e. we shouldn't change the meaning of '5'

Also, pedantically it depends on whether regulators are provided as to
whether Deep Sleep is higher/lower than PowerDown i.e. without regulators to
switch off the device, it will remain in PowerDown mode which does not save
as much power as Deep Sleep.

> 
> Thanks,
> 
> Can Guo.
> 
>>          ==  ====================================================
>>
>>  What:        /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
>> @@ -954,21 +957,24 @@ Date:        September 2014
>>  Contact:    Subhash Jadavani <subhashj@codeaurora.org>
>>  Description:    This entry could be used to set or show the UFS device
>>          system power management level. The current driver
>> -        implementation supports 6 levels with next target states:
>> +        implementation supports 7 levels with next target states:
>>
>>          ==  ====================================================
>> -        0   an UFS device will stay active, an UIC link will
>> +        0   UFS device will stay active, UIC link will
>>              stay active
>> -        1   an UFS device will stay active, an UIC link will
>> +        1   UFS device will stay active, UIC link will
>>              hibernate
>> -        2   an UFS device will moved to sleep, an UIC link will
>> +        2   UFS device will be moved to sleep, UIC link will
>>              stay active
>> -        3   an UFS device will moved to sleep, an UIC link will
>> +        3   UFS device will be moved to sleep, UIC link will
>>              hibernate
>> -        4   an UFS device will be powered off, an UIC link will
>> +        4   UFS device will be powered off, UIC link will
>>              hibernate
>> -        5   an UFS device will be powered off, an UIC link will
>> +        5   UFS device will be powered off, UIC link will
>>              be powered off
>> +        6   UFS device will be moved to deep sleep, UIC link
>> +        will be powered off. Note, deep sleep might not be
>> +        supported in which case this value will not be accepted
>>          ==  ====================================================
>>
>>  What:        /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
>> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
>> index bdcd27faa054..08e72b7eef6a 100644
>> --- a/drivers/scsi/ufs/ufs-sysfs.c
>> +++ b/drivers/scsi/ufs/ufs-sysfs.c
>> @@ -28,6 +28,7 @@ static const char *ufschd_ufs_dev_pwr_mode_to_string(
>>      case UFS_ACTIVE_PWR_MODE:    return "ACTIVE";
>>      case UFS_SLEEP_PWR_MODE:    return "SLEEP";
>>      case UFS_POWERDOWN_PWR_MODE:    return "POWERDOWN";
>> +    case UFS_DEEPSLEEP_PWR_MODE:    return "DEEPSLEEP";
>>      default:            return "UNKNOWN";
>>      }
>>  }
>> @@ -38,6 +39,7 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct
>> device *dev,
>>                           bool rpm)
>>  {
>>      struct ufs_hba *hba = dev_get_drvdata(dev);
>> +    struct ufs_dev_info *dev_info = &hba->dev_info;
>>      unsigned long flags, value;
>>
>>      if (kstrtoul(buf, 0, &value))
>> @@ -46,6 +48,11 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct
>> device *dev,
>>      if (value >= UFS_PM_LVL_MAX)
>>          return -EINVAL;
>>
>> +    if (ufs_pm_lvl_states[value].dev_state == UFS_DEEPSLEEP_PWR_MODE &&
>> +        (!(hba->caps & UFSHCD_CAP_DEEPSLEEP) ||
>> +         !(dev_info->wspecversion >= 0x310)))
>> +        return -EINVAL;
>> +
>>      spin_lock_irqsave(hba->host->host_lock, flags);
>>      if (rpm)
>>          hba->rpm_lvl = value;
>> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
>> index f8ab16f30fdc..d593edb48767 100644
>> --- a/drivers/scsi/ufs/ufs.h
>> +++ b/drivers/scsi/ufs/ufs.h
>> @@ -442,6 +442,7 @@ enum ufs_dev_pwr_mode {
>>      UFS_ACTIVE_PWR_MODE    = 1,
>>      UFS_SLEEP_PWR_MODE    = 2,
>>      UFS_POWERDOWN_PWR_MODE    = 3,
>> +    UFS_DEEPSLEEP_PWR_MODE    = 4,
>>  };
>>
>>  #define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10)
>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>> index 2309253d3101..ee083b96e405 100644
>> --- a/drivers/scsi/ufs/ufshcd.c
>> +++ b/drivers/scsi/ufs/ufshcd.c
>> @@ -163,6 +163,11 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
>>      {UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>>      {UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>>      {UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE},
>> +    /*
>> +     * For DeepSleep, the link is first put in hibern8 and then off.
>> +     * Leaving the link in hibern8 is not supported.
>> +     */
>> +    {UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE},
>>  };
>>
>>  static inline enum ufs_dev_pwr_mode
>> @@ -8297,7 +8302,8 @@ static int ufshcd_link_state_transition(struct
>> ufs_hba *hba,
>>      }
>>      /*
>>       * If autobkops is enabled, link can't be turned off because
>> -     * turning off the link would also turn off the device.
>> +     * turning off the link would also turn off the device, except in the
>> +     * case of DeepSleep where the device is expected to remain powered.
>>       */
>>      else if ((req_link_state == UIC_LINK_OFF_STATE) &&
>>           (!check_for_bkops || !hba->auto_bkops_enabled)) {
>> @@ -8307,6 +8313,9 @@ static int ufshcd_link_state_transition(struct
>> ufs_hba *hba,
>>           * put the link in low power mode is to send the DME end point
>>           * to device and then send the DME reset command to local
>>           * unipro. But putting the link in hibern8 is much faster.
>> +         *
>> +         * Note also that putting the link in Hibern8 is a requirement
>> +         * for entering DeepSleep.
>>           */
>>          ret = ufshcd_uic_hibern8_enter(hba);
>>          if (ret) {
>> @@ -8439,6 +8448,7 @@ static void ufshcd_hba_vreg_set_hpm(struct ufs_hba
>> *hba)
>>  static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>>  {
>>      int ret = 0;
>> +    int check_for_bkops;
>>      enum ufs_pm_level pm_lvl;
>>      enum ufs_dev_pwr_mode req_dev_pwr_mode;
>>      enum uic_link_state req_link_state;
>> @@ -8524,7 +8534,13 @@ static int ufshcd_suspend(struct ufs_hba *hba,
>> enum ufs_pm_op pm_op)
>>      }
>>
>>      flush_work(&hba->eeh_work);
>> -    ret = ufshcd_link_state_transition(hba, req_link_state, 1);
>> +
>> +    /*
>> +     * In the case of DeepSleep, the device is expected to remain powered
>> +     * with the link off, so do not check for bkops.
>> +     */
>> +    check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
>> +    ret = ufshcd_link_state_transition(hba, req_link_state,
>> check_for_bkops);
>>      if (ret)
>>          goto set_dev_active;
>>
>> @@ -8565,11 +8581,25 @@ static int ufshcd_suspend(struct ufs_hba *hba,
>> enum ufs_pm_op pm_op)
>>      if (hba->clk_scaling.is_allowed)
>>          ufshcd_resume_clkscaling(hba);
>>      ufshcd_vreg_set_hpm(hba);
>> +    /*
>> +     * Device hardware reset is required to exit DeepSleep. Also, for
>> +     * DeepSleep, the link is off so host reset and restore will be done
>> +     * further below.
>> +     */
>> +    if (ufshcd_is_ufs_dev_deepsleep(hba)) {
>> +        ufshcd_vops_device_reset(hba);
>> +        WARN_ON(!ufshcd_is_link_off(hba));
>> +    }
>>      if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba))
>>          ufshcd_set_link_active(hba);
>>      else if (ufshcd_is_link_off(hba))
>>          ufshcd_host_reset_and_restore(hba);
>>  set_dev_active:
>> +    /* Can also get here needing to exit DeepSleep */
>> +    if (ufshcd_is_ufs_dev_deepsleep(hba)) {
>> +        ufshcd_vops_device_reset(hba);
>> +        ufshcd_host_reset_and_restore(hba);
>> +    }
>>      if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE))
>>          ufshcd_disable_auto_bkops(hba);
>>  enable_gating:
>> @@ -8631,6 +8661,9 @@ static int ufshcd_resume(struct ufs_hba *hba,
>> enum ufs_pm_op pm_op)
>>      if (ret)
>>          goto disable_vreg;
>>
>> +    /* For DeepSleep, the only supported option is to have the link off */
>> +    WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && !ufshcd_is_link_off(hba));
>> +
>>      if (ufshcd_is_link_hibern8(hba)) {
>>          ret = ufshcd_uic_hibern8_exit(hba);
>>          if (!ret) {
>> @@ -8644,6 +8677,8 @@ static int ufshcd_resume(struct ufs_hba *hba,
>> enum ufs_pm_op pm_op)
>>          /*
>>           * A full initialization of the host and the device is
>>           * required since the link was put to off during suspend.
>> +         * Note, in the case of DeepSleep, the device will exit
>> +         * DeepSleep due to device reset.
>>           */
>>          ret = ufshcd_reset_and_restore(hba);
>>          /*
>> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
>> index 0fbb735bb70c..213be0667b59 100644
>> --- a/drivers/scsi/ufs/ufshcd.h
>> +++ b/drivers/scsi/ufs/ufshcd.h
>> @@ -114,16 +114,22 @@ enum uic_link_state {
>>      ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
>>  #define ufshcd_set_ufs_dev_poweroff(h) \
>>      ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
>> +#define ufshcd_set_ufs_dev_deepsleep(h) \
>> +    ((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE)
>>  #define ufshcd_is_ufs_dev_active(h) \
>>      ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
>>  #define ufshcd_is_ufs_dev_sleep(h) \
>>      ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
>>  #define ufshcd_is_ufs_dev_poweroff(h) \
>>      ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
>> +#define ufshcd_is_ufs_dev_deepsleep(h) \
>> +    ((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE)
>>
>>  /*
>>   * UFS Power management levels.
>> - * Each level is in increasing order of power savings.
>> + * Each level is in increasing order of power savings, except DeepSleep
>> + * which is lower than PowerDown with power on but not PowerDown with
>> + * power off.
>>   */
>>  enum ufs_pm_level {
>>      UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */
>> @@ -132,6 +138,7 @@ enum ufs_pm_level {
>>      UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */
>>      UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE */
>>      UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */
>> +    UFS_PM_LVL_6, /* UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE */
>>      UFS_PM_LVL_MAX
>>  };
>>
>> @@ -599,6 +606,14 @@ enum ufshcd_caps {
>>       * This would increase power savings.
>>       */
>>      UFSHCD_CAP_AGGR_POWER_COLLAPSE            = 1 << 9,
>> +
>> +    /*
>> +     * This capability allows the host controller driver to use DeepSleep,
>> +     * if it is supported by the UFS device. The host controller driver must
>> +     * support device hardware reset via the hba->device_reset() callback,
>> +     * in order to exit DeepSleep state.
>> +     */
>> +    UFSHCD_CAP_DEEPSLEEP                = 1 << 10,
>>  };
>>
>>  struct ufs_hba_variant_params {
>> diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h
>> index 84841b3a7ffd..2362244c2a9e 100644
>> --- a/include/trace/events/ufs.h
>> +++ b/include/trace/events/ufs.h
>> @@ -19,7 +19,8 @@
>>  #define UFS_PWR_MODES            \
>>      EM(UFS_ACTIVE_PWR_MODE)        \
>>      EM(UFS_SLEEP_PWR_MODE)        \
>> -    EMe(UFS_POWERDOWN_PWR_MODE)
>> +    EM(UFS_POWERDOWN_PWR_MODE)    \
>> +    EMe(UFS_DEEPSLEEP_PWR_MODE)
>>
>>  #define UFSCHD_CLK_GATING_STATES    \
>>      EM(CLKS_OFF)            \


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

* Re: [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset()
  2020-11-03 14:14 ` [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset() Adrian Hunter
  2020-11-04  2:55   ` Stanley Chu
  2020-11-04  8:05   ` Can Guo
@ 2020-11-04  8:44   ` Bean Huo
  2020-11-04 16:35   ` Asutosh Das (asd)
  3 siblings, 0 replies; 18+ messages in thread
From: Bean Huo @ 2020-11-04  8:44 UTC (permalink / raw)
  To: Adrian Hunter, Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, linux-kernel, Alim Akhtar, Avri Altman, Can Guo, Stanley Chu

On Tue, 2020-11-03 at 16:14 +0200, Adrian Hunter wrote:
> It is simpler for drivers to provide a ->device_reset() callback
> irrespective of whether the GPIO, or firmware interface necessary to
> do the
> reset, is discovered during probe.
> 
> Change ->device_reset() to return an error code.  Drivers that
> provide
> the callback, but do not do the reset operation should return
> -EOPNOTSUPP.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Bean huo <beanhuo@micron.com>



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

* Re: [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-04  8:37     ` Adrian Hunter
@ 2020-11-04  9:03       ` Can Guo
  0 siblings, 0 replies; 18+ messages in thread
From: Can Guo @ 2020-11-04  9:03 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Martin K . Petersen, James E . J . Bottomley, linux-scsi,
	linux-kernel, Alim Akhtar, Avri Altman, Bean Huo, Stanley Chu

On 2020-11-04 16:37, Adrian Hunter wrote:
> On 4/11/20 10:29 am, Can Guo wrote:
>> Hi Adrian,
>> 
>> On 2020-11-03 22:14, Adrian Hunter wrote:
>>> DeepSleep is a UFS v3.1 feature that achieves the lowest power 
>>> consumption
>>> of the device, apart from power off.
>>> 
>>> In DeepSleep mode, no commands are accepted, and the only way to exit 
>>> is
>>> using a hardware reset or power cycle.
>>> 
>>> This patch assumes that if a power cycle was an option, then power 
>>> off
>>> would be preferable, so only exit via a hardware reset is supported.
>>> 
>>> Drivers that wish to support DeepSleep need to set a new capability 
>>> flag
>>> UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing
>>>  ->device_reset() callback.
>>> 
>>> It is assumed that UFS devices with wspecversion >= 0x310 support
>>> DeepSleep.
>>> 
>>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
>>> ---
>>>  Documentation/ABI/testing/sysfs-driver-ufs | 34 +++++++++++--------
>>>  drivers/scsi/ufs/ufs-sysfs.c               |  7 ++++
>>>  drivers/scsi/ufs/ufs.h                     |  1 +
>>>  drivers/scsi/ufs/ufshcd.c                  | 39 
>>> ++++++++++++++++++++--
>>>  drivers/scsi/ufs/ufshcd.h                  | 17 +++++++++-
>>>  include/trace/events/ufs.h                 |  3 +-
>>>  6 files changed, 83 insertions(+), 18 deletions(-)
>>> 
>>> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
>>> b/Documentation/ABI/testing/sysfs-driver-ufs
>>> index adc0d0e91607..e77fa784d6d8 100644
>>> --- a/Documentation/ABI/testing/sysfs-driver-ufs
>>> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
>>> @@ -916,21 +916,24 @@ Date:        September 2014
>>>  Contact:    Subhash Jadavani <subhashj@codeaurora.org>
>>>  Description:    This entry could be used to set or show the UFS 
>>> device
>>>          runtime power management level. The current driver
>>> -        implementation supports 6 levels with next target states:
>>> +        implementation supports 7 levels with next target states:
>>> 
>>>          ==  ====================================================
>>> -        0   an UFS device will stay active, an UIC link will
>>> +        0   UFS device will stay active, UIC link will
>>>              stay active
>>> -        1   an UFS device will stay active, an UIC link will
>>> +        1   UFS device will stay active, UIC link will
>>>              hibernate
>>> -        2   an UFS device will moved to sleep, an UIC link will
>>> +        2   UFS device will be moved to sleep, UIC link will
>>>              stay active
>>> -        3   an UFS device will moved to sleep, an UIC link will
>>> +        3   UFS device will be moved to sleep, UIC link will
>>>              hibernate
>>> -        4   an UFS device will be powered off, an UIC link will
>>> +        4   UFS device will be powered off, UIC link will
>>>              hibernate
>>> -        5   an UFS device will be powered off, an UIC link will
>>> +        5   UFS device will be powered off, UIC link will
>>>              be powered off
>>> +        6   UFS device will be moved to deep sleep, UIC link
>>> +        will be powered off. Note, deep sleep might not be
>>> +        supported in which case this value will not be accepted
>> 
>> Nitpicking, usually higher spm/rpm_lvl means better power saving.
>> Since POWERDOWN+LINKOFF achieves the lowest power consumption, can
>> we put DEEPSLEEP_LINKOFF to 5, and POWERDOWN_LINKOFF to 6?
> 
> That would break the API i.e. we shouldn't change the meaning of '5'
> 
> Also, pedantically it depends on whether regulators are provided as to
> whether Deep Sleep is higher/lower than PowerDown i.e. without 
> regulators to
> switch off the device, it will remain in PowerDown mode which does not 
> save
> as much power as Deep Sleep.
> 

OK, that makes sense. The change LGTM, I gave my reivewed-by tag.

Regards,

Can Guo.

>> 
>> Thanks,
>> 
>> Can Guo.
>> 
>>>          ==  ====================================================
>>> 
>>>  What:        /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
>>> @@ -954,21 +957,24 @@ Date:        September 2014
>>>  Contact:    Subhash Jadavani <subhashj@codeaurora.org>
>>>  Description:    This entry could be used to set or show the UFS 
>>> device
>>>          system power management level. The current driver
>>> -        implementation supports 6 levels with next target states:
>>> +        implementation supports 7 levels with next target states:
>>> 
>>>          ==  ====================================================
>>> -        0   an UFS device will stay active, an UIC link will
>>> +        0   UFS device will stay active, UIC link will
>>>              stay active
>>> -        1   an UFS device will stay active, an UIC link will
>>> +        1   UFS device will stay active, UIC link will
>>>              hibernate
>>> -        2   an UFS device will moved to sleep, an UIC link will
>>> +        2   UFS device will be moved to sleep, UIC link will
>>>              stay active
>>> -        3   an UFS device will moved to sleep, an UIC link will
>>> +        3   UFS device will be moved to sleep, UIC link will
>>>              hibernate
>>> -        4   an UFS device will be powered off, an UIC link will
>>> +        4   UFS device will be powered off, UIC link will
>>>              hibernate
>>> -        5   an UFS device will be powered off, an UIC link will
>>> +        5   UFS device will be powered off, UIC link will
>>>              be powered off
>>> +        6   UFS device will be moved to deep sleep, UIC link
>>> +        will be powered off. Note, deep sleep might not be
>>> +        supported in which case this value will not be accepted
>>>          ==  ====================================================
>>> 
>>>  What:        /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
>>> diff --git a/drivers/scsi/ufs/ufs-sysfs.c 
>>> b/drivers/scsi/ufs/ufs-sysfs.c
>>> index bdcd27faa054..08e72b7eef6a 100644
>>> --- a/drivers/scsi/ufs/ufs-sysfs.c
>>> +++ b/drivers/scsi/ufs/ufs-sysfs.c
>>> @@ -28,6 +28,7 @@ static const char 
>>> *ufschd_ufs_dev_pwr_mode_to_string(
>>>      case UFS_ACTIVE_PWR_MODE:    return "ACTIVE";
>>>      case UFS_SLEEP_PWR_MODE:    return "SLEEP";
>>>      case UFS_POWERDOWN_PWR_MODE:    return "POWERDOWN";
>>> +    case UFS_DEEPSLEEP_PWR_MODE:    return "DEEPSLEEP";
>>>      default:            return "UNKNOWN";
>>>      }
>>>  }
>>> @@ -38,6 +39,7 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct
>>> device *dev,
>>>                           bool rpm)
>>>  {
>>>      struct ufs_hba *hba = dev_get_drvdata(dev);
>>> +    struct ufs_dev_info *dev_info = &hba->dev_info;
>>>      unsigned long flags, value;
>>> 
>>>      if (kstrtoul(buf, 0, &value))
>>> @@ -46,6 +48,11 @@ static inline ssize_t 
>>> ufs_sysfs_pm_lvl_store(struct
>>> device *dev,
>>>      if (value >= UFS_PM_LVL_MAX)
>>>          return -EINVAL;
>>> 
>>> +    if (ufs_pm_lvl_states[value].dev_state == UFS_DEEPSLEEP_PWR_MODE 
>>> &&
>>> +        (!(hba->caps & UFSHCD_CAP_DEEPSLEEP) ||
>>> +         !(dev_info->wspecversion >= 0x310)))
>>> +        return -EINVAL;
>>> +
>>>      spin_lock_irqsave(hba->host->host_lock, flags);
>>>      if (rpm)
>>>          hba->rpm_lvl = value;
>>> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
>>> index f8ab16f30fdc..d593edb48767 100644
>>> --- a/drivers/scsi/ufs/ufs.h
>>> +++ b/drivers/scsi/ufs/ufs.h
>>> @@ -442,6 +442,7 @@ enum ufs_dev_pwr_mode {
>>>      UFS_ACTIVE_PWR_MODE    = 1,
>>>      UFS_SLEEP_PWR_MODE    = 2,
>>>      UFS_POWERDOWN_PWR_MODE    = 3,
>>> +    UFS_DEEPSLEEP_PWR_MODE    = 4,
>>>  };
>>> 
>>>  #define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10)
>>> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
>>> index 2309253d3101..ee083b96e405 100644
>>> --- a/drivers/scsi/ufs/ufshcd.c
>>> +++ b/drivers/scsi/ufs/ufshcd.c
>>> @@ -163,6 +163,11 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
>>>      {UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>>>      {UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>>>      {UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE},
>>> +    /*
>>> +     * For DeepSleep, the link is first put in hibern8 and then off.
>>> +     * Leaving the link in hibern8 is not supported.
>>> +     */
>>> +    {UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE},
>>>  };
>>> 
>>>  static inline enum ufs_dev_pwr_mode
>>> @@ -8297,7 +8302,8 @@ static int ufshcd_link_state_transition(struct
>>> ufs_hba *hba,
>>>      }
>>>      /*
>>>       * If autobkops is enabled, link can't be turned off because
>>> -     * turning off the link would also turn off the device.
>>> +     * turning off the link would also turn off the device, except 
>>> in the
>>> +     * case of DeepSleep where the device is expected to remain 
>>> powered.
>>>       */
>>>      else if ((req_link_state == UIC_LINK_OFF_STATE) &&
>>>           (!check_for_bkops || !hba->auto_bkops_enabled)) {
>>> @@ -8307,6 +8313,9 @@ static int ufshcd_link_state_transition(struct
>>> ufs_hba *hba,
>>>           * put the link in low power mode is to send the DME end 
>>> point
>>>           * to device and then send the DME reset command to local
>>>           * unipro. But putting the link in hibern8 is much faster.
>>> +         *
>>> +         * Note also that putting the link in Hibern8 is a 
>>> requirement
>>> +         * for entering DeepSleep.
>>>           */
>>>          ret = ufshcd_uic_hibern8_enter(hba);
>>>          if (ret) {
>>> @@ -8439,6 +8448,7 @@ static void ufshcd_hba_vreg_set_hpm(struct 
>>> ufs_hba
>>> *hba)
>>>  static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>>>  {
>>>      int ret = 0;
>>> +    int check_for_bkops;
>>>      enum ufs_pm_level pm_lvl;
>>>      enum ufs_dev_pwr_mode req_dev_pwr_mode;
>>>      enum uic_link_state req_link_state;
>>> @@ -8524,7 +8534,13 @@ static int ufshcd_suspend(struct ufs_hba *hba,
>>> enum ufs_pm_op pm_op)
>>>      }
>>> 
>>>      flush_work(&hba->eeh_work);
>>> -    ret = ufshcd_link_state_transition(hba, req_link_state, 1);
>>> +
>>> +    /*
>>> +     * In the case of DeepSleep, the device is expected to remain 
>>> powered
>>> +     * with the link off, so do not check for bkops.
>>> +     */
>>> +    check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
>>> +    ret = ufshcd_link_state_transition(hba, req_link_state,
>>> check_for_bkops);
>>>      if (ret)
>>>          goto set_dev_active;
>>> 
>>> @@ -8565,11 +8581,25 @@ static int ufshcd_suspend(struct ufs_hba 
>>> *hba,
>>> enum ufs_pm_op pm_op)
>>>      if (hba->clk_scaling.is_allowed)
>>>          ufshcd_resume_clkscaling(hba);
>>>      ufshcd_vreg_set_hpm(hba);
>>> +    /*
>>> +     * Device hardware reset is required to exit DeepSleep. Also, 
>>> for
>>> +     * DeepSleep, the link is off so host reset and restore will be 
>>> done
>>> +     * further below.
>>> +     */
>>> +    if (ufshcd_is_ufs_dev_deepsleep(hba)) {
>>> +        ufshcd_vops_device_reset(hba);
>>> +        WARN_ON(!ufshcd_is_link_off(hba));
>>> +    }
>>>      if (ufshcd_is_link_hibern8(hba) && 
>>> !ufshcd_uic_hibern8_exit(hba))
>>>          ufshcd_set_link_active(hba);
>>>      else if (ufshcd_is_link_off(hba))
>>>          ufshcd_host_reset_and_restore(hba);
>>>  set_dev_active:
>>> +    /* Can also get here needing to exit DeepSleep */
>>> +    if (ufshcd_is_ufs_dev_deepsleep(hba)) {
>>> +        ufshcd_vops_device_reset(hba);
>>> +        ufshcd_host_reset_and_restore(hba);
>>> +    }
>>>      if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE))
>>>          ufshcd_disable_auto_bkops(hba);
>>>  enable_gating:
>>> @@ -8631,6 +8661,9 @@ static int ufshcd_resume(struct ufs_hba *hba,
>>> enum ufs_pm_op pm_op)
>>>      if (ret)
>>>          goto disable_vreg;
>>> 
>>> +    /* For DeepSleep, the only supported option is to have the link 
>>> off */
>>> +    WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && 
>>> !ufshcd_is_link_off(hba));
>>> +
>>>      if (ufshcd_is_link_hibern8(hba)) {
>>>          ret = ufshcd_uic_hibern8_exit(hba);
>>>          if (!ret) {
>>> @@ -8644,6 +8677,8 @@ static int ufshcd_resume(struct ufs_hba *hba,
>>> enum ufs_pm_op pm_op)
>>>          /*
>>>           * A full initialization of the host and the device is
>>>           * required since the link was put to off during suspend.
>>> +         * Note, in the case of DeepSleep, the device will exit
>>> +         * DeepSleep due to device reset.
>>>           */
>>>          ret = ufshcd_reset_and_restore(hba);
>>>          /*
>>> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
>>> index 0fbb735bb70c..213be0667b59 100644
>>> --- a/drivers/scsi/ufs/ufshcd.h
>>> +++ b/drivers/scsi/ufs/ufshcd.h
>>> @@ -114,16 +114,22 @@ enum uic_link_state {
>>>      ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
>>>  #define ufshcd_set_ufs_dev_poweroff(h) \
>>>      ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
>>> +#define ufshcd_set_ufs_dev_deepsleep(h) \
>>> +    ((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE)
>>>  #define ufshcd_is_ufs_dev_active(h) \
>>>      ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
>>>  #define ufshcd_is_ufs_dev_sleep(h) \
>>>      ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
>>>  #define ufshcd_is_ufs_dev_poweroff(h) \
>>>      ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
>>> +#define ufshcd_is_ufs_dev_deepsleep(h) \
>>> +    ((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE)
>>> 
>>>  /*
>>>   * UFS Power management levels.
>>> - * Each level is in increasing order of power savings.
>>> + * Each level is in increasing order of power savings, except 
>>> DeepSleep
>>> + * which is lower than PowerDown with power on but not PowerDown 
>>> with
>>> + * power off.
>>>   */
>>>  enum ufs_pm_level {
>>>      UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */
>>> @@ -132,6 +138,7 @@ enum ufs_pm_level {
>>>      UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */
>>>      UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE 
>>> */
>>>      UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */
>>> +    UFS_PM_LVL_6, /* UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE */
>>>      UFS_PM_LVL_MAX
>>>  };
>>> 
>>> @@ -599,6 +606,14 @@ enum ufshcd_caps {
>>>       * This would increase power savings.
>>>       */
>>>      UFSHCD_CAP_AGGR_POWER_COLLAPSE            = 1 << 9,
>>> +
>>> +    /*
>>> +     * This capability allows the host controller driver to use 
>>> DeepSleep,
>>> +     * if it is supported by the UFS device. The host controller 
>>> driver must
>>> +     * support device hardware reset via the hba->device_reset() 
>>> callback,
>>> +     * in order to exit DeepSleep state.
>>> +     */
>>> +    UFSHCD_CAP_DEEPSLEEP                = 1 << 10,
>>>  };
>>> 
>>>  struct ufs_hba_variant_params {
>>> diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h
>>> index 84841b3a7ffd..2362244c2a9e 100644
>>> --- a/include/trace/events/ufs.h
>>> +++ b/include/trace/events/ufs.h
>>> @@ -19,7 +19,8 @@
>>>  #define UFS_PWR_MODES            \
>>>      EM(UFS_ACTIVE_PWR_MODE)        \
>>>      EM(UFS_SLEEP_PWR_MODE)        \
>>> -    EMe(UFS_POWERDOWN_PWR_MODE)
>>> +    EM(UFS_POWERDOWN_PWR_MODE)    \
>>> +    EMe(UFS_DEEPSLEEP_PWR_MODE)
>>> 
>>>  #define UFSCHD_CLK_GATING_STATES    \
>>>      EM(CLKS_OFF)            \

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

* Re: [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-03 14:14 ` [PATCH V4 1/2] " Adrian Hunter
  2020-11-04  8:04   ` Can Guo
  2020-11-04  8:29   ` Can Guo
@ 2020-11-04 10:57   ` Bean Huo
  2020-11-04 11:55     ` Adrian Hunter
  2020-11-04 16:35   ` Asutosh Das (asd)
  2020-11-05  1:42   ` Stanley Chu
  4 siblings, 1 reply; 18+ messages in thread
From: Bean Huo @ 2020-11-04 10:57 UTC (permalink / raw)
  To: Adrian Hunter, Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, linux-kernel, Alim Akhtar, Avri Altman, Can Guo, Stanley Chu

On Tue, 2020-11-03 at 16:14 +0200, Adrian Hunter wrote:
> DeepSleep is a UFS v3.1 feature that achieves the lowest power
> consumption
> of the device, apart from power off.
> 
> In DeepSleep mode, no commands are accepted, and the only way to exit
> is
> using a hardware reset or power cycle.
> 
> This patch assumes that if a power cycle was an option, then power
> off
> would be preferable, so only exit via a hardware reset is supported.
> 
> Drivers that wish to support DeepSleep need to set a new capability
> flag
> UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing
>  ->device_reset() callback.
> 
> It is assumed that UFS devices with wspecversion >= 0x310 support
> DeepSleep.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
>  Documentation/ABI/testing/sysfs-driver-ufs | 34 +++++++++++--------
>  drivers/scsi/ufs/ufs-sysfs.c               |  7 ++++
>  drivers/scsi/ufs/ufs.h                     |  1 +
>  drivers/scsi/ufs/ufshcd.c                  | 39
> ++++++++++++++++++++--
>  drivers/scsi/ufs/ufshcd.h                  | 17 +++++++++-
>  include/trace/events/ufs.h                 |  3 +-
>  6 files changed, 83 insertions(+), 18 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
> b/Documentation/ABI/testing/sysfs-driver-ufs
> index adc0d0e91607..e77fa784d6d8 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -916,21 +916,24 @@ Date:		September 2014
>  Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>  Description:	This entry could be used to set or show the UFS device
>  		runtime power management level. The current driver
> -		implementation supports 6 levels with next target
> states:
> +		implementation supports 7 levels with next target
> states:
>  
>  		==  ===================================================
> =
> -		0   an UFS device will stay active, an UIC link will
> +		0   UFS device will stay active, UIC link will
>  		    stay active
> -		1   an UFS device will stay active, an UIC link will
> +		1   UFS device will stay active, UIC link will
>  		    hibernate
> -		2   an UFS device will moved to sleep, an UIC link will
> +		2   UFS device will be moved to sleep, UIC link will
>  		    stay active
> -		3   an UFS device will moved to sleep, an UIC link will
> +		3   UFS device will be moved to sleep, UIC link will
>  		    hibernate
> -		4   an UFS device will be powered off, an UIC link will
> +		4   UFS device will be powered off, UIC link will
>  		    hibernate
> -		5   an UFS device will be powered off, an UIC link will
> +		5   UFS device will be powered off, UIC link will
>  		    be powered off
> +		6   UFS device will be moved to deep sleep, UIC link
> +		will be powered off. Note, deep sleep might not be
> +		supported in which case this value will not be accepted
>  		==  ===================================================
> =
>  
>  What:		/sys/bus/platform/drivers/ufshcd/*/rpm_target_d
> ev_state
> @@ -954,21 +957,24 @@ Date:		September 2014
>  Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>  Description:	This entry could be used to set or show the UFS device
>  		system power management level. The current driver
> -		implementation supports 6 levels with next target
> states:
> +		implementation supports 7 levels with next target
> states:
>  
>  		==  ===================================================
> =

Hi Adrian
There doesn't have these equal sign lines in the sysfs-driver-ufs.
maybe you should remove these. or add + prefix.

Thanks,
Bean



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

* Re: [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-04 10:57   ` Bean Huo
@ 2020-11-04 11:55     ` Adrian Hunter
  2020-11-04 13:19       ` Bean Huo
  0 siblings, 1 reply; 18+ messages in thread
From: Adrian Hunter @ 2020-11-04 11:55 UTC (permalink / raw)
  To: Bean Huo, Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, linux-kernel, Alim Akhtar, Avri Altman, Can Guo, Stanley Chu

On 4/11/20 12:57 pm, Bean Huo wrote:
> On Tue, 2020-11-03 at 16:14 +0200, Adrian Hunter wrote:
>> DeepSleep is a UFS v3.1 feature that achieves the lowest power
>> consumption
>> of the device, apart from power off.
>>
>> In DeepSleep mode, no commands are accepted, and the only way to exit
>> is
>> using a hardware reset or power cycle.
>>
>> This patch assumes that if a power cycle was an option, then power
>> off
>> would be preferable, so only exit via a hardware reset is supported.
>>
>> Drivers that wish to support DeepSleep need to set a new capability
>> flag
>> UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing
>>  ->device_reset() callback.
>>
>> It is assumed that UFS devices with wspecversion >= 0x310 support
>> DeepSleep.
>>
>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
>> ---
>>  Documentation/ABI/testing/sysfs-driver-ufs | 34 +++++++++++--------
>>  drivers/scsi/ufs/ufs-sysfs.c               |  7 ++++
>>  drivers/scsi/ufs/ufs.h                     |  1 +
>>  drivers/scsi/ufs/ufshcd.c                  | 39
>> ++++++++++++++++++++--
>>  drivers/scsi/ufs/ufshcd.h                  | 17 +++++++++-
>>  include/trace/events/ufs.h                 |  3 +-
>>  6 files changed, 83 insertions(+), 18 deletions(-)
>>
>> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs
>> b/Documentation/ABI/testing/sysfs-driver-ufs
>> index adc0d0e91607..e77fa784d6d8 100644
>> --- a/Documentation/ABI/testing/sysfs-driver-ufs
>> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
>> @@ -916,21 +916,24 @@ Date:		September 2014
>>  Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>>  Description:	This entry could be used to set or show the UFS device
>>  		runtime power management level. The current driver
>> -		implementation supports 6 levels with next target
>> states:
>> +		implementation supports 7 levels with next target
>> states:
>>  
>>  		==  ===================================================
>> =
>> -		0   an UFS device will stay active, an UIC link will
>> +		0   UFS device will stay active, UIC link will
>>  		    stay active
>> -		1   an UFS device will stay active, an UIC link will
>> +		1   UFS device will stay active, UIC link will
>>  		    hibernate
>> -		2   an UFS device will moved to sleep, an UIC link will
>> +		2   UFS device will be moved to sleep, UIC link will
>>  		    stay active
>> -		3   an UFS device will moved to sleep, an UIC link will
>> +		3   UFS device will be moved to sleep, UIC link will
>>  		    hibernate
>> -		4   an UFS device will be powered off, an UIC link will
>> +		4   UFS device will be powered off, UIC link will
>>  		    hibernate
>> -		5   an UFS device will be powered off, an UIC link will
>> +		5   UFS device will be powered off, UIC link will
>>  		    be powered off
>> +		6   UFS device will be moved to deep sleep, UIC link
>> +		will be powered off. Note, deep sleep might not be
>> +		supported in which case this value will not be accepted
>>  		==  ===================================================
>> =
>>  
>>  What:		/sys/bus/platform/drivers/ufshcd/*/rpm_target_d
>> ev_state
>> @@ -954,21 +957,24 @@ Date:		September 2014
>>  Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>>  Description:	This entry could be used to set or show the UFS device
>>  		system power management level. The current driver
>> -		implementation supports 6 levels with next target
>> states:
>> +		implementation supports 7 levels with next target
>> states:
>>  
>>  		==  ===================================================
>> =
> 
> Hi Adrian
> There doesn't have these equal sign lines in the sysfs-driver-ufs.
> maybe you should remove these. or add + prefix.

The "=" are from the patch below which is in v5.10-rc2

commit 54a19b4d3fe0fa0a31b46cd60951e8177cac25fa
Author: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Date:   Fri Oct 30 08:40:50 2020 +0100

    docs: ABI: cleanup several ABI documents
    
    There are some ABI documents that, while they don't generate
    any warnings, they have issues when parsed by get_abi.pl script
    on its output result.
    
    Address them, in order to provide a clean output.
    
    Reviewed-by: Tom Rix <trix@redhat.com> # for fpga-manager
    Reviewed-By: Kajol Jain<kjain@linux.ibm.com> # for sysfs-bus-event_source-devices-hv_gpci and sysfs-bus-event_source-devices-hv_24x7
    Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> #for IIO                                                                                                                             
    Acked-by: Oded Gabbay <oded.gabbay@gmail.com> # for Habanalabs                                                                                                                                
    Acked-by: Vaibhav Jain <vaibhav@linux.ibm.com> # for sysfs-bus-papr-pmem                                                                                                                      
    Acked-by: Cezary Rojewski <cezary.rojewski@intel.com> # for catpt                                                                                                                             
    Acked-by: Suzuki K Poulose <suzuki.poulose@arm.com>                                                                                                                                           
    Acked-by: Ilya Dryomov <idryomov@gmail.com> # for rbd                                                                                                                                         
    Acked-by: Jonathan Corbet <corbet@lwn.net>                                                                                                                                                    
    Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>                                                                                                                              
    Link: https://lore.kernel.org/r/5bc78e5b68ed1e9e39135173857cb2e753be868f.1604042072.git.mchehab+huawei@kernel.org                                                                             
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>               


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

* Re: [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-04 11:55     ` Adrian Hunter
@ 2020-11-04 13:19       ` Bean Huo
  0 siblings, 0 replies; 18+ messages in thread
From: Bean Huo @ 2020-11-04 13:19 UTC (permalink / raw)
  To: Adrian Hunter, Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, linux-kernel, Alim Akhtar, Avri Altman, Can Guo, Stanley Chu

On Wed, 2020-11-04 at 13:55 +0200, Adrian Hunter wrote:
> > > states:
> > >   
> > >               == 
> > > ===================================================
> > > =
> > 
> > Hi Adrian
> > There doesn't have these equal sign lines in the sysfs-driver-ufs.
> > maybe you should remove these. or add + prefix.
> 
> The "=" are from the patch below which is in v5.10-rc2
> 
> commit 54a19b4d3fe0fa0a31b46cd60951e8177cac25fa
> Author: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> Date:   Fri Oct 30 08:40:50 2020 +0100
thanks for pointing out this.

Reviewed-by: Bean Huo <beanhuo@micron.com>


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

* Re: [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset()
  2020-11-03 14:14 ` [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset() Adrian Hunter
                     ` (2 preceding siblings ...)
  2020-11-04  8:44   ` Bean Huo
@ 2020-11-04 16:35   ` Asutosh Das (asd)
  3 siblings, 0 replies; 18+ messages in thread
From: Asutosh Das (asd) @ 2020-11-04 16:35 UTC (permalink / raw)
  To: Adrian Hunter, Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, linux-kernel, Alim Akhtar, Avri Altman, Bean Huo,
	Can Guo, Stanley Chu

On 11/3/2020 6:14 AM, Adrian Hunter wrote:
> It is simpler for drivers to provide a ->device_reset() callback
> irrespective of whether the GPIO, or firmware interface necessary to do the
> reset, is discovered during probe.
> 
> Change ->device_reset() to return an error code.  Drivers that provide
> the callback, but do not do the reset operation should return -EOPNOTSUPP.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>

Reviewed-by: Asutosh Das <asutoshd@codeaurora.org>

> ---
>   drivers/scsi/ufs/ufs-mediatek.c |  4 +++-
>   drivers/scsi/ufs/ufs-qcom.c     |  6 ++++--
>   drivers/scsi/ufs/ufshcd.h       | 11 +++++++----
>   3 files changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
> index 8df73bc2f8cb..914a827a93ee 100644
> --- a/drivers/scsi/ufs/ufs-mediatek.c
> +++ b/drivers/scsi/ufs/ufs-mediatek.c
> @@ -743,7 +743,7 @@ static int ufs_mtk_link_startup_notify(struct ufs_hba *hba,
>   	return ret;
>   }
>   
> -static void ufs_mtk_device_reset(struct ufs_hba *hba)
> +static int ufs_mtk_device_reset(struct ufs_hba *hba)
>   {
>   	struct arm_smccc_res res;
>   
> @@ -764,6 +764,8 @@ static void ufs_mtk_device_reset(struct ufs_hba *hba)
>   	usleep_range(10000, 15000);
>   
>   	dev_info(hba->dev, "device reset done\n");
> +
> +	return 0;
>   }
>   
>   static int ufs_mtk_link_set_hpm(struct ufs_hba *hba)
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 9a19c6d15d3b..357c3b49321d 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -1422,13 +1422,13 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
>    *
>    * Toggles the (optional) reset line to reset the attached device.
>    */
> -static void ufs_qcom_device_reset(struct ufs_hba *hba)
> +static int ufs_qcom_device_reset(struct ufs_hba *hba)
>   {
>   	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   
>   	/* reset gpio is optional */
>   	if (!host->device_reset)
> -		return;
> +		return -EOPNOTSUPP;
>   
>   	/*
>   	 * The UFS device shall detect reset pulses of 1us, sleep for 10us to
> @@ -1439,6 +1439,8 @@ static void ufs_qcom_device_reset(struct ufs_hba *hba)
>   
>   	gpiod_set_value_cansleep(host->device_reset, 0);
>   	usleep_range(10, 15);
> +
> +	return 0;
>   }
>   
>   #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 213be0667b59..5191d87f6263 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -323,7 +323,7 @@ struct ufs_hba_variant_ops {
>   	int     (*resume)(struct ufs_hba *, enum ufs_pm_op);
>   	void	(*dbg_register_dump)(struct ufs_hba *hba);
>   	int	(*phy_initialization)(struct ufs_hba *);
> -	void	(*device_reset)(struct ufs_hba *hba);
> +	int	(*device_reset)(struct ufs_hba *hba);
>   	void	(*config_scaling_param)(struct ufs_hba *hba,
>   					struct devfreq_dev_profile *profile,
>   					void *data);
> @@ -1207,9 +1207,12 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
>   static inline void ufshcd_vops_device_reset(struct ufs_hba *hba)
>   {
>   	if (hba->vops && hba->vops->device_reset) {
> -		hba->vops->device_reset(hba);
> -		ufshcd_set_ufs_dev_active(hba);
> -		ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0);
> +		int err = hba->vops->device_reset(hba);
> +
> +		if (!err)
> +			ufshcd_set_ufs_dev_active(hba);
> +		if (err != -EOPNOTSUPP)
> +			ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, err);
>   	}
>   }
>   
> 


-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
Linux Foundation Collaborative Project

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

* Re: [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-03 14:14 ` [PATCH V4 1/2] " Adrian Hunter
                     ` (2 preceding siblings ...)
  2020-11-04 10:57   ` Bean Huo
@ 2020-11-04 16:35   ` Asutosh Das (asd)
  2020-11-05  1:42   ` Stanley Chu
  4 siblings, 0 replies; 18+ messages in thread
From: Asutosh Das (asd) @ 2020-11-04 16:35 UTC (permalink / raw)
  To: Adrian Hunter, Martin K . Petersen, James E . J . Bottomley
  Cc: linux-scsi, linux-kernel, Alim Akhtar, Avri Altman, Bean Huo,
	Can Guo, Stanley Chu

On 11/3/2020 6:14 AM, Adrian Hunter wrote:
> DeepSleep is a UFS v3.1 feature that achieves the lowest power consumption
> of the device, apart from power off.
> 
> In DeepSleep mode, no commands are accepted, and the only way to exit is
> using a hardware reset or power cycle.
> 
> This patch assumes that if a power cycle was an option, then power off
> would be preferable, so only exit via a hardware reset is supported.
> 
> Drivers that wish to support DeepSleep need to set a new capability flag
> UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing
>   ->device_reset() callback.
> 
> It is assumed that UFS devices with wspecversion >= 0x310 support
> DeepSleep.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---

Reviewed-by: Asutosh Das <asutoshd@codeaurora.org>


>   Documentation/ABI/testing/sysfs-driver-ufs | 34 +++++++++++--------
>   drivers/scsi/ufs/ufs-sysfs.c               |  7 ++++
>   drivers/scsi/ufs/ufs.h                     |  1 +
>   drivers/scsi/ufs/ufshcd.c                  | 39 ++++++++++++++++++++--
>   drivers/scsi/ufs/ufshcd.h                  | 17 +++++++++-
>   include/trace/events/ufs.h                 |  3 +-
>   6 files changed, 83 insertions(+), 18 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs b/Documentation/ABI/testing/sysfs-driver-ufs
> index adc0d0e91607..e77fa784d6d8 100644
> --- a/Documentation/ABI/testing/sysfs-driver-ufs
> +++ b/Documentation/ABI/testing/sysfs-driver-ufs
> @@ -916,21 +916,24 @@ Date:		September 2014
>   Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>   Description:	This entry could be used to set or show the UFS device
>   		runtime power management level. The current driver
> -		implementation supports 6 levels with next target states:
> +		implementation supports 7 levels with next target states:
>   
>   		==  ====================================================
> -		0   an UFS device will stay active, an UIC link will
> +		0   UFS device will stay active, UIC link will
>   		    stay active
> -		1   an UFS device will stay active, an UIC link will
> +		1   UFS device will stay active, UIC link will
>   		    hibernate
> -		2   an UFS device will moved to sleep, an UIC link will
> +		2   UFS device will be moved to sleep, UIC link will
>   		    stay active
> -		3   an UFS device will moved to sleep, an UIC link will
> +		3   UFS device will be moved to sleep, UIC link will
>   		    hibernate
> -		4   an UFS device will be powered off, an UIC link will
> +		4   UFS device will be powered off, UIC link will
>   		    hibernate
> -		5   an UFS device will be powered off, an UIC link will
> +		5   UFS device will be powered off, UIC link will
>   		    be powered off
> +		6   UFS device will be moved to deep sleep, UIC link
> +		will be powered off. Note, deep sleep might not be
> +		supported in which case this value will not be accepted
>   		==  ====================================================
>   
>   What:		/sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
> @@ -954,21 +957,24 @@ Date:		September 2014
>   Contact:	Subhash Jadavani <subhashj@codeaurora.org>
>   Description:	This entry could be used to set or show the UFS device
>   		system power management level. The current driver
> -		implementation supports 6 levels with next target states:
> +		implementation supports 7 levels with next target states:
>   
>   		==  ====================================================
> -		0   an UFS device will stay active, an UIC link will
> +		0   UFS device will stay active, UIC link will
>   		    stay active
> -		1   an UFS device will stay active, an UIC link will
> +		1   UFS device will stay active, UIC link will
>   		    hibernate
> -		2   an UFS device will moved to sleep, an UIC link will
> +		2   UFS device will be moved to sleep, UIC link will
>   		    stay active
> -		3   an UFS device will moved to sleep, an UIC link will
> +		3   UFS device will be moved to sleep, UIC link will
>   		    hibernate
> -		4   an UFS device will be powered off, an UIC link will
> +		4   UFS device will be powered off, UIC link will
>   		    hibernate
> -		5   an UFS device will be powered off, an UIC link will
> +		5   UFS device will be powered off, UIC link will
>   		    be powered off
> +		6   UFS device will be moved to deep sleep, UIC link
> +		will be powered off. Note, deep sleep might not be
> +		supported in which case this value will not be accepted
>   		==  ====================================================
>   
>   What:		/sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
> index bdcd27faa054..08e72b7eef6a 100644
> --- a/drivers/scsi/ufs/ufs-sysfs.c
> +++ b/drivers/scsi/ufs/ufs-sysfs.c
> @@ -28,6 +28,7 @@ static const char *ufschd_ufs_dev_pwr_mode_to_string(
>   	case UFS_ACTIVE_PWR_MODE:	return "ACTIVE";
>   	case UFS_SLEEP_PWR_MODE:	return "SLEEP";
>   	case UFS_POWERDOWN_PWR_MODE:	return "POWERDOWN";
> +	case UFS_DEEPSLEEP_PWR_MODE:	return "DEEPSLEEP";
>   	default:			return "UNKNOWN";
>   	}
>   }
> @@ -38,6 +39,7 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
>   					     bool rpm)
>   {
>   	struct ufs_hba *hba = dev_get_drvdata(dev);
> +	struct ufs_dev_info *dev_info = &hba->dev_info;
>   	unsigned long flags, value;
>   
>   	if (kstrtoul(buf, 0, &value))
> @@ -46,6 +48,11 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev,
>   	if (value >= UFS_PM_LVL_MAX)
>   		return -EINVAL;
>   
> +	if (ufs_pm_lvl_states[value].dev_state == UFS_DEEPSLEEP_PWR_MODE &&
> +	    (!(hba->caps & UFSHCD_CAP_DEEPSLEEP) ||
> +	     !(dev_info->wspecversion >= 0x310)))
> +		return -EINVAL;
> +
>   	spin_lock_irqsave(hba->host->host_lock, flags);
>   	if (rpm)
>   		hba->rpm_lvl = value;
> diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
> index f8ab16f30fdc..d593edb48767 100644
> --- a/drivers/scsi/ufs/ufs.h
> +++ b/drivers/scsi/ufs/ufs.h
> @@ -442,6 +442,7 @@ enum ufs_dev_pwr_mode {
>   	UFS_ACTIVE_PWR_MODE	= 1,
>   	UFS_SLEEP_PWR_MODE	= 2,
>   	UFS_POWERDOWN_PWR_MODE	= 3,
> +	UFS_DEEPSLEEP_PWR_MODE	= 4,
>   };
>   
>   #define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10)
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 2309253d3101..ee083b96e405 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -163,6 +163,11 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = {
>   	{UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>   	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE},
>   	{UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE},
> +	/*
> +	 * For DeepSleep, the link is first put in hibern8 and then off.
> +	 * Leaving the link in hibern8 is not supported.
> +	 */
> +	{UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE},
>   };
>   
>   static inline enum ufs_dev_pwr_mode
> @@ -8297,7 +8302,8 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba,
>   	}
>   	/*
>   	 * If autobkops is enabled, link can't be turned off because
> -	 * turning off the link would also turn off the device.
> +	 * turning off the link would also turn off the device, except in the
> +	 * case of DeepSleep where the device is expected to remain powered.
>   	 */
>   	else if ((req_link_state == UIC_LINK_OFF_STATE) &&
>   		 (!check_for_bkops || !hba->auto_bkops_enabled)) {
> @@ -8307,6 +8313,9 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba,
>   		 * put the link in low power mode is to send the DME end point
>   		 * to device and then send the DME reset command to local
>   		 * unipro. But putting the link in hibern8 is much faster.
> +		 *
> +		 * Note also that putting the link in Hibern8 is a requirement
> +		 * for entering DeepSleep.
>   		 */
>   		ret = ufshcd_uic_hibern8_enter(hba);
>   		if (ret) {
> @@ -8439,6 +8448,7 @@ static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba)
>   static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>   {
>   	int ret = 0;
> +	int check_for_bkops;
>   	enum ufs_pm_level pm_lvl;
>   	enum ufs_dev_pwr_mode req_dev_pwr_mode;
>   	enum uic_link_state req_link_state;
> @@ -8524,7 +8534,13 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>   	}
>   
>   	flush_work(&hba->eeh_work);
> -	ret = ufshcd_link_state_transition(hba, req_link_state, 1);
> +
> +	/*
> +	 * In the case of DeepSleep, the device is expected to remain powered
> +	 * with the link off, so do not check for bkops.
> +	 */
> +	check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
> +	ret = ufshcd_link_state_transition(hba, req_link_state, check_for_bkops);
>   	if (ret)
>   		goto set_dev_active;
>   
> @@ -8565,11 +8581,25 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>   	if (hba->clk_scaling.is_allowed)
>   		ufshcd_resume_clkscaling(hba);
>   	ufshcd_vreg_set_hpm(hba);
> +	/*
> +	 * Device hardware reset is required to exit DeepSleep. Also, for
> +	 * DeepSleep, the link is off so host reset and restore will be done
> +	 * further below.
> +	 */
> +	if (ufshcd_is_ufs_dev_deepsleep(hba)) {
> +		ufshcd_vops_device_reset(hba);
> +		WARN_ON(!ufshcd_is_link_off(hba));
> +	}
>   	if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba))
>   		ufshcd_set_link_active(hba);
>   	else if (ufshcd_is_link_off(hba))
>   		ufshcd_host_reset_and_restore(hba);
>   set_dev_active:
> +	/* Can also get here needing to exit DeepSleep */
> +	if (ufshcd_is_ufs_dev_deepsleep(hba)) {
> +		ufshcd_vops_device_reset(hba);
> +		ufshcd_host_reset_and_restore(hba);
> +	}
>   	if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE))
>   		ufshcd_disable_auto_bkops(hba);
>   enable_gating:
> @@ -8631,6 +8661,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>   	if (ret)
>   		goto disable_vreg;
>   
> +	/* For DeepSleep, the only supported option is to have the link off */
> +	WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && !ufshcd_is_link_off(hba));
> +
>   	if (ufshcd_is_link_hibern8(hba)) {
>   		ret = ufshcd_uic_hibern8_exit(hba);
>   		if (!ret) {
> @@ -8644,6 +8677,8 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>   		/*
>   		 * A full initialization of the host and the device is
>   		 * required since the link was put to off during suspend.
> +		 * Note, in the case of DeepSleep, the device will exit
> +		 * DeepSleep due to device reset.
>   		 */
>   		ret = ufshcd_reset_and_restore(hba);
>   		/*
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 0fbb735bb70c..213be0667b59 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -114,16 +114,22 @@ enum uic_link_state {
>   	((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE)
>   #define ufshcd_set_ufs_dev_poweroff(h) \
>   	((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE)
> +#define ufshcd_set_ufs_dev_deepsleep(h) \
> +	((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE)
>   #define ufshcd_is_ufs_dev_active(h) \
>   	((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE)
>   #define ufshcd_is_ufs_dev_sleep(h) \
>   	((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE)
>   #define ufshcd_is_ufs_dev_poweroff(h) \
>   	((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE)
> +#define ufshcd_is_ufs_dev_deepsleep(h) \
> +	((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE)
>   
>   /*
>    * UFS Power management levels.
> - * Each level is in increasing order of power savings.
> + * Each level is in increasing order of power savings, except DeepSleep
> + * which is lower than PowerDown with power on but not PowerDown with
> + * power off.
>    */
>   enum ufs_pm_level {
>   	UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */
> @@ -132,6 +138,7 @@ enum ufs_pm_level {
>   	UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */
>   	UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE */
>   	UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */
> +	UFS_PM_LVL_6, /* UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE */
>   	UFS_PM_LVL_MAX
>   };
>   
> @@ -599,6 +606,14 @@ enum ufshcd_caps {
>   	 * This would increase power savings.
>   	 */
>   	UFSHCD_CAP_AGGR_POWER_COLLAPSE			= 1 << 9,
> +
> +	/*
> +	 * This capability allows the host controller driver to use DeepSleep,
> +	 * if it is supported by the UFS device. The host controller driver must
> +	 * support device hardware reset via the hba->device_reset() callback,
> +	 * in order to exit DeepSleep state.
> +	 */
> +	UFSHCD_CAP_DEEPSLEEP				= 1 << 10,
>   };
>   
>   struct ufs_hba_variant_params {
> diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h
> index 84841b3a7ffd..2362244c2a9e 100644
> --- a/include/trace/events/ufs.h
> +++ b/include/trace/events/ufs.h
> @@ -19,7 +19,8 @@
>   #define UFS_PWR_MODES			\
>   	EM(UFS_ACTIVE_PWR_MODE)		\
>   	EM(UFS_SLEEP_PWR_MODE)		\
> -	EMe(UFS_POWERDOWN_PWR_MODE)
> +	EM(UFS_POWERDOWN_PWR_MODE)	\
> +	EMe(UFS_DEEPSLEEP_PWR_MODE)
>   
>   #define UFSCHD_CLK_GATING_STATES	\
>   	EM(CLKS_OFF)			\
> 


-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
Linux Foundation Collaborative Project

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

* Re: [PATCH V4 1/2] scsi: ufs: Add DeepSleep feature
  2020-11-03 14:14 ` [PATCH V4 1/2] " Adrian Hunter
                     ` (3 preceding siblings ...)
  2020-11-04 16:35   ` Asutosh Das (asd)
@ 2020-11-05  1:42   ` Stanley Chu
  4 siblings, 0 replies; 18+ messages in thread
From: Stanley Chu @ 2020-11-05  1:42 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Martin K . Petersen, James E . J . Bottomley, linux-scsi,
	linux-kernel, Alim Akhtar, Avri Altman, Bean Huo, Can Guo

On Tue, 2020-11-03 at 16:14 +0200, Adrian Hunter wrote:
> DeepSleep is a UFS v3.1 feature that achieves the lowest power consumption
> of the device, apart from power off.
> 
> In DeepSleep mode, no commands are accepted, and the only way to exit is
> using a hardware reset or power cycle.
> 
> This patch assumes that if a power cycle was an option, then power off
> would be preferable, so only exit via a hardware reset is supported.
> 
> Drivers that wish to support DeepSleep need to set a new capability flag
> UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing
>  ->device_reset() callback.
> 
> It is assumed that UFS devices with wspecversion >= 0x310 support
> DeepSleep.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>

Reviewed-by: Stanley Chu <stanley.chu@mediatek.com>



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

* Re: [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature
  2020-11-03 14:14 [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature Adrian Hunter
  2020-11-03 14:14 ` [PATCH V4 1/2] " Adrian Hunter
  2020-11-03 14:14 ` [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset() Adrian Hunter
@ 2020-11-05  4:06 ` Martin K. Petersen
  2020-11-11  2:58 ` Martin K. Petersen
  3 siblings, 0 replies; 18+ messages in thread
From: Martin K. Petersen @ 2020-11-05  4:06 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Martin K . Petersen, James E . J . Bottomley, linux-scsi,
	linux-kernel, Alim Akhtar, Avri Altman, Bean Huo, Can Guo,
	Stanley Chu


Adrian,

> Here is V4 of the DeepSleep feature patches.

Applied to 5.11/scsi-staging, thanks!

I left out the sysfs ABI piece due to the conflicts. I suggest you send
that piece through the doc tree.

-- 
Martin K. Petersen	Oracle Linux Engineering

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

* Re: [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature
  2020-11-03 14:14 [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature Adrian Hunter
                   ` (2 preceding siblings ...)
  2020-11-05  4:06 ` [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature Martin K. Petersen
@ 2020-11-11  2:58 ` Martin K. Petersen
  3 siblings, 0 replies; 18+ messages in thread
From: Martin K. Petersen @ 2020-11-11  2:58 UTC (permalink / raw)
  To: Adrian Hunter, James E . J . Bottomley
  Cc: Martin K . Petersen, Alim Akhtar, Can Guo, linux-kernel,
	Bean Huo, linux-scsi, Avri Altman, Stanley Chu

On Tue, 3 Nov 2020 16:14:01 +0200, Adrian Hunter wrote:

> Here is V4 of the DeepSleep feature patches.
> 
> 
> Changes in V4:
> 	Rebased
> 	Added new patch "scsi: ufs: Allow an error return value from ->device_reset()"
> 
> [...]

Applied to 5.11/scsi-queue, thanks!

[1/2] scsi: ufs: Add DeepSleep feature
      https://git.kernel.org/mkp/scsi/c/fe1d4c2ebcae
[2/2] scsi: ufs: Allow an error return value from ->device_reset()
      https://git.kernel.org/mkp/scsi/c/151f1b664ffb

-- 
Martin K. Petersen	Oracle Linux Engineering

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

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

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-03 14:14 [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature Adrian Hunter
2020-11-03 14:14 ` [PATCH V4 1/2] " Adrian Hunter
2020-11-04  8:04   ` Can Guo
2020-11-04  8:29   ` Can Guo
2020-11-04  8:37     ` Adrian Hunter
2020-11-04  9:03       ` Can Guo
2020-11-04 10:57   ` Bean Huo
2020-11-04 11:55     ` Adrian Hunter
2020-11-04 13:19       ` Bean Huo
2020-11-04 16:35   ` Asutosh Das (asd)
2020-11-05  1:42   ` Stanley Chu
2020-11-03 14:14 ` [PATCH V4 2/2] scsi: ufs: Allow an error return value from ->device_reset() Adrian Hunter
2020-11-04  2:55   ` Stanley Chu
2020-11-04  8:05   ` Can Guo
2020-11-04  8:44   ` Bean Huo
2020-11-04 16:35   ` Asutosh Das (asd)
2020-11-05  4:06 ` [PATCH V4 0/2] scsi: ufs: Add DeepSleep feature Martin K. Petersen
2020-11-11  2:58 ` Martin K. Petersen

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).