Re: [PATCH] firmware: xilinx: ufs: move PHY/SRAM ready polling into the firmware backend

[email protected] Tue, 04 Aug 2026 15:32:02 +0000
Newsgroups gmane.linux.scsi
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 2 potential issue(=
s) to consider:
- [Medium] The patch makes per-read primitives static and un-exports them, =
contradicting the commit message claim that they stay exported.
- [Medium] The refactoring regresses error handling by grouping lower-level=
 firmware transport failures under hardware-specific timeout error messages.
--

--- Patch [1]: [PATCH] firmware: xilinx: ufs: move PHY/SRAM ready polling i=
nto the firmware backend ---
commit e824b853b832156de7cffafd5b473161a8e6545d
Author: Michal Simek <[email protected]>

firmware: xilinx: ufs: move PHY/SRAM ready polling into the firmware backend

This commit moves the open-coded do/while polling loops for UFS PHY and SRA=
M=20
initialization into coarse blocking helpers in the firmware driver. It=20
introduces zynqmp_pm_wait_mphy_tx_rx_config_ready() and=20
zynqmp_pm_wait_sram_init_done() to keep the UFS controller backend-agnostic.

> Introduce coarse blocking helpers, zynqmp_pm_wait_mphy_tx_rx_config_ready=
()
> and zynqmp_pm_wait_sram_init_done(), that take a caller-supplied timeout
> budget and contain the poll loop. The loop is EEMI-specific (legacy
> firmware only exposes the per-read status primitive) so it lives in the
> firmware driver, keeping the UFS driver backend-agnostic: a future
> backend can offload the wait to the platform in a single call without
> touching the controller driver again. The existing per-read primitives st=
ay
> exported, so the current EEMI interface is unchanged.

[Severity: Medium]
The commit message indicates that "The existing per-read primitives stay
exported, so the current EEMI interface is unchanged." However, the code
modifications below make these functions static and remove their prototypes.
Is it intentional to un-export these primitives, contrary to the commit
message?

> diff --git a/drivers/firmware/xilinx/zynqmp-ufs.c b/drivers/firmware/xili=
nx/zynqmp-ufs.c
> index 85da8a822f3a5..81ccf61a037ce 100644
> --- a/drivers/firmware/xilinx/zynqmp-ufs.c
> +++ b/drivers/firmware/xilinx/zynqmp-ufs.c

[ ... ]

> @@ -33,7 +34,7 @@
>   *
>   * Return:	Returns 0 on success or error value on failure.
>   */
> -int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready)
> +static int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready)
>  {
>  	u32 regval;
>  	int ret;
> @@ -53,7 +54,6 @@ int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready)
> =20
>  	return ret;
>  }
> -EXPORT_SYMBOL_GPL(zynqmp_pm_is_mphy_tx_rx_config_ready);

[ ... ]

> @@ -61,7 +61,7 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_is_mphy_tx_rx_config_ready);
>   *
>   * Return:	Returns 0 on success or error value on failure.
>   */
> -int zynqmp_pm_is_sram_init_done(bool *is_done)
> +static int zynqmp_pm_is_sram_init_done(bool *is_done)
>  {
>  	u32 regval;
>  	int ret;
> @@ -81,7 +81,69 @@ int zynqmp_pm_is_sram_init_done(bool *is_done)
> =20
>  	return ret;
>  }
> -EXPORT_SYMBOL_GPL(zynqmp_pm_is_sram_init_done);

[ ... ]

> diff --git a/drivers/ufs/host/ufs-amd-versal2.c b/drivers/ufs/host/ufs-am=
d-versal2.c
> index 2154d62868171..dff0c2c954865 100644
> --- a/drivers/ufs/host/ufs-amd-versal2.c
> +++ b/drivers/ufs/host/ufs-amd-versal2.c

[ ... ]

