Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Add multiqueue support, virtio(4)



details:   https://anonhg.NetBSD.org/src/rev/c297b438ca7a
branches:  trunk
changeset: 447510:c297b438ca7a
user:      yamaguchi <yamaguchi%NetBSD.org@localhost>
date:      Mon Jan 14 14:55:37 2019 +0000

description:
Add multiqueue support, virtio(4)

diffstat:

 sys/dev/pci/virtio.c     |  115 +++++++++++++++++++++++++++++++++++----
 sys/dev/pci/virtio_pci.c |  137 +++++++++++++++++++++++++++++++++++++++-------
 sys/dev/pci/virtiovar.h  |    8 ++-
 3 files changed, 226 insertions(+), 34 deletions(-)

diffs (truncated from 463 to 300 lines):

diff -r d309379cc431 -r c297b438ca7a sys/dev/pci/virtio.c
--- a/sys/dev/pci/virtio.c      Mon Jan 14 14:52:57 2019 +0000
+++ b/sys/dev/pci/virtio.c      Mon Jan 14 14:55:37 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: virtio.c,v 1.36 2018/09/30 15:44:22 jmcneill Exp $     */
+/*     $NetBSD: virtio.c,v 1.37 2019/01/14 14:55:37 yamaguchi Exp $    */
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.36 2018/09/30 15:44:22 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.37 2019/01/14 14:55:37 yamaguchi Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -235,6 +235,54 @@
                        ops);
 }
 
+static void
+virtio_vq_soft_intr(void *arg)
+{
+       struct virtqueue *vq = arg;
+
+       KASSERT(vq->vq_intrhand != NULL);
+
+       (vq->vq_intrhand)(vq);
+}
+
+static int
+virtio_vq_softint_establish(struct virtio_softc *sc)
+{
+       struct virtqueue *vq;
+       int qid;
+       u_int flags;
+
+       flags = SOFTINT_NET;
+       if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE)
+               flags |= SOFTINT_MPSAFE;
+
+       for (qid = 0; qid < sc->sc_nvqs; qid++) {
+               vq = &sc->sc_vqs[qid];
+               vq->vq_soft_ih =
+                   softint_establish(flags, virtio_vq_soft_intr, vq);
+               if (vq->vq_soft_ih == NULL)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static void
+virtio_vq_softint_disestablish(struct virtio_softc *sc)
+{
+       struct virtqueue *vq;
+       int qid;
+
+       for (qid = 0; qid < sc->sc_nvqs; qid++) {
+               vq = &sc->sc_vqs[qid];
+               if (vq->vq_soft_ih == NULL)
+                       continue;
+
+               softint_disestablish(vq->vq_soft_ih);
+               vq->vq_soft_ih = NULL;
+       }
+}
+
 /*
  * Can be used as sc_intrhand.
  */
@@ -242,6 +290,26 @@
  * Scan vq, bus_dmamap_sync for the vqs (not for the payload),
  * and calls (*vq_done)() if some entries are consumed.
  */
+static int
+virtio_vq_intr_common(struct virtqueue *vq)
+{
+       struct virtio_softc *sc = vq->vq_owner;
+       int r = 0;
+
+       if (vq->vq_queued) {
+               vq->vq_queued = 0;
+               vq_sync_aring(sc, vq, BUS_DMASYNC_POSTWRITE);
+       }
+       vq_sync_uring(sc, vq, BUS_DMASYNC_POSTREAD);
+       membar_consumer();
+       if (vq->vq_used_idx != vq->vq_used->idx) {
+               if (vq->vq_done)
+                       r |= (vq->vq_done)(vq);
+       }
+
+       return r;
+}
+
 int
 virtio_vq_intr(struct virtio_softc *sc)
 {
@@ -250,21 +318,19 @@
 
        for (i = 0; i < sc->sc_nvqs; i++) {
                vq = &sc->sc_vqs[i];
-               if (vq->vq_queued) {
-                       vq->vq_queued = 0;
-                       vq_sync_aring(sc, vq, BUS_DMASYNC_POSTWRITE);
-               }
-               vq_sync_uring(sc, vq, BUS_DMASYNC_POSTREAD);
-               membar_consumer();
-               if (vq->vq_used_idx != vq->vq_used->idx) {
-                       if (vq->vq_done)
-                               r |= (vq->vq_done)(vq);
-               }
+               r |= virtio_vq_intr_common(vq);
        }
 
        return r;
 }
 
+static int
+virtio_vq_mq_intr(struct virtqueue *vq)
+{
+
+       return virtio_vq_intr_common(vq);
+}
+
 /*
  * Start/stop vq interrupt.  No guarantee.
  */
@@ -409,6 +475,7 @@
 
        /* remember addresses and offsets for later use */
        vq->vq_owner = sc;
+       vq->vq_intrhand = virtio_vq_mq_intr;
        vq->vq_num = vq_size;
        vq->vq_index = index;
        vq->vq_desc = vq->vq_vaddr;
@@ -844,6 +911,16 @@
        aprint_naive("\n");
 }
 
