[PATCH net v2 4/4] net: axienet: reprogram the link settings after a DMA error reset

From: Sagi Maimon

Date: Thu Sep 24 2026 - 09:58:46 EST


axienet_dma_err_handler() resets the DMA engine, which resets the AXI
Ethernet core with it. The handler then restores RCW1, the interrupt
enable mask, the MAC address, the multicast filter and lp->options, but
not the link speed field of XAE_EMMC_OFFSET, and it writes XAE_FCC with
only XAE_FCC_FCRX_MASK, discarding whatever pause configuration had been
negotiated.

axienet_mac_link_up() is the only code that programs the link speed and
the negotiated pause bits, and phylink calls it only when the link state
changes. Nothing about the reset is visible to phylink, so it is never
called again: the MAC keeps its reset-default link speed while software
still believes the negotiated one is in effect, and on a 10 or 100 Mb/s
link frames are clocked at the wrong rate until an unrelated link flap
happens to rerun axienet_mac_link_up(). axienet_open() avoids this only
because it runs phylink_start() after axienet_device_reset().

Tell phylink the link was lost with phylink_mac_change(), so it takes
the link down and back up and calls axienet_mac_link_up() with the
current settings, under its own locking. Do it after the final
axienet_setoptions(), which also writes XAE_FCC, so the negotiated pause
settings are the ones left in place - the same order as in
axienet_open(). Skip it under the same conditions as the queue wake:
axienet_stop() stops phylink, and a resume restarts it.

The link going down and up is visible, which seems right: the MAC has
been reset. A frame may still leave at the reset-default speed in the
short window before phylink runs; the reset has just dropped everything
that was in flight anyway.

This was reported by the Sashiko AI review bot.

Tested on an AXI Ethernet MAC behind a PCIe endpoint: traffic passes,
including across ten down/up cycles made with traffic running, with this
series applied. The DMA error path itself was not exercised.

Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
Assisted-by: LLM sparse
Signed-off-by: Sagi Maimon <maimon.sagi@xxxxxxxxx>
---
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index f16dbfc7dc93..d53f7dc7bd22 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -2801,8 +2801,15 @@ static void axienet_dma_err_handler(struct work_struct *work)
* device was detached for suspend: axienet_stop() and axienet_open()
* own the queue state then.
*/
- if (!READ_ONCE(lp->stopping) && netif_device_present(ndev))
+ if (!READ_ONCE(lp->stopping) && netif_device_present(ndev)) {
+ /* The reset also cleared the link speed and pause settings,
+ * which only axienet_mac_link_up() programs. Have phylink take
+ * the link down and up again so that it is called. This must
+ * follow the axienet_setoptions() above, which writes XAE_FCC.
+ */
+ phylink_mac_change(lp->phylink, false);
netif_wake_queue(ndev);
+ }
}

/**
--
2.47.0