Author: yongari
Date: Sat Feb 19 01:37:28 2011
New Revision: 218831
URL: http://svn.freebsd.org/changeset/base/218831

Log:
  Rearrange interrupt handler a bit and remove forever loop.
  Previously dc(4) always checked whether there is pending interrupts
  and this consumed a lot of CPU cycles in interrupt handler. Limit
  the number of processing for TX/RX frames to 16. Also allow sending
  frames in the loop not to starve TX under high RX load.
  Reading DC_ISR register should be protected with driver lock,
  otherwise interrupt handler could be run(e.g. link state change)
  before the completion of dc_init_locked().
  
  While I'm here remove unneeded code.

Modified:
  head/sys/dev/dc/if_dc.c

Modified: head/sys/dev/dc/if_dc.c
==============================================================================
--- head/sys/dev/dc/if_dc.c     Sat Feb 19 00:00:32 2011        (r218830)
+++ head/sys/dev/dc/if_dc.c     Sat Feb 19 01:37:28 2011        (r218831)
@@ -3135,16 +3135,19 @@ dc_intr(void *arg)
        struct dc_softc *sc;
        struct ifnet *ifp;
        u_int32_t status;
+       int curpkts, n;
 
        sc = arg;
 
        if (sc->suspended)
                return;
 
-       if ((CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0)
-               return;
-
        DC_LOCK(sc);
+       status = CSR_READ_4(sc, DC_ISR);
+       if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0) {
+               DC_UNLOCK(sc);
+               return;
+       }
        ifp = sc->dc_ifp;
 #ifdef DEVICE_POLLING
        if (ifp->if_capenable & IFCAP_POLLING) {
@@ -3152,26 +3155,16 @@ dc_intr(void *arg)
                return;
        }
 #endif
-
-       /* Suppress unwanted interrupts */
-       if (!(ifp->if_flags & IFF_UP)) {
-               if (CSR_READ_4(sc, DC_ISR) & DC_INTRS)
-                       dc_stop(sc);
-               DC_UNLOCK(sc);
-               return;
-       }
-
        /* Disable interrupts. */
        CSR_WRITE_4(sc, DC_IMR, 0x00000000);
 
-       while (((status = CSR_READ_4(sc, DC_ISR)) & DC_INTRS) &&
-           status != 0xFFFFFFFF &&
-           (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-
+       for (n = 16; n > 0; n--) {
+               if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+                       break;
+               /* Ack interrupts. */
                CSR_WRITE_4(sc, DC_ISR, status);
 
                if (status & DC_ISR_RX_OK) {
-                       int             curpkts;
                        curpkts = ifp->if_ipackets;
                        dc_rxeof(sc);
                        if (curpkts == ifp->if_ipackets) {
@@ -3196,7 +3189,6 @@ dc_intr(void *arg)
 
                if ((status & DC_ISR_RX_WATDOGTIMEO)
                    || (status & DC_ISR_RX_NOBUF)) {
-                       int             curpkts;
                        curpkts = ifp->if_ipackets;
                        dc_rxeof(sc);
                        if (curpkts == ifp->if_ipackets) {
@@ -3205,17 +3197,23 @@ dc_intr(void *arg)
                        }
                }
 
+               if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+                       dc_start_locked(ifp);
+
                if (status & DC_ISR_BUS_ERR) {
                        dc_reset(sc);
                        dc_init_locked(sc);
+                       DC_UNLOCK(sc);
+                       return;
                }
+               status = CSR_READ_4(sc, DC_ISR);
+               if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0)
+                       break;
        }
 
        /* Re-enable interrupts. */
-       CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
-
-       if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-               dc_start_locked(ifp);
+       if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+               CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
 
        DC_UNLOCK(sc);
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to