+void
+virtio_child_attach_set_vqs(struct virtio_softc *sc,
+    struct virtqueue *vqs, int nvq_pairs)
+{
+       if (nvq_pairs > 1)
+               sc->sc_child_mq = true;
+
+       sc->sc_vqs = vqs;
+}
+
 int
 virtio_child_attach_finish(struct virtio_softc *sc)
 {
@@ -868,12 +945,26 @@
                            "failed to establish soft interrupt\n");
                        goto fail;
                }
+
+               if (sc->sc_child_mq) {
+                       r = virtio_vq_softint_establish(sc);
+                       aprint_error_dev(sc->sc_dev,
+                           "failed to establish softint interrupt\n");
+                       goto fail;
+               }
        }
 
        virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
        return 0;
 
 fail:
+       if (sc->sc_soft_ih) {
+               softint_disestablish(sc->sc_soft_ih);
+               sc->sc_soft_ih = NULL;
+       }
+
+       virtio_vq_softint_disestablish(sc);
+
        virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
        return 1;
 }
diff -r d309379cc431 -r c297b438ca7a sys/dev/pci/virtio_pci.c
--- a/sys/dev/pci/virtio_pci.c  Mon Jan 14 14:52:57 2019 +0000
+++ b/sys/dev/pci/virtio_pci.c  Mon Jan 14 14:55:37 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: virtio_pci.c,v 1.5 2018/06/06 16:11:36 jakllsch Exp $ */
+/* $NetBSD: virtio_pci.c,v 1.6 2019/01/14 14:55:37 yamaguchi Exp $ */
 
 /*
  * Copyright (c) 2010 Minoura Makoto.
@@ -26,12 +26,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: virtio_pci.c,v 1.5 2018/06/06 16:11:36 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: virtio_pci.c,v 1.6 2019/01/14 14:55:37 yamaguchi Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kmem.h>
 #include <sys/module.h>
+#include <sys/interrupt.h>
 
 #include <sys/device.h>
 
@@ -79,6 +80,7 @@
 
 static int     virtio_pci_intr(void *arg);
 static int     virtio_pci_msix_queue_intr(void *);
+static int     virtio_pci_msix_vq_intr(void *);
 static int     virtio_pci_msix_config_intr(void *);
 static int     virtio_pci_setup_msix_vectors(struct virtio_softc *);
 static int     virtio_pci_setup_msix_interrupts(struct virtio_softc *,
@@ -428,7 +430,7 @@
 
        if (psc->sc_ihs_num > 1) {
                int vec = VIRTIO_MSIX_QUEUE_VECTOR_INDEX;
-               if (false) /* (for per-vq vectors) */
+               if (sc->sc_child_mq)
                        vec += idx;
                bus_space_write_stream_2(psc->sc_iot, psc->sc_ioh,
                    VIRTIO_CONFIG_MSI_QUEUE_VECTOR, vec);
@@ -488,6 +490,9 @@
                offset = VIRTIO_CONFIG_MSI_QUEUE_VECTOR;
                vector = VIRTIO_MSIX_QUEUE_VECTOR_INDEX;
 
