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/68d1aedccd27
branches: trunk
changeset: 351554:68d1aedccd27
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 7d03f6a50e9c -r 68d1aedccd27 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