The branch main has been updated by adrian:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=d11f124e932bfa4fabdc6c5b67735181615a0630

commit d11f124e932bfa4fabdc6c5b67735181615a0630
Author:     Jérémie Jourdin <[email protected]>
AuthorDate: 2026-07-19 18:45:47 +0000
Commit:     Adrian Chadd <[email protected]>
CommitDate: 2026-07-19 18:45:49 +0000

    re(4): recover Tx completions whose MSI was swallowed in re_intr_msi()
    
    A Tx completion that raises a status bit between the ISR ack at the top
    of re_intr_msi() and the IMR re-enable at the bottom is never re-signalled:
    these controllers do not re-assert MSI for an already-set status bit
    (this is why hw.re.msi_disable is a known workaround in the PR).
    
    Re-read ISR before re-enabling; if a Tx bit is pending, ack just that bit,
    reap the ring and restart the queue. Rx bits are deliberately left set so
    they re-arm the interrupt normally and Rx moderation state is untouched.
    
    Also flush the posted IMR write. Mirrors what the INTx path already
    achieves via the loop in re_intr().
    
    * MSI interrupt mode on RTL8168H under load; "missed Tx interrupts"
      watchdog recoveries no longer occur.
    
    Reviewed by:    adrian
    Differential Revision:  https://reviews.freebsd.org/D58278
    PR: kern/166724
---
 sys/dev/re/if_re.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 4df75474bce3..b04dc3cbaf4a 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -2731,7 +2731,34 @@ re_intr_msi(void *xsc)
        if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) {
                if (!if_sendq_empty(ifp))
                        re_start_locked(ifp);
+               /*
+                * A Tx completion can set a Tx status bit between the ISR ack
+                * near the top of this routine and re-enabling interrupts
+                * below.  These controllers do not re-assert the MSI for a
+                * status bit that is already set, so the completion would not
+                * be serviced until the next interrupt or the 1 Hz re_tick()
+                * reclaim (this is why hw.re.msi_disable is a known
+                * workaround).  If a Tx bit is pending, clear just that bit and
+                * reap the ring now; leave any Rx bits set so they re-arm the
+                * interrupt normally and the Rx moderation state is untouched.
+                */
+               status = CSR_READ_2(sc, RL_ISR);
+               if ((status & (RL_ISR_TX_OK | RL_ISR_TX_ERR |
+                   RL_ISR_TX_DESC_UNAVAIL)) != 0) {
+                       CSR_WRITE_2(sc, RL_ISR, status & (RL_ISR_TX_OK |
+                           RL_ISR_TX_ERR | RL_ISR_TX_DESC_UNAVAIL));
+                       if ((status & (RL_ISR_TX_OK |
+                           RL_ISR_TX_DESC_UNAVAIL)) != 0 &&
+                           (sc->rl_flags & RL_FLAG_PCIE) != 0)
+                               CSR_WRITE_1(sc, sc->rl_txstart,
+                                   RL_TXSTART_START);
+                       re_txeof(sc);
+                       if (!if_sendq_empty(ifp))
+                               re_start_locked(ifp);
+               }
                CSR_WRITE_2(sc, RL_IMR, intrs);
+               /* Flush the posted IMR write. */
+               (void)CSR_READ_2(sc, RL_ISR);
        }
        RL_UNLOCK(sc);
 }

Reply via email to