lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20251025160905.3857885-150-sashal@kernel.org>
Date: Sat, 25 Oct 2025 11:56:21 -0400
From: Sasha Levin <sashal@...nel.org>
To: patches@...ts.linux.dev,
	stable@...r.kernel.org
Cc: Peter Wang <peter.wang@...iatek.com>,
	"Martin K. Petersen" <martin.petersen@...cle.com>,
	Sasha Levin <sashal@...nel.org>,
	matthias.bgg@...il.com,
	angelogioacchino.delregno@...labora.com,
	linux-scsi@...r.kernel.org,
	linux-mediatek@...ts.infradead.org,
	linux-kernel@...r.kernel.org,
	linux-arm-kernel@...ts.infradead.org
Subject: [PATCH AUTOSEL 6.17-6.6] scsi: ufs: host: mediatek: Disable auto-hibern8 during power mode changes

From: Peter Wang <peter.wang@...iatek.com>

[ Upstream commit f5ca8d0c7a6388abd5d8023cc682e1543728cc73 ]

Disable auto-hibern8 during power mode transitions to prevent unintended
entry into auto-hibern8. Restore the original auto-hibern8 timer value
after completing the power mode change to maintain system stability and
prevent potential issues during power state transitions.

Signed-off-by: Peter Wang <peter.wang@...iatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@...cle.com>
Signed-off-by: Sasha Levin <sashal@...nel.org>
---

LLM Generated explanations, may be completely bogus:

YES

Summary
- The change disables Auto-Hibern8 (AH8) around UFS power mode
  transitions and restores the prior timer afterward. This prevents
  unintended AH8 entry while the link is being reconfigured, which can
  cause timeouts or recovery events during transitions. The fix is
  small, self-contained, and limited to the Mediatek UFS host driver.

What the patch does
- Saves current AH8 timer and disables AH8 in PRE_CHANGE:
  - drivers/ufs/host/ufs-mediatek.c:1472–1476
    - Reads `REG_AUTO_HIBERNATE_IDLE_TIMER` into a static `reg` and
      calls `ufs_mtk_auto_hibern8_disable(hba)`.
- Disables AH8 in a helper and ensures the link is up before proceeding:
  - drivers/ufs/host/ufs-mediatek.c:1436–1461
    - Writes 0 to `REG_AUTO_HIBERNATE_IDLE_TIMER` (disables AH8), waits
      for the host idle state, then waits for `VS_LINK_UP`. On failure,
      warns and triggers `ufshcd_force_error_recovery(hba)` and returns
      `-EBUSY`.
- Restores the previous AH8 timer in POST_CHANGE:
  - drivers/ufs/host/ufs-mediatek.c:1480–1483

Why this fixes a bug
- Power mode transitions involve DME configuration and link parameter
  changes (see setup/adaptation in `ufs_mtk_pre_pwr_change()`:
  drivers/ufs/host/ufs-mediatek.c:1405–1434). If the link enters AH8
  mid-transition, the controller and device can deadlock or time out,
  requiring error recovery. Temporarily disabling AH8 ensures the link
  stays in the expected state while power mode changes occur and
  restores normal power-saving afterwards.
- The helper already used in suspend PRE_CHANGE (drivers/ufs/host/ufs-
  mediatek.c:1748–1751) shows the driver’s established pattern to
  disable AH8 before low-power transitions; extending this to power mode
  changes closes a similar race.

Scope and risk
- Scope: One driver file; no UFS core changes; no architectural shifts.
  Uses existing helpers (`ufshcd_is_auto_hibern8_supported`,
  `ufshcd_readl/writel`, `ufs_mtk_wait_*`,
  `ufshcd_force_error_recovery`).
- Regression risk: Low. Behavior change is to temporarily disable AH8
  only during power mode changes and then restore the previous timer.
  - Note: `ufs_mtk_pwr_change_notify()` stores the old AH8 timer in a
    function-scope static (`reg`) (drivers/ufs/host/ufs-
    mediatek.c:1469). While typical Mediatek systems have a single UFS
    host and power mode changes are serialized, a static variable is
    theoretically shared if multiple controllers triggered this
    concurrently. In practice, impact is negligible on common
    configurations.
  - Note: The PRE_CHANGE path does not propagate the return of
    `ufs_mtk_auto_hibern8_disable()` (drivers/ufs/host/ufs-
    mediatek.c:1473–1478). The helper triggers error recovery internally
    and returns `-EBUSY`, so recovery still occurs, but the immediate
    PRE_CHANGE return value won’t reflect the failure. A tiny follow-up
    improvement would propagate this error directly (as done later in-
    tree).

