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/633d4d7d39d1
branches:  trunk
changeset: 811117:633d4d7d39d1
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 3f379fae2af2 -r 633d4d7d39d1 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