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