Author: yongari
Date: Mon Mar  1 23:39:43 2010
New Revision: 204541
URL: http://svn.freebsd.org/changeset/base/204541

Log:
  Implement rudimentary interrupt moderation with programmable
  countdown timer register. The timer resolution may vary among
  controllers but the value would be represented by core clock
  cycles. msk(4) will automatically computes number of required clock
  cycles from given micro-seconds unit.
  The default interrupt holdoff timer value is 100us which will
  ensure less than 10k interrupts under load. The timer value can be
  changed with dev.mskc.0.int_holdoff sysctl node.
  
  Note, the interrupt moderation is shared resource on dual-port
  controllers so you can't use separate interrupt moderation value
  for each port. This means we can't stop interrupt moderation in
  driver stop routine. Also have msk_tick() reclaim transmitted Tx
  buffers as safety belt. With this change there is no need to check
  missing Tx completion interrupt in watchdog handler, so remove it.

Modified:
  head/sys/dev/msk/if_msk.c
  head/sys/dev/msk/if_mskreg.h

Modified: head/sys/dev/msk/if_msk.c
==============================================================================
--- head/sys/dev/msk/if_msk.c   Mon Mar  1 22:55:35 2010        (r204540)
+++ head/sys/dev/msk/if_msk.c   Mon Mar  1 23:39:43 2010        (r204541)
@@ -1659,6 +1659,14 @@ mskc_attach(device_t dev)
                }
        }
 
+       sc->msk_int_holdoff = MSK_INT_HOLDOFF_DEFAULT;
+       SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+           "int_holdoff", CTLFLAG_RW, &sc->msk_int_holdoff, 0,
+           "Maximum number of time to delay interrupts");
+       resource_int_value(device_get_name(dev), device_get_unit(dev),
+           "int_holdoff", &sc->msk_int_holdoff);
+
        /* Soft reset. */
        CSR_WRITE_2(sc, B0_CTST, CS_RST_SET);
        CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR);
@@ -2801,8 +2809,6 @@ static void
 msk_watchdog(struct msk_if_softc *sc_if)
 {
        struct ifnet *ifp;
-       uint32_t ridx;
-       int idx;
 
        MSK_IF_LOCK_ASSERT(sc_if);
 
@@ -2819,24 +2825,6 @@ msk_watchdog(struct msk_if_softc *sc_if)
                return;
        }
 
-       /*
-        * Reclaim first as there is a possibility of losing Tx completion
-        * interrupts.
-        */
-       ridx = sc_if->msk_port == MSK_PORT_A ? STAT_TXA1_RIDX : STAT_TXA2_RIDX;
-       idx = CSR_READ_2(sc_if->msk_softc, ridx);
-       if (sc_if->msk_cdata.msk_tx_cons != idx) {
-               msk_txeof(sc_if, idx);
-               if (sc_if->msk_cdata.msk_tx_cnt == 0) {
-                       if_printf(ifp, "watchdog timeout (missed Tx interrupts) 
"
-                           "-- recovering\n");
-                       if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
-                               taskqueue_enqueue(taskqueue_fast,
-                                   &sc_if->msk_tx_task);
-                       return;
-               }
-       }
-
        if_printf(ifp, "watchdog timeout\n");
        ifp->if_oerrors++;
        ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
@@ -3166,6 +3154,7 @@ msk_tick(void *xsc_if)
        mii_tick(mii);
        if ((sc_if->msk_flags & MSK_FLAG_LINK) == 0)
                msk_miibus_statchg(sc_if->msk_if_dev);
+       msk_handle_events(sc_if->msk_softc);
        msk_watchdog(sc_if);
        callout_reset(&sc_if->msk_tick_ch, hz, msk_tick, sc_if);
 }
@@ -3904,6 +3893,17 @@ msk_init_locked(struct msk_if_softc *sc_
                sc->msk_intrmask |= Y2_IS_PORT_B;
                sc->msk_intrhwemask |= Y2_HWE_L2_MASK;
        }
+       /* Configure IRQ moderation mask. */
+       CSR_WRITE_4(sc, B2_IRQM_MSK, sc->msk_intrmask);
+       if (sc->msk_int_holdoff > 0) {
+               /* Configure initial IRQ moderation timer value. */
+               CSR_WRITE_4(sc, B2_IRQM_INI,
+                   MSK_USECS(sc, sc->msk_int_holdoff));
+               CSR_WRITE_4(sc, B2_IRQM_VAL,
+                   MSK_USECS(sc, sc->msk_int_holdoff));
+               /* Start IRQ moderation. */
+               CSR_WRITE_1(sc, B2_IRQM_CTRL, TIM_START);
+       }
        CSR_WRITE_4(sc, B0_HWE_IMSK, sc->msk_intrhwemask);
        CSR_READ_4(sc, B0_HWE_IMSK);
        CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask);

Modified: head/sys/dev/msk/if_mskreg.h
==============================================================================
--- head/sys/dev/msk/if_mskreg.h        Mon Mar  1 22:55:35 2010        
(r204540)
+++ head/sys/dev/msk/if_mskreg.h        Mon Mar  1 23:39:43 2010        
(r204541)
@@ -2406,6 +2406,8 @@ struct msk_ring_data {
 #define        MSK_PROC_MIN            30
 #define        MSK_PROC_MAX            (MSK_RX_RING_CNT - 1)
 
+#define        MSK_INT_HOLDOFF_DEFAULT 100
+
 #define        MSK_TX_TIMEOUT          5
 #define        MSK_PUT_WM      10
 
@@ -2496,6 +2498,7 @@ struct msk_softc {
        bus_dmamap_t            msk_stat_map;
        struct msk_stat_desc    *msk_stat_ring;
        bus_addr_t              msk_stat_ring_paddr;
+       int                     msk_int_holdoff;
        int                     msk_process_limit;
        int                     msk_stat_cons;
        struct taskqueue        *msk_tq;
_______________________________________________
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