Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci support RX multiqueue.
details: https://anonhg.NetBSD.org/src/rev/c05272e6fdda
branches: trunk
changeset: 340976:c05272e6fdda
user: knakahara <knakahara%NetBSD.org@localhost>
date: Tue Oct 13 08:36:02 2015 +0000
description:
support RX multiqueue.
ok by msaitoh@n.o
diffstat:
sys/dev/pci/if_wm.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/pci/if_wmreg.h | 55 ++++++++++++++-
2 files changed, 236 insertions(+), 7 deletions(-)
diffs (truncated from 339 to 300 lines):
diff -r b9de97fd86ed -r c05272e6fdda sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Tue Oct 13 08:33:12 2015 +0000
+++ b/sys/dev/pci/if_wm.c Tue Oct 13 08:36:02 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.364 2015/10/13 08:33:12 knakahara Exp $ */
+/* $NetBSD: if_wm.c,v 1.365 2015/10/13 08:36:02 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.364 2015/10/13 08:33:12 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.365 2015/10/13 08:36:02 knakahara Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -565,6 +565,7 @@
static void wm_reset(struct wm_softc *);
static int wm_add_rxbuf(struct wm_rxqueue *, int);
static void wm_rxdrain(struct wm_rxqueue *);
+static void wm_init_rss(struct wm_softc *);
static int wm_init(struct ifnet *);
static int wm_init_locked(struct ifnet *);
static void wm_stop(struct ifnet *, int);
@@ -609,6 +610,7 @@
static void wm_linkintr(struct wm_softc *, uint32_t);
static int wm_intr_legacy(void *);
#ifdef WM_MSI_MSIX
+static void wm_adjust_qnum(struct wm_softc *, int);
static int wm_setup_legacy(struct wm_softc *);
static int wm_setup_msix(struct wm_softc *);
static int wm_txintr_msix(void *);
@@ -1623,7 +1625,7 @@
return;
}
- /* XXX Currently, Tx, Rx queue are always one. */
+#ifndef WM_MSI_MSIX
sc->sc_ntxqueues = 1;
sc->sc_nrxqueues = 1;
error = wm_alloc_txrx_queues(sc);
@@ -1633,7 +1635,6 @@
return;
}
-#ifndef WM_MSI_MSIX
/*
* Map and establish our interrupt.
*/
@@ -1657,6 +1658,14 @@
aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
sc->sc_nintrs = 1;
#else /* WM_MSI_MSIX */
+ wm_adjust_qnum(sc, pci_msix_count(pa->pa_pc, pa->pa_tag));
+ error = wm_alloc_txrx_queues(sc);
+ if (error) {
+ aprint_error_dev(sc->sc_dev, "cannot allocate queues %d\n",
+ error);
+ return;
+ }
+
/* Allocation settings */
max_type = PCI_INTR_TYPE_MSIX;
counts[PCI_INTR_TYPE_MSIX] = sc->sc_ntxqueues + sc->sc_nrxqueues + 1;
@@ -4036,6 +4045,159 @@
}
}
+/*
+ * Adjust TX and RX queue numbers which the system actulally uses.
+ *
+ * The numbers are affected by below parameters.
+ * - The nubmer of hardware queues
+ * - The number of MSI-X vectors (= "nvectors" argument)
+ * - ncpu
+ */
+static void
+wm_adjust_qnum(struct wm_softc *sc, int nvectors)
+{
+ int hw_ntxqueues, hw_nrxqueues;
+
+ if (nvectors < 3) {
+ sc->sc_ntxqueues = 1;
+ sc->sc_nrxqueues = 1;
+ return;
+ }
+
+ switch(sc->sc_type) {
+ case WM_T_82572:
+ hw_ntxqueues = 2;
+ hw_nrxqueues = 2;
+ break;
+ case WM_T_82574:
+ hw_ntxqueues = 2;
+ hw_nrxqueues = 2;
+ break;
+ case WM_T_82575:
+ hw_ntxqueues = 4;
+ hw_nrxqueues = 4;
+ break;
+ case WM_T_82576:
+ hw_ntxqueues = 16;
+ hw_nrxqueues = 16;
+ break;
+ case WM_T_82580:
+ case WM_T_I350:
+ case WM_T_I354:
+ hw_ntxqueues = 8;
+ hw_nrxqueues = 8;
+ break;
+ case WM_T_I210:
+ hw_ntxqueues = 4;
+ hw_nrxqueues = 4;
+ break;
+ case WM_T_I211:
+ hw_ntxqueues = 2;
+ hw_nrxqueues = 2;
+ break;
+ /*
+ * As below ethernet controllers does not support MSI-X,
+ * this driver let them not use multiqueue.
+ * - WM_T_80003
+ * - WM_T_ICH8
+ * - WM_T_ICH9
+ * - WM_T_ICH10
+ * - WM_T_PCH
+ * - WM_T_PCH2
+ * - WM_T_PCH_LPT
+ */
+ default:
+ hw_ntxqueues = 1;
+ hw_nrxqueues = 1;
+ break;
+ }
+
+ /*
+ * As queues more then MSI-X vectors cannot improve scaling, we limit
+ * the number of queues used actually.
+ *
+ * XXX
+ * Currently, we separate TX queue interrupts and RX queue interrupts.
+ * Howerver, the number of MSI-X vectors of recent controllers (such as
+ * I354) expects that drivers bundle a TX queue interrupt and a RX
+ * interrupt to one interrupt. e.g. FreeBSD's igb deals interrupts in
+ * such a way.
+ */
+ if (nvectors < hw_ntxqueues + hw_nrxqueues + 1) {
+ sc->sc_ntxqueues = (nvectors - 1) / 2;
+ sc->sc_nrxqueues = (nvectors - 1) / 2;
+ } else {
+ sc->sc_ntxqueues = hw_ntxqueues;
+ sc->sc_nrxqueues = hw_nrxqueues;
+ }
+
+ /*
+ * As queues more then cpus cannot improve scaling, we limit
+ * the number of queues used actually.
+ */
+ if (ncpu < sc->sc_ntxqueues)
+ sc->sc_ntxqueues = ncpu;
+ if (ncpu < sc->sc_nrxqueues)
+ sc->sc_nrxqueues = ncpu;
+
+ /* XXX Currently, this driver supports RX multiqueue only. */
+ sc->sc_ntxqueues = 1;
+}
+
+/*
+ * Setup registers for RSS.
+ *
+ * XXX not yet VMDq support
+ */
+static void
+wm_init_rss(struct wm_softc *sc)
+{
+ uint32_t mrqc, reta_reg;
+ int i;
+
+ for (i = 0; i < RETA_NUM_ENTRIES; i++) {
+ int qid, reta_ent;
+
+ qid = i % sc->sc_nrxqueues;
+ switch(sc->sc_type) {
+ case WM_T_82574:
+ reta_ent = __SHIFTIN(qid,
+ RETA_ENT_QINDEX_MASK_82574);
+ break;
+ case WM_T_82575:
+ reta_ent = __SHIFTIN(qid,
+ RETA_ENT_QINDEX1_MASK_82575);
+ break;
+ default:
+ reta_ent = __SHIFTIN(qid, RETA_ENT_QINDEX_MASK);
+ break;
+ }
+
+ reta_reg = CSR_READ(sc, WMREG_RETA_Q(i));
+ reta_reg &= ~RETA_ENTRY_MASK_Q(i);
+ reta_reg |= __SHIFTIN(reta_ent, RETA_ENTRY_MASK_Q(i));
+ CSR_WRITE(sc, WMREG_RETA_Q(i), reta_reg);
+ }
+
+ for (i = 0; i < RSSRK_NUM_REGS; i++)
+ CSR_WRITE(sc, WMREG_RSSRK(i), (uint32_t)random());
+
+ if (sc->sc_type == WM_T_82574)
+ mrqc = MRQC_ENABLE_RSS_MQ_82574;
+ else
+ mrqc = MRQC_ENABLE_RSS_MQ;
+
+ /* XXXX
+ * The same as FreeBSD igb.
+ * Why doesn't use MRQC_RSS_FIELD_IPV6_EX?
+ */
+ mrqc |= (MRQC_RSS_FIELD_IPV4 | MRQC_RSS_FIELD_IPV4_TCP);
+ mrqc |= (MRQC_RSS_FIELD_IPV6 | MRQC_RSS_FIELD_IPV6_TCP);
+ mrqc |= (MRQC_RSS_FIELD_IPV4_UDP | MRQC_RSS_FIELD_IPV6_UDP);
+ mrqc |= (MRQC_RSS_FIELD_IPV6_UDP_EX | MRQC_RSS_FIELD_IPV6_TCP_EX);
+
+ CSR_WRITE(sc, WMREG_MRQC, mrqc);
+}
#ifdef WM_MSI_MSIX
/*
@@ -4450,13 +4612,13 @@
for (i = 0; i < sc->sc_ntxqueues; i++) {
struct wm_txqueue *txq = &sc->sc_txq[i];
CSR_WRITE(sc, WMREG_MSIXBM(txq->txq_intr_idx),
- txq->txq_id);
+ EITR_TX_QUEUE(txq->txq_id));
}
/* RX */
for (i = 0; i < sc->sc_nrxqueues; i++) {
struct wm_rxqueue *rxq = &sc->sc_rxq[i];
CSR_WRITE(sc, WMREG_MSIXBM(rxq->rxq_intr_idx),
- rxq->rxq_id);
+ EITR_RX_QUEUE(rxq->rxq_id));
}
/* Link status */
CSR_WRITE(sc, WMREG_MSIXBM(sc->sc_link_intr_idx),
@@ -4554,6 +4716,20 @@
IVAR_MISC_OTHER);
CSR_WRITE(sc, WMREG_IVAR_MISC, ivar);
}
+
+ if (sc->sc_nrxqueues > 1) {
+ wm_init_rss(sc);
+
+ /*
+ ** NOTE: Receive Full-Packet Checksum Offload
+ ** is mutually exclusive with Multiqueue. However
+ ** this is not the same as TCP/IP checksums which
+ ** still work.
+ */
+ reg = CSR_READ(sc, WMREG_RXCSUM);
+ reg |= RXCSUM_PCSD;
+ CSR_WRITE(sc, WMREG_RXCSUM, reg);
+ }
}
/* Set up the interrupt registers. */
diff -r b9de97fd86ed -r c05272e6fdda sys/dev/pci/if_wmreg.h
--- a/sys/dev/pci/if_wmreg.h Tue Oct 13 08:33:12 2015 +0000
+++ b/sys/dev/pci/if_wmreg.h Tue Oct 13 08:36:02 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wmreg.h,v 1.83 2015/10/13 08:23:31 knakahara Exp $ */
+/* $NetBSD: if_wmreg.h,v 1.84 2015/10/13 08:36:02 knakahara Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -878,6 +878,9 @@
#define RXCSUM_IPOFL (1U << 8) /* IP checksum offload */
#define RXCSUM_TUOFL (1U << 9) /* TCP/UDP checksum offload */
#define RXCSUM_IPV6OFL (1U << 10) /* IPv6 checksum offload */
+#define RXCSUM_CRCOFL (1U << 10) /* SCTP CRC32 checksum offload */
+#define RXCSUM_IPPCSE (1U << 12) /* IP payload checksum enable */
+#define RXCSUM_PCSD (1U << 13) /* packet checksum disabled */
#define WMREG_RLPML 0x5004 /* Rx Long Packet Max Length */
@@ -902,6 +905,56 @@
#define WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup En */
#define WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup En */
+#define WMREG_MRQC 0x5818 /* Multiple Receive Queues Command */
+#define MRQC_DISABLE_RSS 0x00000000
+#define MRQC_ENABLE_RSS_MQ_82574 __BIT(0) /* enable RSS for 82574 */
+#define MRQC_ENABLE_RSS_MQ __BIT(1) /* enable hardware max RSS without VMDq */
+#define MRQC_ENABLE_RSS_VMDQ __BITS(1, 0) /* enable RSS with VMDq */
+#define MRQC_DEFQ_MASK __BITS(5, 3)
+ /*
+ * Defines the default queue in non VMDq
+ * mode according to value of the Multiple Receive
+ * Queues Enable field.
+ */
+#define MRQC_DEFQ_NOT_RSS_FLT __SHFTIN(__BIT(1), MRQC_DEFQ_MASK)
+ /*
+ * the destination of all packets
Home |
Main Index |
Thread Index |
Old Index