OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
[PATCH] if_nfe interrupt handler

From: Oleg Safiullin (formpdp-11.org.ru)
Date: Tue Mar 27 2007 - 05:47:03 CDT


Hi!
Please look at the following patch...

Some if_nfe interrupt handler fixes:
- mask all interrupts while servicing an inrterrupt
- process interrupts until all the NFE_IRQ_WANTED bits are handled
- return 1 only if any nfe interrupts actually handled

Tested on ASUS M2N-SLI Deluxe motherboard.
Patch file also available at http://pdp-11.org.ru/~form/files/nfe-intr.patch

Thanks!

Index: dev/pci/if_nfe.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_nfe.c,v
retrieving revision 1.69
diff -d -u -r1.69 if_nfe.c
--- dev/pci/if_nfe.c 2007/03/02 00:16:59 1.69
+++ dev/pci/if_nfe.c 2007/03/27 10:30:45
-453,29 +453,39
 {
         struct nfe_softc *sc = arg;
         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ int handled = 0;
         uint32_t r;
 
- if ((r = NFE_READ(sc, NFE_IRQ_STATUS)) == 0)
- return 0; /* not for us */
- NFE_WRITE(sc, NFE_IRQ_STATUS, r);
+ if (!(ifp->if_flags & IFF_UP))
+ return (0);
 
- DPRINTFN(5, ("nfe_intr: interrupt register %x\n", r));
+ NFE_WRITE(sc, NFE_IRQ_MASK, 0);
 
- if (r & NFE_IRQ_LINK) {
- NFE_READ(sc, NFE_PHY_STATUS);
- NFE_WRITE(sc, NFE_PHY_STATUS, 0xf);
- DPRINTF(("%s: link state changed\n", sc->sc_dev.dv_xname));
- }
+ for (;;) {
+ if (!((r = NFE_READ(sc, NFE_IRQ_STATUS)) & NFE_IRQ_WANTED))
+ break;
 
- if (ifp->if_flags & IFF_RUNNING) {
- /* check Rx ring */
- nfe_rxeof(sc);
+ NFE_WRITE(sc, NFE_IRQ_STATUS, r);
+ DPRINTFN(5, ("nfe_intr: interrupt register %x\n", r));
+ handled = 1;
 
- /* check Tx ring */
- nfe_txeof(sc);
+ if (r & (NFE_IRQ_RXERR | NFE_IRQ_RX_NOBUF | NFE_IRQ_RX))
+ nfe_rxeof(sc); /* check Rx ring */
+
+ if (r & (NFE_IRQ_TXERR | NFE_IRQ_TXERR2 | NFE_IRQ_TX_DONE))
+ nfe_txeof(sc); /* check Tx ring */
+
+ if (r & NFE_IRQ_LINK) {
+ NFE_READ(sc, NFE_PHY_STATUS);
+ NFE_WRITE(sc, NFE_PHY_STATUS, 0xf);
+ DPRINTF(("%s: link state changed\n",
+ sc->sc_dev.dv_xname));
+ }
         }
 
- return 1;
+ NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED);
+
+ return (handled);
 }
 
 int