]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
net: zynq_gem: clear TXSR transfer complete
authorPadmarao Begari <padmarao.begari@amd.com>
Mon, 2 Mar 2026 07:43:33 +0000 (08:43 +0100)
committerMichal Simek <michal.simek@amd.com>
Mon, 23 Mar 2026 13:58:46 +0000 (14:58 +0100)
The Zynq GEM TX status register retains the transfer‑complete bit
until it is explicitly cleared. The current flow waits for
transfer‑complete but never clears it, so on the next send the wait
loop returns immediately because transfer‑complete is already high.
This causes the driver to report TX completion before the new DMA
transfer has actually finished, which breaks back‑to‑back
transmissions. This issue causes timeouts during LWIP TFTP transfers
when cache coherency is enabled.
Fix this by explicitly clearing transfer‑complete (write‑to‑clear)
after the wait completes, so each transmit starts with a clean TXSR.

Co-developed-by: Harini Katakam <harini.katakam@amd.com>
Signed-off-by: Harini Katakam <harini.katakam@amd.com>
Co-developed-by: Michal Simek <michal.simek@amd.com>
Signed-off-by: Padmarao Begari <padmarao.begari@amd.com>
Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/f354680d43fba0f590a6fae693848e5bf7114ba5.1772437409.git.michal.simek@amd.com
drivers/net/zynq_gem.c

index b05c752b17eb8416adb4fbb8232e479597b8a1c8..41883a44052853a96a78af837a772ce12b551ca2 100644 (file)
@@ -693,6 +693,7 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
 {
        dma_addr_t addr;
        u32 size;
+       int ret;
        struct zynq_gem_priv *priv = dev_get_priv(dev);
        struct zynq_gem_regs *regs = priv->iobase;
        struct emac_bd *current_bd = &priv->tx_bd[1];
@@ -734,8 +735,13 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len)
        if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED)
                printf("TX buffers exhausted in mid frame\n");
 
-       return wait_for_bit_le32(&regs->txsr, ZYNQ_GEM_TSR_DONE,
-                                true, 20000, true);
+       ret = wait_for_bit_le32(&regs->txsr, ZYNQ_GEM_TSR_DONE,
+                               true, 20000, true);
+
+       /* Clear the transfer complete */
+       setbits_le32(&regs->txsr, ZYNQ_GEM_TSR_DONE);
+
+       return ret;
 }
 
 /* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */