drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
The AXI DMA interrupt line is level-sensitive: it asserts whenever
the IOC (XAXIDMA_IRQ_IOC_MASK) or DELAY (XAXIDMA_IRQ_DELAY_MASK) bits
in the status register (XAXIDMA_TX_SR_OFFSET / XAXIDMA_RX_SR_OFFSET)
are set and their corresponding enable bits in the control register
are active.
During TX/RX, interrupts are disabled in the control register while
NAPI runs. Completions arriving in this window cause hardware to latch
IOC/DELAY into the status register regardless of the control register
mask state. After NAPI completion, re-enabling interrupts immediately
re-asserts the IRQ line due to these stale status register bits, even
when no new work is pending.
This results in a stale interrupt and redundant NAPI poll cycle with
no new work pending, causing unnecessary CPU processing.
In the initial driver, the status register was cleared after polling
all packets, which naturally consumed any status accumulated during
processing. When the driver was converted to NAPI, status register
clearing was moved to the ISR before polling begins, leaving no
mechanism to clear status bits that arrive during the NAPI poll window.
Fix the same.
Signed-off-by: Kusuma Vasana <kusuma.vasana@amd.com>
---
drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index fcf517069d16..29050c8d04e2 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1018,6 +1018,13 @@ static int axienet_tx_poll(struct napi_struct *napi, int budget)
netif_wake_queue(ndev);
}
+ /* Clear stale IOC/DELAY bits that may have latched during the
+ * poll window to prevent a stale interrupt when there is no
+ * work pending.
+ */
+ axienet_dma_out32(lp, XAXIDMA_TX_SR_OFFSET,
+ XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK);
+
if (packets < budget && napi_complete_done(napi, packets)) {
/* Re-enable TX completion interrupts. This should
* cause an immediate interrupt if any TX packets are
@@ -1293,6 +1300,13 @@ static int axienet_rx_poll(struct napi_struct *napi, int budget)
cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
}
+ /* Clear stale IOC/DELAY bits that may have latched during the
+ * poll window to prevent a stale interrupt when there is no
+ * work pending.
+ */
+ axienet_dma_out32(lp, XAXIDMA_RX_SR_OFFSET,
+ XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK);
+
u64_stats_update_begin(&lp->rx_stat_sync);
u64_stats_add(&lp->rx_packets, packets);
u64_stats_add(&lp->rx_bytes, size);
--
2.43.0
On 7/15/2026 6:20 PM, Kusuma Vasana wrote:
designate your patch to a tree - [PATCH net] or [PATCH net-next]
https://docs.kernel.org/process/maintainer-netdev.html
also keep all list in cc from get_maintainer.pl.
> The AXI DMA interrupt line is level-sensitive: it asserts whenever
> the IOC (XAXIDMA_IRQ_IOC_MASK) or DELAY (XAXIDMA_IRQ_DELAY_MASK) bits
> in the status register (XAXIDMA_TX_SR_OFFSET / XAXIDMA_RX_SR_OFFSET)
> are set and their corresponding enable bits in the control register
> are active.
>
> During TX/RX, interrupts are disabled in the control register while
> NAPI runs. Completions arriving in this window cause hardware to latch
> IOC/DELAY into the status register regardless of the control register
> mask state. After NAPI completion, re-enabling interrupts immediately
> re-asserts the IRQ line due to these stale status register bits, even
> when no new work is pending.
>
> This results in a stale interrupt and redundant NAPI poll cycle with
> no new work pending, causing unnecessary CPU processing.
>
> In the initial driver, the status register was cleared after polling
> all packets, which naturally consumed any status accumulated during
> processing. When the driver was converted to NAPI, status register
> clearing was moved to the ISR before polling begins, leaving no
> mechanism to clear status bits that arrive during the NAPI poll window.
> Fix the same.
rephrase - fix the same.
Once addressed- feel free to add:
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Thanks!
>
> Signed-off-by: Kusuma Vasana <kusuma.vasana@amd.com>
> ---
> drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> index fcf517069d16..29050c8d04e2 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> @@ -1018,6 +1018,13 @@ static int axienet_tx_poll(struct napi_struct *napi, int budget)
> netif_wake_queue(ndev);
> }
>
> + /* Clear stale IOC/DELAY bits that may have latched during the
> + * poll window to prevent a stale interrupt when there is no
> + * work pending.
> + */
> + axienet_dma_out32(lp, XAXIDMA_TX_SR_OFFSET,
> + XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK);
> +
> if (packets < budget && napi_complete_done(napi, packets)) {
> /* Re-enable TX completion interrupts. This should
> * cause an immediate interrupt if any TX packets are
> @@ -1293,6 +1300,13 @@ static int axienet_rx_poll(struct napi_struct *napi, int budget)
> cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
> }
>
> + /* Clear stale IOC/DELAY bits that may have latched during the
> + * poll window to prevent a stale interrupt when there is no
> + * work pending.
> + */
> + axienet_dma_out32(lp, XAXIDMA_RX_SR_OFFSET,
> + XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK);
> +
> u64_stats_update_begin(&lp->rx_stat_sync);
> u64_stats_add(&lp->rx_packets, packets);
> u64_stats_add(&lp->rx_bytes, size);
© 2016 - 2026 Red Hat, Inc.