Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci ready to support RX multiqueue.
details: https://anonhg.NetBSD.org/src/rev/b9de97fd86ed
branches: trunk
changeset: 340975:b9de97fd86ed
user: knakahara <knakahara%NetBSD.org@localhost>
date: Tue Oct 13 08:33:12 2015 +0000
description:
ready to support RX multiqueue.
ok by msaitoh@n.o
diffstat:
sys/dev/pci/if_wm.c | 692 ++++++++++++++++++++++++++++++++-------------------
1 files changed, 435 insertions(+), 257 deletions(-)
diffs (truncated from 1121 to 300 lines):
diff -r 2604240c016a -r b9de97fd86ed sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Tue Oct 13 08:29:44 2015 +0000
+++ b/sys/dev/pci/if_wm.c Tue Oct 13 08:33:12 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.363 2015/10/13 08:29:44 knakahara Exp $ */
+/* $NetBSD: if_wm.c,v 1.364 2015/10/13 08:33:12 knakahara Exp $ */
/*
* Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -83,7 +83,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.363 2015/10/13 08:29:44 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.364 2015/10/13 08:33:12 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -163,23 +163,11 @@
#endif
/*
- * This device driver divides interrupt to TX, RX and link state.
- * Each MSI-X vector indexes are below.
- */
-#define WM_MSIX_NINTR 3
-#define WM_MSIX_TXINTR_IDX 0
-#define WM_MSIX_RXINTR_IDX 1
-#define WM_MSIX_LINKINTR_IDX 2
-#define WM_MAX_NINTR WM_MSIX_NINTR
-
-/*
- * This device driver set affinity to each interrupts like below (round-robin).
- * If the number CPUs is less than the number of interrupts, this driver usase
- * the same CPU for multiple interrupts.
- */
-#define WM_MSIX_TXINTR_CPUID 0
-#define WM_MSIX_RXINTR_CPUID 1
-#define WM_MSIX_LINKINTR_CPUID 2
+ * This device driver's max interrupt numbers.
+ */
+#define WM_MAX_NTXINTR 16
+#define WM_MAX_NRXINTR 16
+#define WM_MAX_NINTR (WM_MAX_NTXINTR + WM_MAX_NRXINTR + 1)
/*
* Transmit descriptor list size. Due to errata, we can only have
@@ -269,6 +257,9 @@
struct wm_softc *txq_sc;
+ int txq_id; /* index of transmit queues */
+ int txq_intr_idx; /* index of MSI-X tables */
+
/* Software state for the transmit descriptors. */
int txq_num; /* must be a power of two */
struct wm_txsoft txq_soft[WM_TXQUEUELEN_MAX];
@@ -307,6 +298,9 @@
struct wm_softc *rxq_sc;
+ int rxq_id; /* index of receive queues */
+ int rxq_intr_idx; /* index of MSI-X tables */
+
/* Software state for the receive descriptors. */
wiseman_rxdesc_t *rxq_descs;
@@ -376,6 +370,8 @@
pci_intr_handle_t *sc_intrs; /* legacy and msi use sc_intrs[0] */
int sc_nintrs; /* number of interrupts */
+ int sc_link_intr_idx; /* index of MSI-X tables */
+
callout_t sc_tick_ch; /* tick callout */
bool sc_stopping;
@@ -1628,11 +1624,14 @@
}
/* XXX Currently, Tx, Rx queue are always one. */
+ sc->sc_ntxqueues = 1;
sc->sc_nrxqueues = 1;
- sc->sc_ntxqueues = 1;
error = wm_alloc_txrx_queues(sc);
- if (error)
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "cannot allocate queues %d\n",
+ error);
return;
+ }
#ifndef WM_MSI_MSIX
/*
@@ -1660,7 +1659,7 @@
#else /* WM_MSI_MSIX */
/* Allocation settings */
max_type = PCI_INTR_TYPE_MSIX;
- counts[PCI_INTR_TYPE_MSIX] = WM_MAX_NINTR;
+ counts[PCI_INTR_TYPE_MSIX] = sc->sc_ntxqueues + sc->sc_nrxqueues + 1;
counts[PCI_INTR_TYPE_MSI] = 1;
counts[PCI_INTR_TYPE_INTX] = 1;
@@ -2562,7 +2561,6 @@
wm_detach(device_t self, int flags __unused)
{
struct wm_softc *sc = device_private(self);
- struct wm_rxqueue *rxq = sc->sc_rxq;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
int i;
#ifndef WM_MPSAFE
@@ -2600,9 +2598,12 @@
/* Unload RX dmamaps and free mbufs */
- WM_RX_LOCK(rxq);
- wm_rxdrain(rxq);
- WM_RX_UNLOCK(rxq);
+ for (i = 0; i < sc->sc_nrxqueues; i++) {
+ struct wm_rxqueue *rxq = &sc->sc_rxq[i];
+ WM_RX_LOCK(rxq);
+ wm_rxdrain(rxq);
+ WM_RX_UNLOCK(rxq);
+ }
/* Must unlock here */
wm_free_txrx_queues(sc);
@@ -2671,7 +2672,7 @@
wm_watchdog(struct ifnet *ifp)
{
struct wm_softc *sc = ifp->if_softc;
- struct wm_txqueue *txq = sc->sc_txq;
+ struct wm_txqueue *txq = &sc->sc_txq[0];
/*
* Since we're using delayed interrupts, sweep up
@@ -3577,9 +3578,8 @@
static void
wm_reset(struct wm_softc *sc)
{
- struct wm_txqueue *txq = sc->sc_txq;
int phy_reset = 0;
- int error = 0;
+ int i, error = 0;
uint32_t reg, mask;
/*
@@ -3592,11 +3592,14 @@
case WM_T_82547_2:
sc->sc_pba = sc->sc_ethercom.ec_if.if_mtu > 8192 ?
PBA_22K : PBA_30K;
- txq->txq_fifo_head = 0;
- txq->txq_fifo_addr = sc->sc_pba << PBA_ADDR_SHIFT;
- txq->txq_fifo_size =
- (PBA_40K - sc->sc_pba) << PBA_BYTE_SHIFT;
- txq->txq_fifo_stall = 0;
+ for (i = 0; i < sc->sc_ntxqueues; i++) {
+ struct wm_txqueue *txq = &sc->sc_txq[i];
+ txq->txq_fifo_head = 0;
+ txq->txq_fifo_addr = sc->sc_pba << PBA_ADDR_SHIFT;
+ txq->txq_fifo_size =
+ (PBA_40K - sc->sc_pba) << PBA_BYTE_SHIFT;
+ txq->txq_fifo_stall = 0;
+ }
break;
case WM_T_82571:
case WM_T_82572:
@@ -4069,77 +4072,154 @@
{
void *vih;
kcpuset_t *affinity;
- int i, error;
+ int qidx, error, intr_idx, tx_established, rx_established;
pci_chipset_tag_t pc = sc->sc_pc;
const char *intrstr = NULL;
char intrbuf[PCI_INTRSTR_LEN];
char intr_xname[INTRDEVNAMEBUF];
- struct _msix_matrix {
- const char *intrname;
- int(*func)(void *);
- void *arg;
- int intridx;
- int cpuid;
- } msix_matrix[WM_MSIX_NINTR] = {
- { "TX", wm_txintr_msix, sc->sc_txq,
- WM_MSIX_TXINTR_IDX, WM_MSIX_TXINTR_CPUID },
- { "RX", wm_rxintr_msix, sc->sc_rxq,
- WM_MSIX_RXINTR_IDX, WM_MSIX_RXINTR_CPUID },
- { "LINK", wm_linkintr_msix, sc,
- WM_MSIX_LINKINTR_IDX, WM_MSIX_LINKINTR_CPUID },
- };
-
-
kcpuset_create(&affinity, false);
-
- for (i = 0; i < WM_MSIX_NINTR; i++) {
- intrstr = pci_intr_string(pc,
- sc->sc_intrs[msix_matrix[i].intridx], intrbuf,
+ intr_idx = 0;
+
+ /*
+ * TX
+ */
+ tx_established = 0;
+ for (qidx = 0; qidx < sc->sc_ntxqueues; qidx++) {
+ struct wm_txqueue *txq = &sc->sc_txq[qidx];
+
+ intrstr = pci_intr_string(pc, sc->sc_intrs[intr_idx], intrbuf,
sizeof(intrbuf));
#ifdef WM_MPSAFE
- pci_intr_setattr(pc,
- &sc->sc_intrs[msix_matrix[i].intridx],
+ pci_intr_setattr(pc, &sc->sc_intrs[intr_idx],
+ PCI_INTR_MPSAFE, true);
+#endif
+ memset(intr_xname, 0, sizeof(intr_xname));
+ snprintf(intr_xname, sizeof(intr_xname), "%sTX%d",
+ device_xname(sc->sc_dev), qidx);
+ vih = pci_intr_establish_xname(pc, sc->sc_intrs[intr_idx],
+ IPL_NET, wm_txintr_msix, txq, intr_xname);
+ if (vih == NULL) {
+ aprint_error_dev(sc->sc_dev,
+ "unable to establish MSI-X(for TX)%s%s\n",
+ intrstr ? " at " : "",
+ intrstr ? intrstr : "");
+
+ goto fail_0;
+ }
+ kcpuset_zero(affinity);
+ /* Round-robin affinity */
+ kcpuset_set(affinity, intr_idx % ncpu);
+ error = interrupt_distribute(vih, affinity, NULL);
+ if (error == 0) {
+ aprint_normal_dev(sc->sc_dev,
+ "for TX interrupting at %s affinity to %u\n",
+ intrstr, intr_idx % ncpu);
+ } else {
+ aprint_normal_dev(sc->sc_dev,
+ "for TX interrupting at %s\n", intrstr);
+ }
+ sc->sc_ihs[intr_idx] = vih;
+ txq->txq_id = qidx;
+ txq->txq_intr_idx = intr_idx;
+
+ tx_established++;
+ intr_idx++;
+ }
+
+ /*
+ * RX
+ */
+ rx_established = 0;
+ for (qidx = 0; qidx < sc->sc_nrxqueues; qidx++) {
+ struct wm_rxqueue *rxq = &sc->sc_rxq[qidx];
+
+ intrstr = pci_intr_string(pc, sc->sc_intrs[intr_idx], intrbuf,
+ sizeof(intrbuf));
+#ifdef WM_MPSAFE
+ pci_intr_setattr(pc, &sc->sc_intrs[intr_idx],
PCI_INTR_MPSAFE, true);
#endif
memset(intr_xname, 0, sizeof(intr_xname));
- strlcat(intr_xname, device_xname(sc->sc_dev),
- sizeof(intr_xname));
- strlcat(intr_xname, msix_matrix[i].intrname,
- sizeof(intr_xname));
- vih = pci_intr_establish_xname(pc,
- sc->sc_intrs[msix_matrix[i].intridx], IPL_NET,
- msix_matrix[i].func, msix_matrix[i].arg, intr_xname);
+ snprintf(intr_xname, sizeof(intr_xname), "%sRX%d",
+ device_xname(sc->sc_dev), qidx);
+ vih = pci_intr_establish_xname(pc, sc->sc_intrs[intr_idx],
+ IPL_NET, wm_rxintr_msix, rxq, intr_xname);
if (vih == NULL) {
aprint_error_dev(sc->sc_dev,
- "unable to establish MSI-X(for %s)%s%s\n",
- msix_matrix[i].intrname,
+ "unable to establish MSI-X(for RX)%s%s\n",
intrstr ? " at " : "",
intrstr ? intrstr : "");
- kcpuset_destroy(affinity);
-
- return ENOMEM;
+
+ goto fail_1;
}
kcpuset_zero(affinity);
/* Round-robin affinity */
- kcpuset_set(affinity, msix_matrix[i].cpuid % ncpu);
+ kcpuset_set(affinity, intr_idx % ncpu);
error = interrupt_distribute(vih, affinity, NULL);
if (error == 0) {
aprint_normal_dev(sc->sc_dev,
- "for %s interrupting at %s affinity to %u\n",
- msix_matrix[i].intrname, intrstr,
- msix_matrix[i].cpuid % ncpu);
+ "for RX interrupting at %s affinity to %u\n",
+ intrstr, intr_idx % ncpu);
} else {
aprint_normal_dev(sc->sc_dev,
Home |
Main Index |
Thread Index |
Old Index