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