Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c214857a authored by Stanley Chu's avatar Stanley Chu Committed by Greg Kroah-Hartman
Browse files

UPSTREAM: scsi: ufs-mediatek: Do not gate clocks if auto-hibern8 is not entered yet

There is a chance that link enters hibern8 via auto-hibern8 scheme during
the clock-gating flow. Clocks shall not be gated if link is still active
otherwise host or device may hang.

Fix this by returning error code to the caller __ufshcd_setup_clocks() to
skip gating clocks there if link is not confirmed in hibern8 state yet.

Also allow some waiting time for the hibern8 state transition.

Link: https://lore.kernel.org/r/20200601104646.15436-3-stanley.chu@mediatek.com


Reviewed-by: default avatarAndy Teng <andy.teng@mediatek.com>
Signed-off-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>

Bug: 151050916
(cherry picked from commit 9006e3986f6689897c2f1ede2671656b1cb41582)
Change-Id: Ieeccc13fd1f05463344c8f746ba7aa8ff172cd1a
Signed-off-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 767e2644
Loading
Loading
Loading
Loading
+27 −9
Original line number Diff line number Diff line
@@ -178,15 +178,30 @@ static void ufs_mtk_setup_ref_clk_wait_us(struct ufs_hba *hba,
	host->ref_clk_ungating_wait_us = ungating_us;
}

static u32 ufs_mtk_link_get_state(struct ufs_hba *hba)
int ufs_mtk_wait_link_state(struct ufs_hba *hba, u32 state,
			    unsigned long max_wait_ms)
{
	ktime_t timeout, time_checked;
	u32 val;

	timeout = ktime_add_us(ktime_get(), ms_to_ktime(max_wait_ms));
	do {
		time_checked = ktime_get();
		ufshcd_writel(hba, 0x20, REG_UFS_DEBUG_SEL);
		val = ufshcd_readl(hba, REG_UFS_PROBE);
		val = val >> 28;

	return val;
		if (val == state)
			return 0;

		/* Sleep for max. 200us */
		usleep_range(100, 200);
	} while (ktime_before(time_checked, timeout));

	if (val == state)
		return 0;

	return -ETIMEDOUT;
}

/**
@@ -221,11 +236,14 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on,
			 * triggered by Auto-Hibern8.
			 */
			if (!ufshcd_can_hibern8_during_gating(hba) &&
			    ufshcd_is_auto_hibern8_enabled(hba) &&
			    ufs_mtk_link_get_state(hba) ==
			    VS_LINK_HIBERN8)
			    ufshcd_is_auto_hibern8_enabled(hba)) {
				ret = ufs_mtk_wait_link_state(hba,
							      VS_LINK_HIBERN8,
							      15);
				if (!ret)
					ufs_mtk_setup_ref_clk(hba, on);
			}
		}
	} else if (on && status == POST_CHANGE) {
		ret = phy_power_on(host->mphy);
		ufs_mtk_setup_ref_clk(hba, on);