summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPadmarao Begari <[email protected]>2026-03-02 08:43:33 +0100
committerMichal Simek <[email protected]>2026-03-23 14:58:46 +0100
commit0d96ce69d40b45e50f0ec38d02f20d6493c969e6 (patch)
tree9f0d6ce4a2361b4e97197ed4946dc7a8dd9f2731
parent3371da09c5709984533e307c8fde4e935945f435 (diff)
net: zynq_gem: clear TXSR transfer complete
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 <[email protected]> Signed-off-by: Harini Katakam <[email protected]> Co-developed-by: Michal Simek <[email protected]> Signed-off-by: Padmarao Begari <[email protected]> Signed-off-by: Michal Simek <[email protected]> Link: https://lore.kernel.org/r/f354680d43fba0f590a6fae693848e5bf7114ba5.1772437409.git.michal.simek@amd.com
-rw-r--r--drivers/net/zynq_gem.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c
index b05c752b17e..41883a44052 100644
--- a/drivers/net/zynq_gem.c
+++ b/drivers/net/zynq_gem.c
@@ -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 */