scsi: ufs: core: Always notify POST_CHANGE even on gear switch failure

Previously, POST_CHANGE was only notified on a successful gear switch.
This could leave the host in an inconsistent state if resources were
acquired in PRE_CHANGE (e.g. disabling auto-hibern8) but never released due
to a missing POST_CHANGE.

Fix this by always calling POST_CHANGE regardless of the gear switch
result. On failure, pass dev_req_params = NULL to signal that there is
nothing to apply; hosts that receive NULL simply skip their post work.

Update the affected drivers (ufs-exynos and ufshcd-pci) to guard their
POST_CHANGE logic with a NULL check so they correctly handle the failure
case.

Fixes: f5ca8d0c7a ("scsi: ufs: host: mediatek: Disable auto-hibern8 during power mode changes")
Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Reviewed-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Link: https://patch.msgid.link/20260914085148.136429-2-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
This commit is contained in:
Peter Wang 2026-09-14 16:49:24 +08:00 committed by Martin K. Petersen (Oracle)
parent 00eec343c7
commit 6efee14ca0
3 changed files with 11 additions and 4 deletions

View File

@ -5020,8 +5020,12 @@ int ufshcd_change_power_mode(struct ufs_hba *hba,
ret = ufshcd_dme_change_power_mode(hba, pwr_mode, pmc_policy);
if (!ret)
ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, pwr_mode);
/*
* Always notify POST_CHANGE to pair with PRE_CHANGE, even on failure.
* On failure, pass dev_req_params = NULL to indicate nothing to apply.
* POST_CHANGE return value is advisory and does not mask @ret.
*/
ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, ret ? NULL : pwr_mode);
return ret;
}

View File

@ -1782,7 +1782,9 @@ static int exynos_ufs_pwr_change_notify(struct ufs_hba *hba,
ret = exynos_ufs_pre_pwr_mode(hba, dev_req_params);
break;
case POST_CHANGE:
ret = exynos_ufs_post_pwr_mode(hba, dev_req_params);
/* NULL when the gear switch failed: nothing to apply */
if (dev_req_params)
ret = exynos_ufs_post_pwr_mode(hba, dev_req_params);
break;
}

View File

@ -166,7 +166,8 @@ static int ufs_intel_lkf_pwr_change_notify(struct ufs_hba *hba,
ufs_intel_set_lanes(hba, 2);
break;
case POST_CHANGE:
if (ufshcd_is_hs_mode(dev_req_params)) {
/* NULL when the gear switch failed: nothing to apply */
if (dev_req_params && ufshcd_is_hs_mode(dev_req_params)) {
u32 peer_granularity;
usleep_range(1000, 1250);