Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci unify Tx softint and Rx softint to uniform ixg(4...



details:   https://anonhg.NetBSD.org/src/rev/7698bae59051
branches:  trunk
changeset: 821805:7698bae59051
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Fri Feb 17 12:16:37 2017 +0000

description:
unify Tx softint and Rx softint to uniform ixg(4) design.

Furthermore, that can remove wm_deferred_start() which holds all txq's
txq_lock, so it would reduce lock contention between Tx interrupt handler and
Tx softint handler.

diffstat:

 sys/dev/pci/if_wm.c |  115 +++++++++++++++++++++++++--------------------------
 1 files changed, 56 insertions(+), 59 deletions(-)

diffs (233 lines):

diff -r a2973c37dc1c -r 7698bae59051 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Fri Feb 17 12:10:40 2017 +0000
+++ b/sys/dev/pci/if_wm.c       Fri Feb 17 12:16:37 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.483 2017/02/17 11:57:26 knakahara Exp $    */
+/*     $NetBSD: if_wm.c,v 1.484 2017/02/17 12:16:37 knakahara Exp $    */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -84,7 +84,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.483 2017/02/17 11:57:26 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.484 2017/02/17 12:16:37 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -404,6 +404,8 @@
 
        struct wm_txqueue wmq_txq;
        struct wm_rxqueue wmq_rxq;
+
+       void *wmq_si;
 };
 
 struct wm_phyop {
@@ -709,8 +711,8 @@
 static int     wm_nq_transmit(struct ifnet *, struct mbuf *);
 static void    wm_nq_transmit_locked(struct ifnet *, struct wm_txqueue *);
 static void    wm_nq_send_common_locked(struct ifnet *, struct wm_txqueue *, bool);
-static void    wm_deferred_start(struct ifnet *);
 static void    wm_deferred_start_locked(struct wm_txqueue *);
+static void    wm_handle_queue(void *);
 /* Interrupt */
 static int     wm_txeof(struct wm_softc *, struct wm_txqueue *);
 static void    wm_rxeof(struct wm_rxqueue *);
@@ -1645,7 +1647,6 @@
        bool force_clear_smbi;
        uint32_t link_mode;
        uint32_t reg;
-       void (*deferred_start_func)(struct ifnet *) = NULL;
 
        sc->sc_dev = self;
        callout_init(&sc->sc_tick_ch, CALLOUT_FLAGS);
@@ -2539,16 +2540,12 @@
        ifp->if_ioctl = wm_ioctl;
        if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) {
                ifp->if_start = wm_nq_start;
-               if (sc->sc_nqueues > 1) {
+               if (sc->sc_nqueues > 1)
                        ifp->if_transmit = wm_nq_transmit;
-                       deferred_start_func = wm_deferred_start;
-               }
        } else {
                ifp->if_start = wm_start;
-               if (sc->sc_nqueues > 1) {
+               if (sc->sc_nqueues > 1)
                        ifp->if_transmit = wm_transmit;
-                       deferred_start_func = wm_deferred_start;
-               }
        }
        ifp->if_watchdog = wm_watchdog;
        ifp->if_init = wm_init;
@@ -2649,7 +2646,6 @@
        /* Attach the interface. */
        if_initialize(ifp);
        sc->sc_ipq = if_percpuq_create(&sc->sc_ethercom.ec_if);
-       if_deferred_start_init(ifp, deferred_start_func);
        ether_ifattach(ifp, enaddr);
        if_register(ifp);
        ether_set_ifflags_cb(&sc->sc_ethercom, wm_ifflags_cb);
@@ -4680,8 +4676,19 @@
                            "for TX and RX interrupting at %s\n", intrstr);
                }
                sc->sc_ihs[intr_idx] = vih;
-               wmq->wmq_id= qidx;
+               wmq->wmq_id = qidx;
                wmq->wmq_intr_idx = intr_idx;
+               wmq->wmq_si = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE,
+                   wm_handle_queue, wmq);
+               if (wmq->wmq_si == NULL) {
+                       aprint_error_dev(sc->sc_dev,
+                           "unable to establish queue[%d] handler\n",
+                           wmq->wmq_id);
+                       pci_intr_disestablish(sc->sc_pc,
+                           sc->sc_ihs[wmq->wmq_intr_idx]);
+                       sc->sc_ihs[wmq->wmq_intr_idx] = NULL;
+                       goto fail;
+               }
 
                txrx_established++;
                intr_idx++;
@@ -7085,11 +7092,11 @@
         * The situations which this mutex_tryenter() fails at running time
         * are below two patterns.
         *     (1) contention with interrupt handler(wm_txrxintr_msix())
-        *     (2) contention with deferred if_start softint(wm_deferred_start())
+        *     (2) contention with deferred if_start softint(wm_handle_queue())
         * In the case of (1), the last packet enqueued to txq->txq_interq is