> @@ -235,23 +233,15 @@ static int ufs_versal2_phy_init(struct ufs_hba *hba)
>  		{ UIC_ARG_MIB(VS_MPHYCFGUPDT), 1, DME_LOCAL }
>  	};
> =20
> -	/* Wait for Tx/Rx config_rdy */
> -	time_left =3D TIMEOUT_MICROSEC;
> -	do {
> -		time_left--;
> -		ret =3D zynqmp_pm_is_mphy_tx_rx_config_ready(&is_ready);
> -		if (ret)
> -			return ret;
> -
> -		if (!is_ready)
> -			break;
> -
> -		usleep_range(1, 5);
> -	} while (time_left);
> -
> -	if (!time_left) {
> +	/*
> +	 * Wait for Tx/Rx config_rdy. The poll loop lives in the firmware
> +	 * backend (EEMI today, SCMI in future) so this driver stays
> +	 * backend-agnostic; the timeout budget stays here with the consumer.
> +	 */
> +	ret =3D zynqmp_pm_wait_mphy_tx_rx_config_ready(TIMEOUT_MICROSEC);
> +	if (ret) {
>  		dev_err(hba->dev, "Tx/Rx configuration signal busy.\n");
> -		return -ETIMEDOUT;
> +		return ret;
>  	}

[Severity: Medium]
Will this change result in misleading error logs if a firmware transport
error occurs?

In the original code, if zynqmp_pm_is_mphy_tx_rx_config_ready() failed with=
 a
transport error like -EIO, the function returned silently. The
"Tx/Rx configuration signal busy" error was only logged when the timeout
actually expired.

With this update, if zynqmp_pm_wait_mphy_tx_rx_config_ready() returns -EIO,
it seems we will incorrectly log "Tx/Rx configuration signal busy." instead
of propagating the transport failure silently.

>  	ret =3D ufshcd_dwc_dme_set_attrs(hba, rmmi_attrs, ARRAY_SIZE(rmmi_attrs=
));
> @@ -264,23 +254,11 @@ static int ufs_versal2_phy_init(struct ufs_hba *hba)
>  		return ret;
>  	}
> =20
> -	/* Wait for SRAM init done */
> -	time_left =3D TIMEOUT_MICROSEC;
> -	do {
> -		time_left--;
> -		ret =3D zynqmp_pm_is_sram_init_done(&is_ready);
> -		if (ret)
> -			return ret;
> -
> -		if (is_ready)
> -			break;
> -
> -		usleep_range(1, 5);
> -	} while (time_left);
> -
> -	if (!time_left) {
> +	/* Wait for SRAM init done (poll handled by the firmware backend). */
> +	ret =3D zynqmp_pm_wait_sram_init_done(TIMEOUT_MICROSEC);
> +	if (ret) {
>  		dev_err(hba->dev, "SRAM initialization failed.\n");
> -		return -ETIMEDOUT;
> +		return ret;
>  	}

[Severity: Medium]
Similarly, if zynqmp_pm_wait_sram_init_done() returns a generic firmware
transport error, will it now misleadingly print "SRAM initialization failed=
."
rather than bubbling up the underlying error?

[ ... ]

> diff --git a/include/linux/firmware/xlnx-zynqmp-ufs.h b/include/linux/fir=
mware/xlnx-zynqmp-ufs.h
> index d3538dd5822a5..00383dd835f24 100644
> --- a/include/linux/firmware/xlnx-zynqmp-ufs.h
> +++ b/include/linux/firmware/xlnx-zynqmp-ufs.h
> @@ -9,17 +9,17 @@
>  #define __FIRMWARE_XLNX_ZYNQMP_UFS_H__
> =20
>  #if IS_REACHABLE(CONFIG_ZYNQMP_FIRMWARE)
> -int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready);
> -int zynqmp_pm_is_sram_init_done(bool *is_done);

[Severity: Medium]
Is it intentional to remove these prototypes from the public header, despite
the commit message mentioning that the per-read primitives stay exported?

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/eaeaaea8ed76069943e=
[email protected]?part=3D1