[BUG] Re: [PATCH 1/1] PCI: dwc: Apply ECRC workaround for DesignWare cores prior to 5.10A
From: Radu Rendec
Date: Tue Sep 01 2026 - 21:41:25 EST
On Fri, 2026-04-10 at 11:55 +0530, Manikanta Maddireddy wrote:
> The ECRC (TLP digest) workaround was originally applied only for DesignWare
> core version 4.90a. Per discussion in Synopsys case, the dependency of the
> iATU TD bit on ECRC generation was removed in 5.10a, so apply the
> workaround for all DWC versions below that release.
>
> Replace the misleading comment that referred to raw version constants
> with readable DesignWare release name aligned with the implementation.
>
> Fixes: b210b1595606 PCI: dwc: Apply ECRC workaround to DesignWare 5.00a as well
> Signed-off-by: Manikanta Maddireddy <mmaddireddy@xxxxxxxxxx>
This patch breaks dw_pcie emulation in Qemu. I'm using the imx8mp-evk
machine and a single virtio-net-pci device attached to dw_pcie.
What I see is this: pci->version is 0x0, so with the patch applied,
dw_pcie_enable_ecrc() gets called now, whereas previously it didn't
(because the condition checked specifically for 490A and 500A).
This has a ripple effect that ultimately makes the system fail to boot:
* vp_reset() for the virtio-net-pci device spins forever in the loop
around vp_modern_get_status(mdev), which always returns 0xff.
* vp_reset() is called in the context of the probe() function for the
virtio-net-pci device, so probe() never returns.
* the init task gets stuck in wait_for_device_probe() before it
executes the real init binary (stack trace below).
#0 wait_for_device_probe
#1 prepare_namespace
#2 kernel_init_freeable
#3 kernel_init
#4 ret_from_fork
This is a separate problem of virtio (vp_reset() should eventually give
up), and I will send a RFC patch shortly.
Now back to the point, the obvious dumb fix is to check if pci->version
is 0x0 but I believe there is little appetite for that because it would
be just a workaround for the (incomplete) Qemu emulation of dw_pcie. I
assume it would be preferable to fix it in Qemu instead, to present a
valid version value that also happens to be >= 510A to avoid setting
the PCIE_ATU_TD bit.
But looking at the code, I'm not sure if it's as easy as it sounds. I
noticed there are quite a few other things that happen differently in
the driver if the version is >= 460A, so setting a correct version in
Qemu would also flip those conditions. I don't know if that can break
something else.
If, however, the "dumb fix" doesn't sound that horrible, I'm happy to
send a patch. Or, if you have any other suggestions, please let me
know. Thanks!
> ---
> drivers/pci/controller/dwc/pcie-designware.c | 6 +++---
> drivers/pci/controller/dwc/pcie-designware.h | 1 +
> 2 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
> index d69db0ab3b14..d0b3b93fc940 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.c
> +++ b/drivers/pci/controller/dwc/pcie-designware.c
> @@ -487,8 +487,8 @@ static inline void dw_pcie_writel_atu_ob(struct dw_pcie *pci, u32 index, u32 reg
> static inline u32 dw_pcie_enable_ecrc(u32 val)
> {
> /*
> - * DWC versions 0x3530302a and 0x3536322a has a design issue where the 'TD'
> - * bit in the Control register-1 of the ATU outbound region acts
> + * DesignWare core versions prior to 5.10A have a design issue where the
> + * 'TD' bit in the Control register-1 of the ATU outbound region acts
> * like an override for the ECRC setting, i.e., the presence of TLP
> * Digest (ECRC) in the outgoing TLPs is solely determined by this
> * bit. This is contrary to the PCIe spec which says that the
> @@ -563,7 +563,7 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
> if (upper_32_bits(limit_addr) > upper_32_bits(parent_bus_addr) &&
> dw_pcie_ver_is_ge(pci, 460A))
> val |= PCIE_ATU_INCREASE_REGION_SIZE;
> - if (dw_pcie_ver_is(pci, 490A) || dw_pcie_ver_is(pci, 500A))
> + if (!dw_pcie_ver_is_ge(pci, 510A))
> val = dw_pcie_enable_ecrc(val);
> dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL1, val);
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
> index 82946bf78b21..739a213c27c9 100644
> --- a/drivers/pci/controller/dwc/pcie-designware.h
> +++ b/drivers/pci/controller/dwc/pcie-designware.h
> @@ -35,6 +35,7 @@
> #define DW_PCIE_VER_480A 0x3438302a
> #define DW_PCIE_VER_490A 0x3439302a
> #define DW_PCIE_VER_500A 0x3530302a
> +#define DW_PCIE_VER_510A 0x3531302a
> #define DW_PCIE_VER_520A 0x3532302a
> #define DW_PCIE_VER_540A 0x3534302a
> #define DW_PCIE_VER_562A 0x3536322a
--
Best regards,
Radu