[PATCH v5] scsi: ufs: core: call hibern8 notify when hibern8 cmd failed
From: Hongjie Fang
Date: Sat May 02 2026 - 10:31:28 EST
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 third enum ROLLBACK_CHANGE for the ufshcd_vops_hibern8_notify(),
pass the ROLLBACK_CHANGE when the hibern8 command returns a failure and
use the POST_CHANGE otherwise.
Signed-off-by: Hongjie Fang <hongjiefang@xxxxxxxxxxxx>
---
drivers/ufs/core/ufshcd.c | 11 ++++++-----
drivers/ufs/host/ufs-exynos.c | 6 ++++++
drivers/ufs/host/ufs-qcom.c | 4 +++-
include/ufs/ufshcd.h | 1 +
4 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 9ceb6d6d479d..1d4939bb7ec0 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -4500,9 +4500,9 @@ 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,
+ ret ? ROLLBACK_CHANGE : POST_CHANGE);
return ret;
}
@@ -4526,12 +4526,13 @@ 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,
+ ret ? ROLLBACK_CHANGE : POST_CHANGE);
+
return ret;
}
EXPORT_SYMBOL_GPL(ufshcd_uic_hibern8_exit);
diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index 76fee3a79c77..7ada4e96f236 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -1654,6 +1654,8 @@ static int exynos_ufs_hce_enable_notify(struct ufs_hba *hba,
if (ufs->drv_data->post_hce_enable)
ret = ufs->drv_data->post_hce_enable(ufs);
+ break;
+ default:
break;
}
@@ -1672,6 +1674,8 @@ static int exynos_ufs_link_startup_notify(struct ufs_hba *hba,
case POST_CHANGE:
ret = exynos_ufs_post_link(hba);
break;
+ default:
+ break;
}
return ret;
@@ -1692,6 +1696,8 @@ static int exynos_ufs_pwr_change_notify(struct ufs_hba *hba,
case POST_CHANGE:
ret = exynos_ufs_post_pwr_mode(hba, dev_req_params);
break;
+ default:
+ break;
}
return ret;
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 375fd24ba458..4f1caf8dabbf 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -1234,7 +1234,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct phy *phy;
- int err;
+ int err = 0;
/*
* In case ufs_qcom_init() is not yet done, simply ignore.
@@ -1289,6 +1289,8 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
ufs_qcom_bw_table[MODE_MIN][0][0].cfg_bw);
}
break;
+ default:
+ break;
}
return 0;
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index 8563b6648976..4f7c619db324 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -270,6 +270,7 @@ struct ufs_clk_info {
enum ufs_notify_change_status {
PRE_CHANGE,
POST_CHANGE,
+ ROLLBACK_CHANGE,
};
struct ufs_pa_layer_attr {
--
2.25.1