summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/virtio_pci.c51
1 files changed, 33 insertions, 18 deletions
diff --git a/sys/dev/pci/virtio_pci.c b/sys/dev/pci/virtio_pci.c
index f7b2acda17b..fe137db8632 100644
--- a/sys/dev/pci/virtio_pci.c
+++ b/sys/dev/pci/virtio_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: virtio_pci.c,v 1.40 2024/08/27 19:01:11 sf Exp $ */
+/* $OpenBSD: virtio_pci.c,v 1.41 2024/09/02 08:22:08 sf Exp $ */
/* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */
/*
@@ -99,6 +99,11 @@ enum irq_type {
IRQ_MSIX_PER_VQ, /* vec 0: config irq, vec n: irq of vq[n-1] */
};
+struct virtio_pci_intr {
+ char name[16];
+ void *ih;
+};
+
struct virtio_pci_softc {
struct virtio_softc sc_sc;
pci_chipset_tag_t sc_pc;
@@ -132,7 +137,8 @@ struct virtio_pci_softc {
bus_space_handle_t sc_isr_ioh;
bus_size_t sc_isr_iosize;
- void *sc_ih[MAX_MSIX_VECS];
+ struct virtio_pci_intr *sc_intr;
+ int sc_nintr;
enum irq_type sc_irq_type;
};
@@ -585,7 +591,6 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
char const *intrstr;
pci_intr_handle_t ih;
struct virtio_pci_attach_args vpa = { { 0 }, pa };
- int n;
revision = PCI_REVISION(pa->pa_class);
switch (revision) {
@@ -617,9 +622,12 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
virtio_pci_dump_caps(sc);
#endif
- n = MIN(MAX_MSIX_VECS, pci_intr_msix_count(pa));
- n = MAX(n, 1);
- vpa.vpa_va.va_nintr = n;
+ sc->sc_nintr = min(MAX_MSIX_VECS, pci_intr_msix_count(pa));
+ sc->sc_nintr = max(sc->sc_nintr, 1);
+ vpa.vpa_va.va_nintr = sc->sc_nintr;
+
+ sc->sc_intr = mallocarray(sc->sc_nintr, sizeof(*sc->sc_intr),
+ M_DEVBUF, M_WAITOK | M_ZERO);
vsc->sc_ops = &virtio_pci_ops;
if ((vsc->sc_dev.dv_cfdata->cf_flags & VIRTIO_CF_NO_VERSION_1) == 0 &&
@@ -633,13 +641,13 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
}
if (ret != 0) {
printf(": Cannot attach (%d)\n", ret);
- return;
+ goto fail_0;
}
sc->sc_devcfg_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI;
sc->sc_irq_type = IRQ_NO_MSIX;
if (virtio_pci_adjust_config_region(sc) != 0)
- return;
+ goto fail_0;
virtio_device_reset(vsc);
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
@@ -680,9 +688,10 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
*/
if (vsc->sc_ipl & IPL_MPSAFE)
ih_func = virtio_pci_legacy_intr_mpsafe;
- sc->sc_ih[0] = pci_intr_establish(pc, ih, vsc->sc_ipl | IPL_MPSAFE,
- ih_func, sc, vsc->sc_dev.dv_xname);
- if (sc->sc_ih[0] == NULL) {
+ sc->sc_intr[0].ih = pci_intr_establish(pc, ih,
+ vsc->sc_ipl | IPL_MPSAFE, ih_func, sc,
+ vsc->sc_child->dv_xname);
+ if (sc->sc_intr[0].ih == NULL) {
printf("%s: couldn't establish interrupt", vsc->sc_dev.dv_xname);
if (intrstr != NULL)
printf(" at %s", intrstr);
@@ -699,6 +708,8 @@ fail_2:
fail_1:
/* no pci_mapreg_unmap() or pci_intr_unmap() */
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
+fail_0:
+ free(sc->sc_intr, M_DEVBUF, sc->sc_nintr * sizeof(*sc->sc_intr));
}
int
@@ -929,6 +940,8 @@ virtio_pci_msix_establish(struct virtio_pci_softc *sc,
struct virtio_softc *vsc = &sc->sc_sc;
pci_intr_handle_t ih;
+ KASSERT(idx < sc->sc_nintr);
+
if (pci_intr_map_msix(vpa->vpa_pa, idx, &ih) != 0) {
#if VIRTIO_DEBUG
printf("%s[%d]: pci_intr_map_msix failed\n",
@@ -936,9 +949,11 @@ virtio_pci_msix_establish(struct virtio_pci_softc *sc,
#endif
return 1;
}
- sc->sc_ih[idx] = pci_intr_establish(sc->sc_pc, ih, vsc->sc_ipl,
- handler, ih_arg, vsc->sc_dev.dv_xname);
- if (sc->sc_ih[idx] == NULL) {
+ snprintf(sc->sc_intr[idx].name, sizeof(sc->sc_intr[idx].name), "%s:%d",
+ vsc->sc_child->dv_xname, idx);
+ sc->sc_intr[idx].ih = pci_intr_establish(sc->sc_pc, ih, vsc->sc_ipl,
+ handler, ih_arg, sc->sc_intr[idx].name);
+ if (sc->sc_intr[idx].ih == NULL) {
printf("%s[%d]: couldn't establish msix interrupt\n",
vsc->sc_dev.dv_xname, idx);
return 1;
@@ -985,10 +1000,10 @@ virtio_pci_free_irqs(struct virtio_pci_softc *sc)
}
}
- for (i = 0; i < MAX_MSIX_VECS; i++) {
- if (sc->sc_ih[i]) {
- pci_intr_disestablish(sc->sc_pc, sc->sc_ih[i]);
- sc->sc_ih[i] = NULL;
+ for (i = 0; i < sc->sc_nintr; i++) {
+ if (sc->sc_intr[i].ih) {
+ pci_intr_disestablish(sc->sc_pc, sc->sc_intr[i].ih);
+ sc->sc_intr[i].ih = NULL;
}
}