diff options
author | bryanv <bryanv@FreeBSD.org> | 2013-07-04 17:59:09 +0000 |
---|---|---|
committer | bryanv <bryanv@FreeBSD.org> | 2013-07-04 17:59:09 +0000 |
commit | c07f9b1406dc341b897c83057d28907b8e2fc35f (patch) | |
tree | 090f15d7d38b8f0bda30c7440ac2740770885cd5 | |
parent | 5cda36b5ac3c30cfb2a0c172471aacfa08583438 (diff) | |
download | FreeBSD-src-c07f9b1406dc341b897c83057d28907b8e2fc35f.zip FreeBSD-src-c07f9b1406dc341b897c83057d28907b8e2fc35f.tar.gz |
Merge virtio_pci changes from projects/virtio
This commit is primarily a significant cleanup to the interrupt
allocation code that had gotten a bit jumbled from having to
support per-vq MSIX, shared MSIX, MSI, and legacy style interrupts.
Contains projects/virtio commits:
r246064:
virtio_pci: Rewrite allocation of interrupts
r246065:
virtio_pci: Remove spaces before a tab
r246066:
virtio_pci: Dynamically allocate the virtqueue array
r246304:
virtio_pci: Clean up after failed virtqueue alloc attempt
r246305:
virtio_pci: Move no interrupt check into the PCI interrupt handlers
r246308:
virtio_pci: Remove unused variable
MFC after: 1 month
-rw-r--r-- | sys/dev/virtio/pci/virtio_pci.c | 433 | ||||
-rw-r--r-- | sys/dev/virtio/virtio.h | 5 | ||||
-rw-r--r-- | sys/dev/virtio/virtqueue.c | 5 |
3 files changed, 242 insertions, 201 deletions
diff --git a/sys/dev/virtio/pci/virtio_pci.c b/sys/dev/virtio/pci/virtio_pci.c index 0e7d412..b3df3d9 100644 --- a/sys/dev/virtio/pci/virtio_pci.c +++ b/sys/dev/virtio/pci/virtio_pci.c @@ -51,6 +51,17 @@ __FBSDID("$FreeBSD$"); #include "virtio_bus_if.h" #include "virtio_if.h" +struct vtpci_interrupt { + struct resource *vti_irq; + int vti_rid; + void *vti_handler; +}; + +struct vtpci_virtqueue { + struct virtqueue *vtv_vq; + int vtv_no_intr; +}; + struct vtpci_softc { device_t vtpci_dev; struct resource *vtpci_res; @@ -69,40 +80,22 @@ struct vtpci_softc { device_t vtpci_child_dev; struct virtio_feature_desc *vtpci_child_feat_desc; - /* - * Ideally, each virtqueue that the driver provides a callback for - * will receive its own MSIX vector. If there are not sufficient - * vectors available, we will then attempt to have all the VQs - * share one vector. Note that when using MSIX, the configuration - * changed notifications must be on their own vector. - * - * If MSIX is not available, we will attempt to have the whole - * device share one MSI vector, and then, finally, one legacy - * interrupt. - */ int vtpci_nvqs; - struct vtpci_virtqueue { - struct virtqueue *vq; - /* Device did not provide a callback for this virtqueue. */ - int no_intr; - /* Index into vtpci_intr_res[] below. Unused, then -1. */ - int ires_idx; - } vtpci_vqx[VIRTIO_MAX_VIRTQUEUES]; + struct vtpci_virtqueue *vtpci_vqs; /* - * When using MSIX interrupts, the first element of vtpci_intr_res[] - * is always the configuration changed notifications. The remaining - * element(s) are used for the virtqueues. + * Ideally, each virtqueue that the driver provides a callback for will + * receive its own MSIX vector. If there are not sufficient vectors + * available, then attempt to have all the VQs share one vector. For + * MSIX, the configuration changed notifications must be on their own + * vector. * - * With MSI and legacy interrupts, only the first element of - * vtpci_intr_res[] is used. + * If MSIX is not available, we will attempt to have the whole device + * share one MSI vector, and then, finally, one legacy interrupt. */ - int vtpci_nintr_res; - struct vtpci_intr_resource { - struct resource *irq; - int rid; - void *intrhand; - } vtpci_intr_res[1 + VIRTIO_MAX_VIRTQUEUES]; + struct vtpci_interrupt vtpci_device_interrupt; + struct vtpci_interrupt *vtpci_msix_vq_interrupts; + int vtpci_nmsix_resources; }; static int vtpci_probe(device_t); @@ -134,28 +127,35 @@ static void vtpci_describe_features(struct vtpci_softc *, const char *, uint64_t); static void vtpci_probe_and_attach_child(struct vtpci_softc *); -static int vtpci_alloc_msix(struct vtpci_softc *, int); -static int vtpci_alloc_msi(struct vtpci_softc *); -static int vtpci_alloc_intr_msix_pervq(struct vtpci_softc *); -static int vtpci_alloc_intr_msix_shared(struct vtpci_softc *); -static int vtpci_alloc_intr_msi(struct vtpci_softc *); -static int vtpci_alloc_intr_legacy(struct vtpci_softc *); +static int vtpci_alloc_msix(struct vtpci_softc *, int); +static int vtpci_alloc_msi(struct vtpci_softc *); +static int vtpci_alloc_intr_msix_pervq(struct vtpci_softc *); +static int vtpci_alloc_intr_msix_shared(struct vtpci_softc *); +static int vtpci_alloc_intr_msi(struct vtpci_softc *); +static int vtpci_alloc_intr_legacy(struct vtpci_softc *); +static int vtpci_alloc_interrupt(struct vtpci_softc *, int, int, + struct vtpci_interrupt *); static int vtpci_alloc_intr_resources(struct vtpci_softc *); -static int vtpci_setup_legacy_interrupt(struct vtpci_softc *, +static int vtpci_setup_legacy_interrupt(struct vtpci_softc *, enum intr_type); -static int vtpci_setup_msix_interrupts(struct vtpci_softc *, +static int vtpci_setup_pervq_msix_interrupts(struct vtpci_softc *, enum intr_type); -static int vtpci_setup_interrupts(struct vtpci_softc *, enum intr_type); +static int vtpci_setup_msix_interrupts(struct vtpci_softc *, + enum intr_type); +static int vtpci_setup_interrupts(struct vtpci_softc *, enum intr_type); -static int vtpci_register_msix_vector(struct vtpci_softc *, int, int); -static int vtpci_set_host_msix_vectors(struct vtpci_softc *); -static int vtpci_reinit_virtqueue(struct vtpci_softc *, int); +static int vtpci_register_msix_vector(struct vtpci_softc *, int, + struct vtpci_interrupt *); +static int vtpci_set_host_msix_vectors(struct vtpci_softc *); +static int vtpci_reinit_virtqueue(struct vtpci_softc *, int); +static void vtpci_free_interrupt(struct vtpci_softc *, + struct vtpci_interrupt *); static void vtpci_free_interrupts(struct vtpci_softc *); static void vtpci_free_virtqueues(struct vtpci_softc *); -static void vtpci_cleanup_setup_intr_attempt(struct vtpci_softc *); static void vtpci_release_child_resources(struct vtpci_softc *); +static void vtpci_cleanup_setup_intr_attempt(struct vtpci_softc *); static void vtpci_reset(struct vtpci_softc *); static void vtpci_select_virtqueue(struct vtpci_softc *, int); @@ -480,15 +480,19 @@ vtpci_alloc_virtqueues(device_t dev, int flags, int nvqs, uint16_t size; sc = device_get_softc(dev); - error = 0; if (sc->vtpci_nvqs != 0) return (EALREADY); - if (nvqs <= 0 || nvqs > VIRTIO_MAX_VIRTQUEUES) + if (nvqs <= 0) return (EINVAL); + sc->vtpci_vqs = malloc(nvqs * sizeof(struct vtpci_virtqueue), + M_DEVBUF, M_NOWAIT | M_ZERO); + if (sc->vtpci_vqs == NULL) + return (ENOMEM); + for (idx = 0; idx < nvqs; idx++) { - vqx = &sc->vtpci_vqx[idx]; + vqx = &sc->vtpci_vqs[idx]; info = &vq_info[idx]; vtpci_select_virtqueue(sc, idx); @@ -505,12 +509,15 @@ vtpci_alloc_virtqueues(device_t dev, int flags, int nvqs, vtpci_write_config_4(sc, VIRTIO_PCI_QUEUE_PFN, virtqueue_paddr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); - vqx->vq = *info->vqai_vq = vq; - vqx->no_intr = info->vqai_intr == NULL; + vqx->vtv_vq = *info->vqai_vq = vq; + vqx->vtv_no_intr = info->vqai_intr == NULL; sc->vtpci_nvqs++; } + if (error) + vtpci_free_virtqueues(sc); + return (error); } @@ -771,7 +778,7 @@ vtpci_alloc_msix(struct vtpci_softc *sc, int nvectors) cnt = required; if (pci_alloc_msix(dev, &cnt) == 0 && cnt >= required) { - sc->vtpci_nintr_res = required; + sc->vtpci_nmsix_resources = required; return (0); } @@ -794,10 +801,8 @@ vtpci_alloc_msi(struct vtpci_softc *sc) return (1); cnt = required; - if (pci_alloc_msi(dev, &cnt) == 0 && cnt >= required) { - sc->vtpci_nintr_res = required; + if (pci_alloc_msi(dev, &cnt) == 0 && cnt >= required) return (0); - } pci_release_msi(dev); @@ -814,7 +819,7 @@ vtpci_alloc_intr_msix_pervq(struct vtpci_softc *sc) return (ENOTSUP); for (nvectors = 0, i = 0; i < sc->vtpci_nvqs; i++) { - if (sc->vtpci_vqx[i].no_intr == 0) + if (sc->vtpci_vqs[i].vtv_no_intr == 0) nvectors++; } @@ -868,54 +873,62 @@ vtpci_alloc_intr_legacy(struct vtpci_softc *sc) { sc->vtpci_flags |= VTPCI_FLAG_LEGACY; - sc->vtpci_nintr_res = 1; return (0); } static int -vtpci_alloc_intr_resources(struct vtpci_softc *sc) +vtpci_alloc_interrupt(struct vtpci_softc *sc, int rid, int flags, + struct vtpci_interrupt *intr) { - device_t dev; struct resource *irq; - struct vtpci_virtqueue *vqx; - int i, rid, flags, res_idx; - dev = sc->vtpci_dev; + irq = bus_alloc_resource_any(sc->vtpci_dev, SYS_RES_IRQ, &rid, flags); + if (irq == NULL) + return (ENXIO); - if (sc->vtpci_flags & VTPCI_FLAG_LEGACY) { - rid = 0; - flags = RF_ACTIVE | RF_SHAREABLE; - } else { - rid = 1; - flags = RF_ACTIVE; - } + intr->vti_irq = irq; + intr->vti_rid = rid; - for (i = 0; i < sc->vtpci_nintr_res; i++) { - irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, flags); - if (irq == NULL) - return (ENXIO); + return (0); +} - sc->vtpci_intr_res[i].irq = irq; - sc->vtpci_intr_res[i].rid = rid++; - } +static int +vtpci_alloc_intr_resources(struct vtpci_softc *sc) +{ + struct vtpci_interrupt *intr; + int i, rid, flags, nvq_intrs, error; + + rid = 0; + flags = RF_ACTIVE; + + if (sc->vtpci_flags & VTPCI_FLAG_LEGACY) + flags |= RF_SHAREABLE; + else + rid = 1; /* - * Map the virtqueue into the correct index in vq_intr_res[]. The - * first index is reserved for configuration changed notifications. + * For legacy and MSI interrupts, this single resource handles all + * interrupts. For MSIX, this resource is used for the configuration + * changed interrupt. */ - for (i = 0, res_idx = 1; i < sc->vtpci_nvqs; i++) { - vqx = &sc->vtpci_vqx[i]; - - if (sc->vtpci_flags & VTPCI_FLAG_MSIX) { - if (vqx->no_intr != 0) - vqx->ires_idx = -1; - else if (sc->vtpci_flags & VTPCI_FLAG_SHARED_MSIX) - vqx->ires_idx = res_idx; - else - vqx->ires_idx = res_idx++; - } else - vqx->ires_idx = -1; + intr = &sc->vtpci_device_interrupt; + error = vtpci_alloc_interrupt(sc, rid, flags, intr); + if (error || sc->vtpci_flags & (VTPCI_FLAG_LEGACY | VTPCI_FLAG_MSI)) + return (error); + + /* Subtract one for the configuration changed interrupt. */ + nvq_intrs = sc->vtpci_nmsix_resources - 1; + + intr = sc->vtpci_msix_vq_interrupts = malloc(nvq_intrs * + sizeof(struct vtpci_interrupt), M_DEVBUF, M_NOWAIT | M_ZERO); + if (sc->vtpci_msix_vq_interrupts == NULL) + return (ENOMEM); + + for (i = 0, rid++; i < nvq_intrs; i++, rid++, intr++) { + error = vtpci_alloc_interrupt(sc, rid, flags, intr); + if (error) + return (error); } return (0); @@ -924,63 +937,67 @@ vtpci_alloc_intr_resources(struct vtpci_softc *sc) static int vtpci_setup_legacy_interrupt(struct vtpci_softc *sc, enum intr_type type) { - device_t dev; - struct vtpci_intr_resource *ires; + struct vtpci_interrupt *intr; int error; - dev = sc->vtpci_dev; - - ires = &sc->vtpci_intr_res[0]; - error = bus_setup_intr(dev, ires->irq, type, NULL, vtpci_legacy_intr, - sc, &ires->intrhand); + intr = &sc->vtpci_device_interrupt; + error = bus_setup_intr(sc->vtpci_dev, intr->vti_irq, type, NULL, + vtpci_legacy_intr, sc, &intr->vti_handler); return (error); } static int -vtpci_setup_msix_interrupts(struct vtpci_softc *sc, enum intr_type type) +vtpci_setup_pervq_msix_interrupts(struct vtpci_softc *sc, enum intr_type type) { - device_t dev; - struct vtpci_intr_resource *ires; struct vtpci_virtqueue *vqx; + struct vtpci_interrupt *intr; int i, error; + intr = sc->vtpci_msix_vq_interrupts; + + for (i = 0; i < sc->vtpci_nvqs; i++) { + vqx = &sc->vtpci_vqs[i]; + + if (vqx->vtv_no_intr) + continue; + + error = bus_setup_intr(sc->vtpci_dev, intr->vti_irq, type, + vtpci_vq_intr_filter, vtpci_vq_intr, vqx->vtv_vq, + &intr->vti_handler); + if (error) + return (error); + + intr++; + } + + return (0); +} + +static int +vtpci_setup_msix_interrupts(struct vtpci_softc *sc, enum intr_type type) +{ + device_t dev; + struct vtpci_interrupt *intr; + int error; + dev = sc->vtpci_dev; + intr = &sc->vtpci_device_interrupt; - /* - * The first MSIX vector is used for configuration changed interrupts. - */ - ires = &sc->vtpci_intr_res[0]; - error = bus_setup_intr(dev, ires->irq, type, NULL, vtpci_config_intr, - sc, &ires->intrhand); + error = bus_setup_intr(dev, intr->vti_irq, type, NULL, + vtpci_config_intr, sc, &intr->vti_handler); if (error) return (error); if (sc->vtpci_flags & VTPCI_FLAG_SHARED_MSIX) { - ires = &sc->vtpci_intr_res[1]; - - error = bus_setup_intr(dev, ires->irq, type, + intr = sc->vtpci_msix_vq_interrupts; + error = bus_setup_intr(dev, intr->vti_irq, type, vtpci_vq_shared_intr_filter, vtpci_vq_shared_intr, sc, - &ires->intrhand); - } else { - for (i = 0; i < sc->vtpci_nvqs; i++) { - vqx = &sc->vtpci_vqx[i]; - if (vqx->ires_idx < 1) - continue; - - ires = &sc->vtpci_intr_res[vqx->ires_idx]; - error = bus_setup_intr(dev, ires->irq, type, - vtpci_vq_intr_filter, vtpci_vq_intr, vqx->vq, - &ires->intrhand); - if (error) - break; - } - } - - if (error == 0) - error = vtpci_set_host_msix_vectors(sc); + &intr->vti_handler); + } else + error = vtpci_setup_pervq_msix_interrupts(sc, type); - return (error); + return (error ? error : vtpci_set_host_msix_vectors(sc)); } static int @@ -990,7 +1007,7 @@ vtpci_setup_interrupts(struct vtpci_softc *sc, enum intr_type type) type |= INTR_MPSAFE; KASSERT(sc->vtpci_flags & VTPCI_FLAG_ITYPE_MASK, - ("no interrupt type selected: %#x", sc->vtpci_flags)); + ("%s: no interrupt type selected %#x", __func__, sc->vtpci_flags)); error = vtpci_alloc_intr_resources(sc); if (error) @@ -1007,34 +1024,24 @@ vtpci_setup_interrupts(struct vtpci_softc *sc, enum intr_type type) } static int -vtpci_register_msix_vector(struct vtpci_softc *sc, int offset, int res_idx) +vtpci_register_msix_vector(struct vtpci_softc *sc, int offset, + struct vtpci_interrupt *intr) { device_t dev; - uint16_t vector, rdvector; + uint16_t vector; dev = sc->vtpci_dev; - if (res_idx != -1) { + if (intr != NULL) { /* Map from guest rid to host vector. */ - vector = sc->vtpci_intr_res[res_idx].rid - 1; + vector = intr->vti_rid - 1; } else vector = VIRTIO_MSI_NO_VECTOR; - /* - * Assert the first resource is always used for the configuration - * changed interrupts. - */ - if (res_idx == 0) { - KASSERT(vector == 0 && offset == VIRTIO_MSI_CONFIG_VECTOR, - ("bad first res use vector:%d offset:%d", vector, offset)); - } else - KASSERT(offset == VIRTIO_MSI_QUEUE_VECTOR, ("bad offset")); - vtpci_write_config_2(sc, offset, vector); /* Read vector to determine if the host had sufficient resources. */ - rdvector = vtpci_read_config_2(sc, offset); - if (rdvector != vector) { + if (vtpci_read_config_2(sc, offset) != vector) { device_printf(dev, "insufficient host resources for MSIX interrupts\n"); return (ENODEV); @@ -1046,24 +1053,40 @@ vtpci_register_msix_vector(struct vtpci_softc *sc, int offset, int res_idx) static int vtpci_set_host_msix_vectors(struct vtpci_softc *sc) { - struct vtpci_virtqueue *vqx; - int idx, error; + struct vtpci_interrupt *intr, *tintr; + int idx, offset, error; - error = vtpci_register_msix_vector(sc, VIRTIO_MSI_CONFIG_VECTOR, 0); + intr = &sc->vtpci_device_interrupt; + offset = VIRTIO_MSI_CONFIG_VECTOR; + + error = vtpci_register_msix_vector(sc, offset, intr); if (error) return (error); - for (idx = 0; idx < sc->vtpci_nvqs; idx++) { - vqx = &sc->vtpci_vqx[idx]; + intr = sc->vtpci_msix_vq_interrupts; + offset = VIRTIO_MSI_QUEUE_VECTOR; + for (idx = 0; idx < sc->vtpci_nvqs; idx++) { vtpci_select_virtqueue(sc, idx); - error = vtpci_register_msix_vector(sc, VIRTIO_MSI_QUEUE_VECTOR, - vqx->ires_idx); + + if (sc->vtpci_vqs[idx].vtv_no_intr) + tintr = NULL; + else + tintr = intr; + + error = vtpci_register_msix_vector(sc, offset, tintr); if (error) - return (error); + break; + + /* + * For shared MSIX, all the virtqueues share the first + * interrupt. + */ + if ((sc->vtpci_flags & VTPCI_FLAG_SHARED_MSIX) == 0) + intr++; } - return (0); + return (error); } static int @@ -1074,10 +1097,10 @@ vtpci_reinit_virtqueue(struct vtpci_softc *sc, int idx) int error; uint16_t size; - vqx = &sc->vtpci_vqx[idx]; - vq = vqx->vq; + vqx = &sc->vtpci_vqs[idx]; + vq = vqx->vtv_vq; - KASSERT(vq != NULL, ("vq %d not allocated", idx)); + KASSERT(vq != NULL, ("%s: vq %d not allocated", __func__, idx)); vtpci_select_virtqueue(sc, idx); size = vtpci_read_config_2(sc, VIRTIO_PCI_QUEUE_NUM); @@ -1093,35 +1116,50 @@ vtpci_reinit_virtqueue(struct vtpci_softc *sc, int idx) } static void -vtpci_free_interrupts(struct vtpci_softc *sc) +vtpci_free_interrupt(struct vtpci_softc *sc, struct vtpci_interrupt *intr) { device_t dev; - struct vtpci_intr_resource *ires; - int i; dev = sc->vtpci_dev; - for (i = 0; i < sc->vtpci_nintr_res; i++) { - ires = &sc->vtpci_intr_res[i]; + if (intr->vti_handler != NULL) { + bus_teardown_intr(dev, intr->vti_irq, intr->vti_handler); + intr->vti_handler = NULL; + } - if (ires->intrhand != NULL) { - bus_teardown_intr(dev, ires->irq, ires->intrhand); - ires->intrhand = NULL; - } + if (intr->vti_irq != NULL) { + bus_release_resource(dev, SYS_RES_IRQ, intr->vti_rid, + intr->vti_irq); + intr->vti_irq = NULL; + intr->vti_rid = -1; + } +} - if (ires->irq != NULL) { - bus_release_resource(dev, SYS_RES_IRQ, ires->rid, - ires->irq); - ires->irq = NULL; - } +static void +vtpci_free_interrupts(struct vtpci_softc *sc) +{ + struct vtpci_interrupt *intr; + int i, nvq_intrs; + + vtpci_free_interrupt(sc, &sc->vtpci_device_interrupt); - ires->rid = -1; + if (sc->vtpci_nmsix_resources != 0) { + nvq_intrs = sc->vtpci_nmsix_resources - 1; + sc->vtpci_nmsix_resources = 0; + + intr = sc->vtpci_msix_vq_interrupts; + if (intr != NULL) { + for (i = 0; i < nvq_intrs; i++, intr++) + vtpci_free_interrupt(sc, intr); + + free(sc->vtpci_msix_vq_interrupts, M_DEVBUF); + sc->vtpci_msix_vq_interrupts = NULL; + } } if (sc->vtpci_flags & (VTPCI_FLAG_MSI | VTPCI_FLAG_MSIX)) - pci_release_msi(dev); + pci_release_msi(sc->vtpci_dev); - sc->vtpci_nintr_res = 0; sc->vtpci_flags &= ~VTPCI_FLAG_ITYPE_MASK; } @@ -1129,19 +1167,32 @@ static void vtpci_free_virtqueues(struct vtpci_softc *sc) { struct vtpci_virtqueue *vqx; - int i; + int idx; - for (i = 0; i < sc->vtpci_nvqs; i++) { - vqx = &sc->vtpci_vqx[i]; + for (idx = 0; idx < sc->vtpci_nvqs; idx++) { + vqx = &sc->vtpci_vqs[idx]; + + vtpci_select_virtqueue(sc, idx); + vtpci_write_config_4(sc, VIRTIO_PCI_QUEUE_PFN, 0); - virtqueue_free(vqx->vq); - vqx->vq = NULL; + virtqueue_free(vqx->vtv_vq); + vqx->vtv_vq = NULL; } + free(sc->vtpci_vqs, M_DEVBUF); + sc->vtpci_vqs = NULL; sc->vtpci_nvqs = 0; } static void +vtpci_release_child_resources(struct vtpci_softc *sc) +{ + + vtpci_free_interrupts(sc); + vtpci_free_virtqueues(sc); +} + +static void vtpci_cleanup_setup_intr_attempt(struct vtpci_softc *sc) { int idx; @@ -1161,14 +1212,6 @@ vtpci_cleanup_setup_intr_attempt(struct vtpci_softc *sc) } static void -vtpci_release_child_resources(struct vtpci_softc *sc) -{ - - vtpci_free_interrupts(sc); - vtpci_free_virtqueues(sc); -} - -static void vtpci_reset(struct vtpci_softc *sc) { @@ -1195,7 +1238,7 @@ vtpci_legacy_intr(void *xsc) uint8_t isr; sc = xsc; - vqx = &sc->vtpci_vqx[0]; + vqx = &sc->vtpci_vqs[0]; /* Reading the ISR also clears it. */ isr = vtpci_read_config_1(sc, VIRTIO_PCI_ISR); @@ -1204,8 +1247,10 @@ vtpci_legacy_intr(void *xsc) vtpci_config_intr(sc); if (isr & VIRTIO_PCI_ISR_INTR) { - for (i = 0; i < sc->vtpci_nvqs; i++, vqx++) - virtqueue_intr(vqx->vq); + for (i = 0; i < sc->vtpci_nvqs; i++, vqx++) { + if (vqx->vtv_no_intr == 0) + virtqueue_intr(vqx->vtv_vq); + } } } @@ -1218,10 +1263,12 @@ vtpci_vq_shared_intr_filter(void *xsc) rc = 0; sc = xsc; - vqx = &sc->vtpci_vqx[0]; + vqx = &sc->vtpci_vqs[0]; - for (i = 0; i < sc->vtpci_nvqs; i++, vqx++) - rc |= virtqueue_intr_filter(vqx->vq); + for (i = 0; i < sc->vtpci_nvqs; i++, vqx++) { + if (vqx->vtv_no_intr == 0) + rc |= virtqueue_intr_filter(vqx->vtv_vq); + } return (rc ? FILTER_SCHEDULE_THREAD : FILTER_STRAY); } @@ -1234,10 +1281,12 @@ vtpci_vq_shared_intr(void *xsc) int i; sc = xsc; - vqx = &sc->vtpci_vqx[0]; + vqx = &sc->vtpci_vqs[0]; - for (i = 0; i < sc->vtpci_nvqs; i++, vqx++) - virtqueue_intr(vqx->vq); + for (i = 0; i < sc->vtpci_nvqs; i++, vqx++) { + if (vqx->vtv_no_intr == 0) + virtqueue_intr(vqx->vtv_vq); + } } static int diff --git a/sys/dev/virtio/virtio.h b/sys/dev/virtio/virtio.h index e201640..b1334f8 100644 --- a/sys/dev/virtio/virtio.h +++ b/sys/dev/virtio/virtio.h @@ -71,11 +71,6 @@ struct vq_alloc_info; #define VIRTIO_TRANSPORT_F_END 32 /* - * Maximum number of virtqueues per device. - */ -#define VIRTIO_MAX_VIRTQUEUES 8 - -/* * Each virtqueue indirect descriptor list must be physically contiguous. * To allow us to malloc(9) each list individually, limit the number * supported to what will fit in one page. With 4KB pages, this is a limit diff --git a/sys/dev/virtio/virtqueue.c b/sys/dev/virtio/virtqueue.c index 88ce577..a82426e 100644 --- a/sys/dev/virtio/virtqueue.c +++ b/sys/dev/virtio/virtqueue.c @@ -417,8 +417,6 @@ int virtqueue_intr_filter(struct virtqueue *vq) { - if (__predict_false(vq->vq_intrhand == NULL)) - return (0); if (vq->vq_used_cons_idx == vq->vq_ring.used->idx) return (0); @@ -431,8 +429,7 @@ void virtqueue_intr(struct virtqueue *vq) { - if (__predict_true(vq->vq_intrhand != NULL)) - vq->vq_intrhand(vq->vq_intrhand_arg); + vq->vq_intrhand(vq->vq_intrhand_arg); } int |