Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci wm(4) can use workqueue as deferred Rx/Tx handle...
details: https://anonhg.NetBSD.org/src/rev/d11bf2e488fe
branches: trunk
changeset: 1006699:d11bf2e488fe
user: knakahara <knakahara%NetBSD.org@localhost>
date: Fri Jan 24 02:50:41 2020 +0000
description:
wm(4) can use workqueue as deferred Rx/Tx handler like ixg(4).
Set hw.wm*.txrx_workqueue=1 to use workqueue instead of softint.
The default value of hw.wm*.txrx_workqueue is 0, that is, use softint
as before.
ok by msaitoh@n.o.
diffstat:
sys/dev/pci/if_wm.c | 138 ++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 118 insertions(+), 20 deletions(-)
diffs (290 lines):
diff -r dc1030099411 -r d11bf2e488fe sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Thu Jan 23 23:59:53 2020 +0000
+++ b/sys/dev/pci/if_wm.c Fri Jan 24 02:50:41 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.661 2020/01/23 07:49:57 knakahara Exp $ */
+/* $NetBSD: if_wm.c,v 1.662 2020/01/24 02:50:41 knakahara Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -82,7 +82,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.661 2020/01/23 07:49:57 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.662 2020/01/24 02:50:41 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -105,6 +105,8 @@
#include <sys/interrupt.h>
#include <sys/cpu.h>
#include <sys/pcq.h>
+#include <sys/sysctl.h>
+#include <sys/workqueue.h>
#include <sys/rndsource.h>
@@ -164,10 +166,14 @@
#ifdef NET_MPSAFE
#define WM_MPSAFE 1
#define CALLOUT_FLAGS CALLOUT_MPSAFE
+#define WM_WORKQUEUE_FLAGS WQ_PERCPU | WQ_MPSAFE
#else
#define CALLOUT_FLAGS 0
+#define WM_WORKQUEUE_FLAGS WQ_PERCPU
#endif
+#define WM_WORKQUEUE_PRI PRI_SOFTNET
+
/*
* This device driver's max interrupt numbers.
*/
@@ -456,6 +462,8 @@
struct wm_txqueue wmq_txq;
struct wm_rxqueue wmq_rxq;
+ bool wmq_txrx_use_workqueue;
+ struct work wmq_cookie;
void *wmq_si;
krndsource_t rnd_source; /* random source */
};
@@ -552,6 +560,8 @@
u_int sc_tx_intr_process_limit; /* Tx proc. repeat limit in H/W intr */
u_int sc_rx_process_limit; /* Rx proc. repeat limit in softint */
u_int sc_rx_intr_process_limit; /* Rx proc. repeat limit in H/W intr */
+ struct workqueue *sc_queue_wq;
+ bool sc_txrx_use_workqueue;
int sc_affinity_offset;
@@ -567,6 +577,8 @@
struct evcnt sc_ev_rx_macctl; /* Rx Unsupported */
#endif /* WM_EVENT_COUNTERS */
+ struct sysctllog *sc_sysctllog;
+
/* This variable are used only on the 82547. */
callout_t sc_txfifo_ch; /* Tx FIFO stall work-around timer */
@@ -738,11 +750,12 @@
static void wm_adjust_qnum(struct wm_softc *, int);
static inline bool wm_is_using_msix(struct wm_softc *);
static inline bool wm_is_using_multiqueue(struct wm_softc *);
-static int wm_softint_establish(struct wm_softc *, int, int);
+static int wm_softhandler_establish(struct wm_softc *, int, int);
static int wm_setup_legacy(struct wm_softc *);
static int wm_setup_msix(struct wm_softc *);
static int wm_init(struct ifnet *);
static int wm_init_locked(struct ifnet *);
+static void wm_init_sysctls(struct wm_softc *);
static void wm_unset_stopping_flags(struct wm_softc *);
static void wm_set_stopping_flags(struct wm_softc *);
static void wm_stop(struct ifnet *, int);
@@ -794,6 +807,7 @@
bool);
static void wm_deferred_start_locked(struct wm_txqueue *);
static void wm_handle_queue(void *);
+static void wm_handle_queue_work(struct work *, void *);
/* Interrupt */
static bool wm_txeof(struct wm_txqueue *, u_int);
static bool wm_rxeof(struct wm_rxqueue *, u_int);
@@ -3026,6 +3040,10 @@
NULL, xname, "rx_macctl");
#endif /* WM_EVENT_COUNTERS */
+ sc->sc_txrx_use_workqueue = false;
+
+ wm_init_sysctls(sc);
+
if (pmf_device_register(self, wm_suspend, wm_resume))
pmf_class_network_register(self, ifp);
else
@@ -3052,6 +3070,8 @@
pmf_device_deregister(self);
+ sysctl_teardown(&sc->sc_sysctllog);
+
#ifdef WM_EVENT_COUNTERS
evcnt_detach(&sc->sc_ev_linkintr);
@@ -5393,9 +5413,12 @@
}
static int
-wm_softint_establish(struct wm_softc *sc, int qidx, int intr_idx)
-{
+wm_softhandler_establish(struct wm_softc *sc, int qidx, int intr_idx)
+{
+ char wqname[MAXCOMLEN];
struct wm_queue *wmq = &sc->sc_queue[qidx];
+ int error;
+
wmq->wmq_id = qidx;
wmq->wmq_intr_idx = intr_idx;
wmq->wmq_si = softint_establish(SOFTINT_NET
@@ -5403,12 +5426,28 @@
| SOFTINT_MPSAFE
#endif
, wm_handle_queue, wmq);
- if (wmq->wmq_si != NULL)
- return 0;
-
- aprint_error_dev(sc->sc_dev, "unable to establish queue[%d] handler\n",
- wmq->wmq_id);
-
+ if (wmq->wmq_si == NULL) {
+ aprint_error_dev(sc->sc_dev,
+ "unable to establish queue[%d] softint handler\n",
+ wmq->wmq_id);
+ goto err;
+ }
+
+ snprintf(wqname, sizeof(wqname), "%sTxRx", device_xname(sc->sc_dev));
+ error = workqueue_create(&sc->sc_queue_wq, wqname,
+ wm_handle_queue_work, sc, WM_WORKQUEUE_PRI, IPL_NET,
+ WM_WORKQUEUE_FLAGS);
+ if (error) {
+ softint_disestablish(wmq->wmq_si);
+ aprint_error_dev(sc->sc_dev,
+ "unable to create queue[%d] workqueue\n",
+ wmq->wmq_id);
+ goto err;
+ }
+
+ return 0;
+
+err:
pci_intr_disestablish(sc->sc_pc, sc->sc_ihs[wmq->wmq_intr_idx]);
sc->sc_ihs[wmq->wmq_intr_idx] = NULL;
return ENOMEM;
@@ -5448,7 +5487,7 @@
aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
sc->sc_nintrs = 1;
- return wm_softint_establish(sc, 0, 0);
+ return wm_softhandler_establish(sc, 0, 0);
}
static int
@@ -5526,7 +5565,7 @@
"for TX and RX interrupting at %s\n", intrstr);
}
sc->sc_ihs[intr_idx] = vih;
- if (wm_softint_establish(sc, qidx, intr_idx) != 0)
+ if (wm_softhandler_establish(sc, qidx, intr_idx) != 0)
goto fail;
txrx_established++;
intr_idx++;
@@ -5720,6 +5759,40 @@
#endif
}
+static void
+wm_init_sysctls(struct wm_softc *sc)
+{
+ struct sysctllog **log;
+ const struct sysctlnode *rnode, *cnode;
+ int rv;
+ const char *dvname;
+
+ log = &sc->sc_sysctllog;
+ dvname = device_xname(sc->sc_dev);
+
+ rv = sysctl_createv(log, 0, NULL, &rnode,
+ 0, CTLTYPE_NODE, dvname,
+ SYSCTL_DESCR("wm information and settings"),
+ NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
+ if (rv != 0)
+ goto err;
+
+ rv = sysctl_createv(log, 0, &rnode, &cnode, CTLFLAG_READWRITE,
+ CTLTYPE_BOOL, "txrx_workqueue", SYSCTL_DESCR("Use workqueue for packet processing"),
+ NULL, 0, &sc->sc_txrx_use_workqueue, 0, CTL_CREATE, CTL_EOL);
+ if (rv != 0)
+ goto teardown;
+
+ return;
+
+teardown:
+ sysctl_teardown(log);
+err:
+ sc->sc_sysctllog = NULL;
+ device_printf(sc->sc_dev, "%s: sysctl_createv failed, rv = %d\n",
+ __func__, rv);
+}
+
/*
* wm_init: [ifnet interface function]
*
@@ -9435,6 +9508,17 @@
wm_linkintr_tbi(sc, icr);
}
+
+static inline void
+wm_sched_handle_queue(struct wm_softc *sc, struct wm_queue *wmq)
+{
+
+ if (wmq->wmq_txrx_use_workqueue)
+ workqueue_enqueue(sc->sc_queue_wq, &wmq->wmq_cookie, curcpu());
+ else
+ softint_schedule(wmq->wmq_si);
+}
+
/*
* wm_intr_legacy:
*
@@ -9536,7 +9620,8 @@
if (handled) {
/* Try to get more packets going. */
- softint_schedule(wmq->wmq_si);
+ wmq->wmq_txrx_use_workqueue = sc->sc_txrx_use_workqueue;
+ wm_sched_handle_queue(sc, wmq);
}
return handled;
@@ -9639,9 +9724,10 @@
if (rndval != 0)
rnd_add_uint32(&sc->sc_queue[wmq->wmq_id].rnd_source, rndval);
- if (txmore || rxmore)
- softint_schedule(wmq->wmq_si);
- else
+ if (txmore || rxmore) {
+ wmq->wmq_txrx_use_workqueue = sc->sc_txrx_use_workqueue;
+ wm_sched_handle_queue(sc, wmq);
+ } else
wm_txrxintr_enable(wmq);
return 1;
@@ -9677,12 +9763,24 @@
rxmore = wm_rxeof(rxq, rxlimit);
mutex_exit(rxq->rxq_lock);
- if (txmore || rxmore)
- softint_schedule(wmq->wmq_si);
- else
+ if (txmore || rxmore) {
+ wmq->wmq_txrx_use_workqueue = sc->sc_txrx_use_workqueue;
+ wm_sched_handle_queue(sc, wmq);
+ } else
wm_txrxintr_enable(wmq);
}
+static void
+wm_handle_queue_work(struct work *wk, void *context)
+{
+ struct wm_queue *wmq = container_of(wk, struct wm_queue, wmq_cookie);
+
+ /*
+ * "enqueued flag" is not required here.
+ */
+ wm_handle_queue(wmq);
+}
+
/*
* wm_linkintr_msix:
*
Home |
Main Index |
Thread Index |
Old Index