Evidence of established pattern
- Other vendor drivers also manage AH8 around sensitive transitions,
  supporting this approach:
  - Hisilicon disables/adjusts AH8 during link setup:
    drivers/ufs/host/ufs-hisi.c:234–237
  - Spreadtrum disables AH8 during suspend PRE_CHANGE:
    drivers/ufs/host/ufs-sprd.c:185–190

Stable backport criteria
- Fixes a real operational bug (unintended AH8 mid-transition),
  observable as timeouts or recovery during power mode changes.
- Small, targeted change in a single vendor driver; minimal risk to
  other subsystems.
- No new features or architectural changes; follows established patterns
  in UFS vendor drivers.
- While the commit message lacks an explicit Fixes/Stable tag, the
  change aligns well with stable policy as a platform-specific
  reliability fix.

Recommendation
- Backport to stable: YES.
- Optional but advisable: include the small follow-up that returns an
  error immediately on idle wait timeout (to propagate the PRE_CHANGE
  failure) to match the improved error handling now seen in-tree.

 drivers/ufs/host/ufs-mediatek.c | 53 +++++++++++++++++++--------------
 1 file changed, 30 insertions(+), 23 deletions(-)

diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index 91081d2aabe44..3defb5f135e33 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -1400,19 +1400,49 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba,
 	return ret;
 }
 
+static int ufs_mtk_auto_hibern8_disable(struct ufs_hba *hba)
+{
+	int ret;
+
+	/* disable auto-hibern8 */
+	ufshcd_writel(hba, 0, REG_AUTO_HIBERNATE_IDLE_TIMER);
+
+	/* wait host return to idle state when auto-hibern8 off */
+	ufs_mtk_wait_idle_state(hba, 5);
+
+	ret = ufs_mtk_wait_link_state(hba, VS_LINK_UP, 100);
+	if (ret) {
+		dev_warn(hba->dev, "exit h8 state fail, ret=%d\n", ret);
+
+		ufshcd_force_error_recovery(hba);
+
+		/* trigger error handler and break suspend */
+		ret = -EBUSY;
+	}
+
+	return ret;
+}
+
 static int ufs_mtk_pwr_change_notify(struct ufs_hba *hba,
 				enum ufs_notify_change_status stage,
 				const struct ufs_pa_layer_attr *dev_max_params,
 				struct ufs_pa_layer_attr *dev_req_params)
 {
 	int ret = 0;
+	static u32 reg;
 
 	switch (stage) {
 	case PRE_CHANGE:
+		if (ufshcd_is_auto_hibern8_supported(hba)) {
+			reg = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER);
+			ufs_mtk_auto_hibern8_disable(hba);
+		}
 		ret = ufs_mtk_pre_pwr_change(hba, dev_max_params,
 					     dev_req_params);
 		break;
 	case POST_CHANGE:
+		if (ufshcd_is_auto_hibern8_supported(hba))
+			ufshcd_writel(hba, reg, REG_AUTO_HIBERNATE_IDLE_TIMER);
 		break;
 	default:
 		ret = -EINVAL;
@@ -1646,29 +1676,6 @@ static void ufs_mtk_dev_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
 	}
 }
 
-static int ufs_mtk_auto_hibern8_disable(struct ufs_hba *hba)
-{
-	int ret;
-
-	/* disable auto-hibern8 */
-	ufshcd_writel(hba, 0, REG_AUTO_HIBERNATE_IDLE_TIMER);
-
-	/* wait host return to idle state when auto-hibern8 off */
-	ufs_mtk_wait_idle_state(hba, 5);
-
-	ret = ufs_mtk_wait_link_state(hba, VS_LINK_UP, 100);
-	if (ret) {
-		dev_warn(hba->dev, "exit h8 state fail, ret=%d\n", ret);
-
-		ufshcd_force_error_recovery(hba);
-
-		/* trigger error handler and break suspend */
-		ret = -EBUSY;
-	}
-
-	return ret;
-}
-
 static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
 	enum ufs_notify_change_status status)
 {
-- 
2.51.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