Hi folks,
This series fixes several stability issues with the upstream ufs-exynos driver, specifically for the gs101 SoC found in Pixel 6.
The main fix is regarding the IO cache coherency setting and ensuring that it is correctly applied depending on if the dma-coherent property is specified in device tree. This fixes the UFS stability issues on gs101 and I would imagine will also fix issues on exynosauto platform that seems to have similar iocc shareability bits.
Additionally the phy reference counting is fixed which allows module load/unload to work reliably and keeps the phy state machine in sync with the controller glue driver.
regards,
Peter
Changes since v1: * Added patch for correct handling of iocc depedent on dma-coherent property * Rebased onto next-20250319 * Add a gs101 specific suspend hook (Bart) * Drop asserting GPIO_OUT in .exit() (Peter) * Remove superfluous blank line (Bart) * Update PRDT_PREFECT_EN to PRDT_PREFETCH_EN (Bart) * Update commit description for desctype type 3 (Eric) * https://lore.kernel.org/lkml/20250226220414.343659-1-peter.griffin@linaro.or...
Signed-off-by: Peter Griffin peter.griffin@linaro.org --- Peter Griffin (7): scsi: ufs: exynos: ensure pre_link() executes before exynos_ufs_phy_init() scsi: ufs: exynos: move ufs shareability value to drvdata scsi: ufs: exynos: disable iocc if dma-coherent property isn't set scsi: ufs: exynos: ensure consistent phy reference counts scsi: ufs: exynos: Enable PRDT pre-fetching with UFSHCD_CAP_CRYPTO scsi: ufs: exynos: Move phy calls to .exit() callback scsi: ufs: exynos: gs101: put ufs device in reset on .suspend()
drivers/ufs/host/ufs-exynos.c | 85 ++++++++++++++++++++++++++++++++----------- drivers/ufs/host/ufs-exynos.h | 6 ++- 2 files changed, 68 insertions(+), 23 deletions(-) --- base-commit: 433ccb6f2e879866b8601fcb1de14e316cdb0d39 change-id: 20250319-exynos-ufs-stability-fixes-e8da9862e3dc
Best regards,
gs101 IO coherency shareability bits differ from exynosauto SoC. To support both SoCs move this info the SoC drvdata.
Currently both the value and mask are the same for both gs101 and exynosauto, thus we use the same value.
Signed-off-by: Peter Griffin peter.griffin@linaro.org Fixes: d11e0a318df8 ("scsi: ufs: exynos: Add support for Tensor gs101 SoC") Cc: stable@vger.kernel.org --- drivers/ufs/host/ufs-exynos.c | 20 ++++++++++++++------ drivers/ufs/host/ufs-exynos.h | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index 0c8c2e41e851cdbefc80a66d87273b7e8fcf9d4d..f393d42a659f821225e67e3e5d323478456ca3af 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -92,11 +92,16 @@ UIC_TRANSPORT_NO_CONNECTION_RX |\ UIC_TRANSPORT_BAD_TC)
-/* FSYS UFS Shareability */ -#define UFS_WR_SHARABLE BIT(2) -#define UFS_RD_SHARABLE BIT(1) -#define UFS_SHARABLE (UFS_WR_SHARABLE | UFS_RD_SHARABLE) -#define UFS_SHAREABILITY_OFFSET 0x710 +/* UFS Shareability */ +#define UFS_EXYNOSAUTO_WR_SHARABLE BIT(2) +#define UFS_EXYNOSAUTO_RD_SHARABLE BIT(1) +#define UFS_EXYNOSAUTO_SHARABLE (UFS_EXYNOSAUTO_WR_SHARABLE | \ + UFS_EXYNOSAUTO_RD_SHARABLE) +#define UFS_GS101_WR_SHARABLE BIT(1) +#define UFS_GS101_RD_SHARABLE BIT(0) +#define UFS_GS101_SHARABLE (UFS_GS101_WR_SHARABLE | \ + UFS_GS101_RD_SHARABLE) +#define UFS_SHAREABILITY_OFFSET 0x710
/* Multi-host registers */ #define MHCTRL 0xC4 @@ -210,7 +215,7 @@ static int exynos_ufs_shareability(struct exynos_ufs *ufs) if (ufs->sysreg) { return regmap_update_bits(ufs->sysreg, ufs->shareability_reg_offset, - UFS_SHARABLE, UFS_SHARABLE); + ufs->iocc_mask, ufs->iocc_mask); }
return 0; @@ -1174,6 +1179,7 @@ static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs) } }
+ ufs->iocc_mask = ufs->drv_data->iocc_mask; ufs->pclk_avail_min = PCLK_AVAIL_MIN; ufs->pclk_avail_max = PCLK_AVAIL_MAX;
@@ -2035,6 +2041,7 @@ static const struct exynos_ufs_drv_data exynosauto_ufs_drvs = { .opts = EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL | EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR | EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX, + .iocc_mask = UFS_EXYNOSAUTO_SHARABLE, .drv_init = exynosauto_ufs_drv_init, .post_hce_enable = exynosauto_ufs_post_hce_enable, .pre_link = exynosauto_ufs_pre_link, @@ -2136,6 +2143,7 @@ static const struct exynos_ufs_drv_data gs101_ufs_drvs = { .opts = EXYNOS_UFS_OPT_SKIP_CONFIG_PHY_ATTR | EXYNOS_UFS_OPT_UFSPR_SECURE | EXYNOS_UFS_OPT_TIMER_TICK_SELECT, + .iocc_mask = UFS_GS101_SHARABLE, .drv_init = gs101_ufs_drv_init, .pre_link = gs101_ufs_pre_link, .post_link = gs101_ufs_post_link, diff --git a/drivers/ufs/host/ufs-exynos.h b/drivers/ufs/host/ufs-exynos.h index aac5172761899a5dd8ad98f9ee34b1671dd27880..17696b3768debd641188b5089585b6d303de7451 100644 --- a/drivers/ufs/host/ufs-exynos.h +++ b/drivers/ufs/host/ufs-exynos.h @@ -181,6 +181,7 @@ struct exynos_ufs_drv_data { struct exynos_ufs_uic_attr *uic_attr; unsigned int quirks; unsigned int opts; + u32 iocc_mask; /* SoC's specific operations */ int (*drv_init)(struct exynos_ufs *ufs); int (*pre_link)(struct exynos_ufs *ufs); @@ -231,6 +232,7 @@ struct exynos_ufs { const struct exynos_ufs_drv_data *drv_data; struct regmap *sysreg; u32 shareability_reg_offset; + u32 iocc_mask;
u32 opts; #define EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL BIT(0)
If dma-coherent property isn't set then descriptors are non-cacheable and the iocc shareability bits should be disabled. Without this UFS can end up in an incompatible configuration and suffer from random cache related stability issues.
Suggested-by: Bart Van Assche bvanassche@acm.org Fixes: cc52e15397cc ("scsi: ufs: ufs-exynos: Support ExynosAuto v9 UFS") Signed-off-by: Peter Griffin peter.griffin@linaro.org Cc: Chanho Park chanho61.park@samsung.com Cc: stable@vger.kernel.org --- drivers/ufs/host/ufs-exynos.c | 17 +++++++++++++---- drivers/ufs/host/ufs-exynos.h | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index f393d42a659f821225e67e3e5d323478456ca3af..61b03e493cc1ddba17179a9f22e5b59ece02458b 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -214,8 +214,8 @@ static int exynos_ufs_shareability(struct exynos_ufs *ufs) /* IO Coherency setting */ if (ufs->sysreg) { return regmap_update_bits(ufs->sysreg, - ufs->shareability_reg_offset, - ufs->iocc_mask, ufs->iocc_mask); + ufs->iocc_offset, + ufs->iocc_mask, ufs->iocc_val); }
return 0; @@ -1173,13 +1173,22 @@ static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs) ufs->sysreg = NULL; else { if (of_property_read_u32_index(np, "samsung,sysreg", 1, - &ufs->shareability_reg_offset)) { + &ufs->iocc_offset)) { dev_warn(dev, "can't get an offset from sysreg. Set to default value\n"); - ufs->shareability_reg_offset = UFS_SHAREABILITY_OFFSET; + ufs->iocc_offset = UFS_SHAREABILITY_OFFSET; } }
ufs->iocc_mask = ufs->drv_data->iocc_mask; + /* + * no 'dma-coherent' property means the descriptors are + * non-cacheable so iocc shareability should be disabled. + */ + if (of_dma_is_coherent(dev->of_node)) + ufs->iocc_val = ufs->iocc_mask; + else + ufs->iocc_val = 0; + ufs->pclk_avail_min = PCLK_AVAIL_MIN; ufs->pclk_avail_max = PCLK_AVAIL_MAX;
diff --git a/drivers/ufs/host/ufs-exynos.h b/drivers/ufs/host/ufs-exynos.h index 17696b3768debd641188b5089585b6d303de7451..a345809af79dc528ad518d3572fe8be034341ee0 100644 --- a/drivers/ufs/host/ufs-exynos.h +++ b/drivers/ufs/host/ufs-exynos.h @@ -231,8 +231,9 @@ struct exynos_ufs { ktime_t entry_hibern8_t; const struct exynos_ufs_drv_data *drv_data; struct regmap *sysreg; - u32 shareability_reg_offset; + u32 iocc_offset; u32 iocc_mask; + u32 iocc_val;
u32 opts; #define EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL BIT(0)
ufshcd_link_startup() can call ufshcd_vops_link_startup_notify() multiple times when retrying. This causes the phy reference count to keep increasing and the phy to not properly re-initialize.
If the phy has already been previously powered on, first issue a phy_power_off() and phy_exit(), before re-initializing and powering on again.
Signed-off-by: Peter Griffin peter.griffin@linaro.org Fixes: 3d73b200f989 ("scsi: ufs: ufs-exynos: Change ufs phy control sequence") Cc: stable@vger.kernel.org --- drivers/ufs/host/ufs-exynos.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index 61b03e493cc1ddba17179a9f22e5b59ece02458b..34e16e198830d086cbdb6cb0b027ca92687b2ae6 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -962,6 +962,12 @@ static int exynos_ufs_phy_init(struct exynos_ufs *ufs) }
phy_set_bus_width(generic_phy, ufs->avail_ln_rx); + + if (generic_phy->power_count) { + phy_power_off(generic_phy); + phy_exit(generic_phy); + } + ret = phy_init(generic_phy); if (ret) { dev_err(hba->dev, "%s: phy init failed, ret = %d\n",
On 3/19/25 8:30 AM, Peter Griffin wrote:
This series fixes several stability issues with the upstream ufs-exynos driver, specifically for the gs101 SoC found in Pixel 6.
The main fix is regarding the IO cache coherency setting and ensuring that it is correctly applied depending on if the dma-coherent property is specified in device tree. This fixes the UFS stability issues on gs101 and I would imagine will also fix issues on exynosauto platform that seems to have similar iocc shareability bits.
Additionally the phy reference counting is fixed which allows module load/unload to work reliably and keeps the phy state machine in sync with the controller glue driver.
Although these patches are somewhat outside my area of expertise, the patches look good to me, hence:
Reviewed-by: Bart Van Assche bvanassche@acm.org
linux-stable-mirror@lists.linaro.org