+               if (sc->sc_child_mq)
+                       vector += qid;
+
                bus_space_write_stream_2(psc->sc_iot, psc->sc_ioh, offset, vector);
                ret = bus_space_read_stream_2(psc->sc_iot, psc->sc_ioh, offset);
                aprint_debug_dev(sc->sc_dev, "expected=%d, actual=%d\n",
@@ -507,29 +512,57 @@
        device_t self = sc->sc_dev;
        pci_chipset_tag_t pc = pa->pa_pc;
        char intrbuf[PCI_INTRSTR_LEN];
+       char intr_xname[INTRDEVNAMEBUF];
        char const *intrstr;
-       int idx;
+       int idx, qid, n;
 
        idx = VIRTIO_MSIX_CONFIG_VECTOR_INDEX;
        if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE)
                pci_intr_setattr(pc, &psc->sc_ihp[idx], PCI_INTR_MPSAFE, true);
 
+       snprintf(intr_xname, sizeof(intr_xname), "%s config",
+           device_xname(sc->sc_dev));
+
        psc->sc_ihs[idx] = pci_intr_establish_xname(pc, psc->sc_ihp[idx],
-           sc->sc_ipl, virtio_pci_msix_config_intr, sc, device_xname(sc->sc_dev));
+           sc->sc_ipl, virtio_pci_msix_config_intr, sc, intr_xname);
        if (psc->sc_ihs[idx] == NULL) {
                aprint_error_dev(self, "couldn't establish MSI-X for config\n");
                goto error;
        }
 
        idx = VIRTIO_MSIX_QUEUE_VECTOR_INDEX;
-       if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE)
-               pci_intr_setattr(pc, &psc->sc_ihp[idx], PCI_INTR_MPSAFE, true);
+       if (sc->sc_child_mq) {
+               for (qid = 0; qid < sc->sc_nvqs; qid++) {
+                       n = idx + qid;
+
+                       snprintf(intr_xname, sizeof(intr_xname), "%s vq#%d",
+                           device_xname(sc->sc_dev), qid);
+
+                       if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE) {
+                               pci_intr_setattr(pc, &psc->sc_ihp[n],
+                                   PCI_INTR_MPSAFE, true);
+                       }
 
-       psc->sc_ihs[idx] = pci_intr_establish_xname(pc, psc->sc_ihp[idx],
-           sc->sc_ipl, virtio_pci_msix_queue_intr, sc, device_xname(sc->sc_dev));
-       if (psc->sc_ihs[idx] == NULL) {
-               aprint_error_dev(self, "couldn't establish MSI-X for queues\n");
-               goto error;
+                       psc->sc_ihs[n] = pci_intr_establish_xname(pc, psc->sc_ihp[n],
+                           sc->sc_ipl, virtio_pci_msix_vq_intr, &sc->sc_vqs[qid],
+                           intr_xname);
+                       if (psc->sc_ihs[n] == NULL) {
+                               aprint_error_dev(self, "couldn't establish MSI-X for a vq\n");
+                               goto error;
+                       }
+               }
+       } else {
+               if (sc->sc_flags & VIRTIO_F_PCI_INTR_MPSAFE)
+                       pci_intr_setattr(pc, &psc->sc_ihp[idx], PCI_INTR_MPSAFE, true);
+
+               snprintf(intr_xname, sizeof(intr_xname), "%s queues",
+                   device_xname(sc->sc_dev));
+               psc->sc_ihs[idx] = pci_intr_establish_xname(pc, psc->sc_ihp[idx],
+                   sc->sc_ipl, virtio_pci_msix_queue_intr, sc, intr_xname);
+               if (psc->sc_ihs[idx] == NULL) {
+                       aprint_error_dev(self, "couldn't establish MSI-X for queues\n");
+                       goto error;
+               }
        }
 
        if (virtio_pci_setup_msix_vectors(sc) != 0) {



Home | Main Index | Thread Index | Old Index