Re: [PATCH] scsi: ufs: core: cancel RTC work in active-active suspend

From: Bean Huo

Date: Wed Jul 08 2026 - 17:09:30 EST


On Wed, 2026-07-08 at 20:49 +0800, Guangshuo Li wrote:
> UFS RTC support schedules ufs_rtc_update_work to periodically update the
> device RTC. The work can issue query commands and access the UFS host
> controller.
>
> __ufshcd_wl_suspend() cancels ufs_rtc_update_work in the common suspend
> path before calling the vendor suspend callback. However, the
> active-active path, where both the device power mode and link state stay
> active, jumps directly to vops_suspend after flushing exception handling
> work. That jump bypasses the RTC work cancellation.
>
> If the RTC work runs while the vendor suspend callback is gating or
> otherwise changing hardware state, it can access the controller during
> suspend and trigger an SError.
>
> Cancel the RTC work in the active-active path before jumping to
> vops_suspend, matching the common suspend path.
>
> Fixes: 6bf999e0eb41 ("scsi: ufs: core: Add UFS RTC support")


this fix tag is wrong, should be:
Fixes: b0bd84c39289 ("scsi: ufs: core: Fix SError in ufshcd_rtc_work() during
UFS suspend")

since 6bf999e0eb41 ("scsi: ufs: core: Add UFS RTC support") placed the cancel
after the vops_suspend: label (after the POST_CHANGE vops call), so the active-
active goto vops_suspend path did cancel the work. then b0bd84c39289 ("scsi:
ufs: core: Fix SError in ufshcd_rtc_work() during UFS suspend", moved the cancel
up above the PRE_CHANGE vops call to close a race in the common path. That move
is what removed cancellation from the active-active path. So the correct tag is
Fixes: b0bd84c39289, not 6bf999e0eb41.

> Signed-off-by: Guangshuo Li <lgs201920130244@xxxxxxxxx>
> ---
>  drivers/ufs/core/ufshcd.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
> index d3044a3089b5..9d5571a7aec2 100644
> --- a/drivers/ufs/core/ufshcd.c
> +++ b/drivers/ufs/core/ufshcd.c
> @@ -10269,6 +10269,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba,
> enum ufs_pm_op pm_op)
>                         req_link_state == UIC_LINK_ACTIVE_STATE) {
>                 ufshcd_disable_auto_bkops(hba);
>                 flush_work(&hba->eeh_work);
> +               cancel_delayed_work_sync(&hba->ufs_rtc_update_work);

RTC updates stop permanently after the first active-active suspend. you need to
add resume:



diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 376a314189e4..06f253b08b65 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -10339,6 +10339,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum
ufs_pm_op pm_op)
req_link_state == UIC_LINK_ACTIVE_STATE) {
ufshcd_disable_auto_bkops(hba);
flush_work(&hba->eeh_work);
+ cancel_delayed_work_sync(&hba->ufs_rtc_update_work);
goto vops_suspend;
}

@@ -10548,10 +10549,11 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba,
enum ufs_pm_op pm_op)
if (ret)
goto set_old_link_state;
ufshcd_set_timestamp_attr(hba);
- schedule_delayed_work(&hba->ufs_rtc_update_work,
-
msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS));
}

+ schedule_delayed_work(&hba->ufs_rtc_update_work,
+ msecs_to_jiffies(UFS_RTC_UPDATE_INTERVAL_MS));
+
if (ufshcd_keep_autobkops_enabled_except_suspend(hba))
ufshcd_enable_auto_bkops(hba);
else

Kind regards,
Bean



>                 goto vops_suspend;
>         }
>