Well, I've been watching everyone argue about the value of interrupt
coalescing in the net drivers, so I decided to port terry's patch to 4.4 &
-current to see what the results are.  The patch included applies cleanly
to 4.4's if_dc, and will apply to -current with a one line change.
Whitespace is horrible, I copied and pasted the original patch, used patch
-l, etc.

The test setup I used was as follows:
Duron 600, PNIC, running -current
Celeron 450, ADMtek tulip-clone, running -stable

The network is 100mbps, switched.  To simulate load, I used a syn flooder
aimed at an unused port.  icmp/rst response limiting was enabled.

With the -current box attacking the -stable box, I was able to notice a
slight drop in interrupts/second with the patch applied.  The number of
packets was ~57000/second.

Before: ~46000 ints/sec, 57-63% processor usage due to interrupts.
After: ~38000 ints/sec, 50-60% processor usage due to interrupts.

In both cases, the box felt responsive.

With the -stable box attacking the -current box, the patch made no
difference.  The box bogged down at only ~25000 ints/sec, and response
limiting reported the number of packets to be ~44000/second.

I'm not sure if the number was lower because the celeron couldn't run the
flooder as quickly, or if the -current box was dropping packets.  I
suspect the latter, as the -current box was NOTICEABLY slowed down; I
could watch systat refresh the screen.

The conclusion?  I think that the dc driver does a good enough job of
grabbing multiple packets at once, and won't be helped by Terry's patch
except in a few very cases.  In fact, I have a sneaky suspicion that
Terry's patch may increase bus traffic slightly.  I'm not sure how much of
an issue this is, perhaps Bill or Luigi could comment.

In short, if we're going to try to tackle high interrupt load, it should
be done by disabling interrupts and going to polling under high load;
the patch proposed here isn't worth the extra complexity.

I suppose this would all change if we were using LRP and doing lots of
processing in the interrupt handler... but we aren't.

Mike "Silby" Silbersack
--- if_dc.c.orig        Thu Oct 11 01:39:05 2001
+++ if_dc.c     Thu Oct 11 01:39:30 2001
@@ -193,8 +193,8 @@
 static int dc_coal             __P((struct dc_softc *, struct mbuf **));
 static void dc_pnic_rx_bug_war __P((struct dc_softc *, int));
 static int dc_rx_resync                __P((struct dc_softc *));
-static void dc_rxeof           __P((struct dc_softc *));
-static void dc_txeof           __P((struct dc_softc *));
+static int dc_rxeof           __P((struct dc_softc *));
+static int dc_txeof           __P((struct dc_softc *));
 static void dc_tick            __P((void *));
 static void dc_tx_underrun     __P((struct dc_softc *));
 static void dc_intr            __P((void *));
@@ -2302,7 +2302,7 @@
  * A frame has been uploaded: pass the resulting mbuf chain up to
  * the higher level protocols.
  */
-static void dc_rxeof(sc)
+static int dc_rxeof(sc)
        struct dc_softc         *sc;
 {
         struct ether_header    *eh;
@@ -2311,6 +2311,7 @@
        struct dc_desc          *cur_rx;
        int                     i, total_len = 0;
        u_int32_t               rxstat;
+      int                     cnt = 0;
 
        ifp = &sc->arpcom.ac_if;
        i = sc->dc_cdata.dc_rx_prod;
@@ -2355,7 +2356,7 @@
                                continue;
                        } else {
                                dc_init(sc);
-                               return;
+                              return(cnt);
                        }
                }
 
@@ -2379,6 +2380,7 @@
                /* Remove header from mbuf and pass it on. */
                m_adj(m, sizeof(struct ether_header));
                ether_input(ifp, eh, m);
+              cnt++;
        }
 
        sc->dc_cdata.dc_rx_prod = i;
@@ -2389,12 +2391,13 @@
  * the list buffers.
  */
 
-static void dc_txeof(sc)
+static int dc_txeof(sc)
        struct dc_softc         *sc;
 {
        struct dc_desc          *cur_tx = NULL;
        struct ifnet            *ifp;
        int                     idx;
+      int                     cnt = 0;
 
        ifp = &sc->arpcom.ac_if;
 
@@ -2452,7 +2455,7 @@
                                ifp->if_collisions++;
                        if (!(txstat & DC_TXSTAT_UNDERRUN)) {
                                dc_init(sc);
-                               return;
+                              return(cnt);
                        }
                }
 
@@ -2466,13 +2469,14 @@
 
                sc->dc_cdata.dc_tx_cnt--;
                DC_INC(idx, DC_TX_LIST_CNT);
+              cnt++;
        }
 
        sc->dc_cdata.dc_tx_cons = idx;
        if (cur_tx != NULL)
                ifp->if_flags &= ~IFF_OACTIVE;
 
-       return;
+      return(cnt);
 }
 
 static void dc_tick(xsc)
@@ -2612,6 +2616,7 @@
        struct dc_softc         *sc;
        struct ifnet            *ifp;
        u_int32_t               status;
+      int                     cnt = 0;
 
        sc = arg;
 
@@ -2630,6 +2635,7 @@
        /* Disable interrupts. */
        CSR_WRITE_4(sc, DC_IMR, 0x00000000);
 
+again:
        while((status = CSR_READ_4(sc, DC_ISR)) & DC_INTRS) {
 
                CSR_WRITE_4(sc, DC_ISR, status);
@@ -2637,18 +2643,18 @@
                if (status & DC_ISR_RX_OK) {
                        int             curpkts;
                        curpkts = ifp->if_ipackets;
-                       dc_rxeof(sc);
+                      cnt += dc_rxeof(sc);
                        if (curpkts == ifp->if_ipackets) {
                                while(dc_rx_resync(sc))
-                                       dc_rxeof(sc);
+                                      cnt += dc_rxeof(sc);
                        }
                }
 
                if (status & (DC_ISR_TX_OK|DC_ISR_TX_NOBUF))
-                       dc_txeof(sc);
+                      cnt += dc_txeof(sc);
 
                if (status & DC_ISR_TX_IDLE) {
-                       dc_txeof(sc);
+                      cnt += dc_txeof(sc);
                        if (sc->dc_cdata.dc_tx_cnt) {
                                DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
                                CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
@@ -2662,10 +2668,10 @@
                    || (status & DC_ISR_RX_NOBUF)) {
                        int             curpkts;
                        curpkts = ifp->if_ipackets;
-                       dc_rxeof(sc);
+                      cnt += dc_rxeof(sc);
                        if (curpkts == ifp->if_ipackets) {
                                while(dc_rx_resync(sc))
-                                       dc_rxeof(sc);
+                                      cnt += dc_rxeof(sc);
                        }
                }
 
@@ -2673,6 +2679,10 @@
                        dc_reset(sc);
                        dc_init(sc);
                }
+      }
+      if (cnt) {      /* XXX limit repeats? */
+              cnt = 0;
+              goto again;
        }
 
        /* Re-enable interrupts. */

Reply via email to