-        * dequeued by wm_deferred_start(). So, it does not get stuck.
+        * dequeued by wm_deferred_start_locked(). So, it does not get stuck.
         * In the case of (2), the last packet enqueued to txq->txq_interq is also
-        * dequeued by wm_deferred_start(). So, it does not get stuck, either.
+        * dequeued by wm_deferred_start_locked(). So, it does not get stuck, either.
         */
        if (mutex_tryenter(txq->txq_lock)) {
                if (!txq->txq_stopping)
@@ -7395,34 +7402,6 @@
 }
 
 static void
-wm_deferred_start(struct ifnet *ifp)
-{
-       struct wm_softc *sc = ifp->if_softc;
-       int qid = 0;
-
-       /*
-        * Try to transmit on all Tx queues. Passing a txq somehow and
-        * transmitting only on the txq may be better.
-        */
-       for (; qid < sc->sc_nqueues; qid++) {
-               struct wm_txqueue *txq = &sc->sc_queue[qid].wmq_txq;
-
-               /*
-                * We must mutex_enter(txq->txq_lock) instead of
-                * mutex_tryenter(txq->txq_lock) here.
-                * mutex_tryenter(txq->txq_lock) would fail as this txq's
-                * txq_stopping flag is being set. In this case, this device
-                * begin to stop, so we must not start any Tx processing.
-                * However, it may start Tx processing for sc_queue[qid+1]
-                * if we use mutex_tryenter() here.
-                */
-               mutex_enter(txq->txq_lock);
-               wm_deferred_start_locked(txq);
-               mutex_exit(txq->txq_lock);
-       }
-}
-
-static void
 wm_deferred_start_locked(struct wm_txqueue *txq)
 {
        struct wm_softc *sc = txq->txq_sc;
@@ -8234,9 +8213,9 @@
 wm_intr_legacy(void *arg)
 {
        struct wm_softc *sc = arg;
-       struct wm_txqueue *txq = &sc->sc_queue[0].wmq_txq;
-       struct wm_rxqueue *rxq = &sc->sc_queue[0].wmq_rxq;
-       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       struct wm_queue *wmq = &sc->sc_queue[0];
+       struct wm_txqueue *txq = &wmq->wmq_txq;
+       struct wm_rxqueue *rxq = &wmq->wmq_rxq;
        uint32_t icr, rndval = 0;
        int handled = 0;
 
@@ -8314,7 +8293,7 @@
 
        if (handled) {
                /* Try to get more packets going. */
-               if_schedule_deferred_start(ifp);
+               softint_schedule(wmq->wmq_si);
        }
 
        return handled;
@@ -8353,7 +8332,6 @@
        struct wm_txqueue *txq = &wmq->wmq_txq;
        struct wm_rxqueue *rxq = &wmq->wmq_rxq;
        struct wm_softc *sc = txq->txq_sc;
-       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 
        KASSERT(wmq->wmq_intr_idx == wmq->wmq_id);
 
@@ -8371,17 +8349,7 @@
 
        WM_Q_EVCNT_INCR(txq, txdw);
        wm_txeof(sc, txq);
-
-       /* Try to get more packets going. */
-       if (pcq_peek(txq->txq_interq) != NULL)
-               if_schedule_deferred_start(ifp);
-       /*
-        * There are still some upper layer processing which call
-        * ifp->if_start(). e.g. ALTQ
-        */
-       if (wmq->wmq_id == 0)
-               if_schedule_deferred_start(ifp);
-
+       /* wm_deferred start() is done in wm_handle_queue(). */
        mutex_exit(txq->txq_lock);
 
        DPRINTF(WM_DEBUG_RX,
@@ -8397,11 +8365,40 @@
        wm_rxeof(rxq);
        mutex_exit(rxq->rxq_lock);
 
+       softint_schedule(wmq->wmq_si);
+
        wm_txrxintr_enable(wmq);
 
        return 1;
 }
 
+static void
+wm_handle_queue(void *arg)
+{
+       struct wm_queue *wmq = arg;
+       struct wm_txqueue *txq = &wmq->wmq_txq;
+       struct wm_rxqueue *rxq = &wmq->wmq_rxq;
+       struct wm_softc *sc = txq->txq_sc;
+
+       mutex_enter(txq->txq_lock);
+       if (txq->txq_stopping) {
+               mutex_exit(txq->txq_lock);
+               return;
+       }
+       wm_txeof(sc, txq);
+       wm_deferred_start_locked(txq);
+       mutex_exit(txq->txq_lock);
+
+       mutex_enter(rxq->rxq_lock);
+       if (rxq->rxq_stopping) {
+               mutex_exit(rxq->rxq_lock);
+               return;
+       }
+       WM_Q_EVCNT_INCR(rxq, rxintr);
+       wm_rxeof(rxq);
+       mutex_exit(rxq->rxq_lock);
+}
+
 /*
  * wm_linkintr_msix:
  *



Home | Main Index | Thread Index | Old Index