Linux SCSI subsystem development
 help / color / mirror / Atom feed
* [PATCH v2] scsi: ufs: core: call hibern8 notify when hibern8 cmd failed
@ 2026-04-29 11:23 Hongjie Fang
  2026-04-29 16:23 ` Bart Van Assche
  0 siblings, 1 reply; 3+ messages in thread
From: Hongjie Fang @ 2026-04-29 11:23 UTC (permalink / raw)
  To: alim.akhtar, avri.altman, bvanassche, James.Bottomley,
	martin.petersen
  Cc: linux-scsi, linux-kernel

The vendor hibern8 notify callback always can be executed in the
PRE_CHANGE phase of hibern8 enter/exit. But it cannot be executed
in the POST_CHANGE phase if the hibern8 cmd fails.

When the hibern8 cmd fails, the vendor hibern8 notify callback
should still have the opportunity to execute.

Add a new argument to ufshcd_vops_hibern8_notify() that represents
whether or not the hibern8 cmd succeeded for POST_CHANGE callbacks.

Signed-off-by: Hongjie Fang <hongjiefang@asrmicro.com>
---
 drivers/ufs/core/ufshcd-priv.h |  5 +++--
 drivers/ufs/core/ufshcd.c      | 13 ++++++-------
 drivers/ufs/host/cdns-pltfrm.c |  4 ++--
 drivers/ufs/host/ufs-exynos.c  |  6 ++++--
 drivers/ufs/host/ufs-sprd.c    |  5 +++--
 include/ufs/ufshcd.h           |  3 ++-
 6 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index 37c32071e754..1d3b90e280a9 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -188,10 +188,11 @@ static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba,
 
 static inline void ufshcd_vops_hibern8_notify(struct ufs_hba *hba,
 					enum uic_cmd_dme cmd,
-					enum ufs_notify_change_status status)
+					enum ufs_notify_change_status status,
+					int cmd_ret)
 {
 	if (hba->vops && hba->vops->hibern8_notify)
-		return hba->vops->hibern8_notify(hba, cmd, status);
+		return hba->vops->hibern8_notify(hba, cmd, status, cmd_ret);
 }
 
 static inline int ufshcd_vops_apply_dev_quirks(struct ufs_hba *hba)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 9ceb6d6d479d..ec636a9b643d 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -4491,7 +4491,7 @@ int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
 	ktime_t start = ktime_get();
 	int ret;
 
-	ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER, PRE_CHANGE);
+	ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER, PRE_CHANGE, 0);
 
 	ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
 	trace_ufshcd_profile_hibern8(hba, "enter",
@@ -4500,9 +4500,8 @@ int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
 	if (ret)
 		dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
 			__func__, ret);
-	else
-		ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER,
-								POST_CHANGE);
+
+	ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER, POST_CHANGE, ret);
 
 	return ret;
 }
@@ -4516,7 +4515,7 @@ int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
 	int ret;
 	ktime_t start = ktime_get();
 
-	ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT, PRE_CHANGE);
+	ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT, PRE_CHANGE, 0);
 
 	ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
 	trace_ufshcd_profile_hibern8(hba, "exit",
@@ -4526,12 +4525,12 @@ int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
 		dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d\n",
 			__func__, ret);
 	} else {
-		ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT,
-								POST_CHANGE);
 		hba->ufs_stats.last_hibern8_exit_tstamp = local_clock();
 		hba->ufs_stats.hibern8_exit_cnt++;
 	}
 
+	ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_EXIT, POST_CHANGE, ret);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(ufshcd_uic_hibern8_exit);
diff --git a/drivers/ufs/host/cdns-pltfrm.c b/drivers/ufs/host/cdns-pltfrm.c
index e793e3538c48..5822f23acd93 100644
--- a/drivers/ufs/host/cdns-pltfrm.c
+++ b/drivers/ufs/host/cdns-pltfrm.c
@@ -164,11 +164,11 @@ static int cdns_ufs_hce_enable_notify(struct ufs_hba *hba,
  * @status: notify stage (pre, post change)
  */
 static void cdns_ufs_hibern8_notify(struct ufs_hba *hba, enum uic_cmd_dme cmd,
-				    enum ufs_notify_change_status status)
+				    enum ufs_notify_change_status status, int cmd_ret)
 {
 	if (status == PRE_CHANGE && cmd == UIC_CMD_DME_HIBER_ENTER)
 		cdns_ufs_get_l4_attr(hba);
-	if (status == POST_CHANGE && cmd == UIC_CMD_DME_HIBER_EXIT)
+	if (status == POST_CHANGE && cmd == UIC_CMD_DME_HIBER_EXIT && !cmd_ret)
 		cdns_ufs_set_l4_attr(hba);
 }
 
diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index 76fee3a79c77..83f19a3411c5 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -1699,14 +1699,16 @@ static int exynos_ufs_pwr_change_notify(struct ufs_hba *hba,
 
 static void exynos_ufs_hibern8_notify(struct ufs_hba *hba,
 				     enum uic_cmd_dme cmd,
-				     enum ufs_notify_change_status notify)
+				     enum ufs_notify_change_status notify,
+				     int cmd_ret)
 {
 	switch ((u8)notify) {
 	case PRE_CHANGE:
 		exynos_ufs_pre_hibern8(hba, cmd);
 		break;
 	case POST_CHANGE:
-		exynos_ufs_post_hibern8(hba, cmd);
+		if (!cmd_ret)
+			exynos_ufs_post_hibern8(hba, cmd);
 		break;
 	}
 }
diff --git a/drivers/ufs/host/ufs-sprd.c b/drivers/ufs/host/ufs-sprd.c
index 65bd8fb96b99..70423a766b32 100644
--- a/drivers/ufs/host/ufs-sprd.c
+++ b/drivers/ufs/host/ufs-sprd.c
@@ -352,7 +352,8 @@ static int sprd_ufs_n6_hce_enable_notify(struct ufs_hba *hba,
 
 static void sprd_ufs_n6_h8_notify(struct ufs_hba *hba,
 				  enum uic_cmd_dme cmd,
-				  enum ufs_notify_change_status status)
+				  enum ufs_notify_change_status status,
+				  int cmd_ret)
 {
 	struct ufs_sprd_priv *priv = ufs_sprd_get_priv_data(hba);
 
@@ -372,7 +373,7 @@ static void sprd_ufs_n6_h8_notify(struct ufs_hba *hba,
 		}
 	}
 
-	if (status == POST_CHANGE) {
+	if (status == POST_CHANGE && !cmd_ret) {
 		if (cmd == UIC_CMD_DME_HIBER_EXIT)
 			ufs_sprd_ctrl_uic_compl(hba, true);
 
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 8563b6648976..c1cb30d8aa4a 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -355,7 +355,8 @@ struct ufs_hba_variant_ops {
 				  bool is_scsi_cmd);
 	void	(*setup_task_mgmt)(struct ufs_hba *, int, u8);
 	void    (*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme,
-					enum ufs_notify_change_status);
+					enum ufs_notify_change_status,
+					int cmd_ret);
 	int	(*apply_dev_quirks)(struct ufs_hba *hba);
 	void	(*fixup_dev_quirks)(struct ufs_hba *hba);
 	int     (*suspend)(struct ufs_hba *, enum ufs_pm_op,
-- 
2.25.1


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

end of thread, other threads:[~2026-04-30  2:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-29 11:23 [PATCH v2] scsi: ufs: core: call hibern8 notify when hibern8 cmd failed Hongjie Fang
2026-04-29 16:23 ` Bart Van Assche
2026-04-30  2:40   ` Fang Hongjie(方洪杰)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox