1
0
mirror of https://github.com/openbsd/src.git synced 2024-12-21 23:18:00 -08:00

virtio: Refactor attach logic

virtio 1.x requires that all queue setup, including the queue interrupt
vector, is done before setting the queue_enable register to 1. This
conflicts with how we do things right now:

* We implicitly make queue setup in virtio_alloc_vq(), which is called
  from the child driver attach functions. This also sets queue_enable=1.

* Later, we allocate the interrupts and set the queue interrupt vectors
  in the second half of the virtio transport attach functions.

This is a violation of a MUST from the standard and causes problems with
some hypervisors, in particular those that have no virtio 0.9 support,
which has no such ordering requirements.

To fix this:

* Move the interrupt allocation to a new virtio_attach_finish() function.
  This does all queue setup, including the interrupt vectors.

* Don't call virtio_setup_queue() in virtio_alloc_vq() anymore.

* We can also move the setting of the DRIVER_OK flag into this function.
  virtio_attach_finish() must be called before using any virtqueue or
  writing any virtio config register.

While there,

* also streamline the attach error handling in all drivers.

* skip initially setting sc_config_change to NULL, the softc is
  initialized to 0.

ok jan@
tested by bluhm@
This commit is contained in:
sf 2024-12-20 22:18:27 +00:00
parent 7aa20da420
commit 77d0f8231d
12 changed files with 156 additions and 82 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: virtio_mmio.c,v 1.20 2024/12/03 19:14:40 sf Exp $ */
/* $OpenBSD: virtio_mmio.c,v 1.21 2024/12/20 22:18:27 sf Exp $ */
/* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */
/*
@ -98,6 +98,7 @@ void virtio_mmio_write_device_config_8(struct virtio_softc *, int, uint64_t);
uint16_t virtio_mmio_read_queue_size(struct virtio_softc *, uint16_t);
void virtio_mmio_setup_queue(struct virtio_softc *, struct virtqueue *, uint64_t);
void virtio_mmio_setup_intrs(struct virtio_softc *);
int virtio_mmio_attach_finish(struct virtio_softc *, struct virtio_attach_args *);
int virtio_mmio_get_status(struct virtio_softc *);
void virtio_mmio_set_status(struct virtio_softc *, int);
int virtio_mmio_negotiate_features(struct virtio_softc *,
@ -119,6 +120,11 @@ struct virtio_mmio_softc {
uint32_t sc_version;
};
struct virtio_mmio_attach_args {
struct virtio_attach_args vma_va;
struct fdt_attach_args *vma_fa;
};
const struct cfattach virtio_mmio_ca = {
sizeof(struct virtio_mmio_softc),
virtio_mmio_match,
@ -151,6 +157,7 @@ const struct virtio_ops virtio_mmio_ops = {
virtio_mmio_get_status,
virtio_mmio_set_status,
virtio_mmio_negotiate_features,
virtio_mmio_attach_finish,
virtio_mmio_intr,
virtio_mmio_intr_barrier,
};
@ -250,7 +257,7 @@ virtio_mmio_attach(struct device *parent, struct device *self, void *aux)
struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)self;
struct virtio_softc *vsc = &sc->sc_sc;
uint32_t id, magic;
struct virtio_attach_args va = { 0 };
struct virtio_mmio_attach_args vma = { { 0 }, faa };
if (faa->fa_nreg < 1) {
printf(": no register data\n");
@ -299,38 +306,45 @@ virtio_mmio_attach(struct device *parent, struct device *self, void *aux)
virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
virtio_mmio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER);
va.va_devid = id;
va.va_nintr = 1;
vma.vma_va.va_devid = id;
vma.vma_va.va_nintr = 1;
vsc->sc_child = NULL;
config_found(self, &va, NULL);
config_found(self, &vma, NULL);
if (vsc->sc_child == NULL) {
printf("%s: no matching child driver; not configured\n",
vsc->sc_dev.dv_xname);
goto fail_1;
goto fail;
}
if (vsc->sc_child == VIRTIO_CHILD_ERROR) {
printf("%s: virtio configuration failed\n",
vsc->sc_dev.dv_xname);
goto fail_1;
}
sc->sc_ih = fdt_intr_establish(faa->fa_node, vsc->sc_ipl,
virtio_mmio_intr, sc, vsc->sc_dev.dv_xname);
if (sc->sc_ih == NULL) {
printf("%s: couldn't establish interrupt\n",
vsc->sc_dev.dv_xname);
goto fail_2;
goto fail;
}
return;
fail_2:
config_detach(vsc->sc_child, 0);
fail_1:
/* no mmio_mapreg_unmap() or mmio_intr_unmap() */
fail:
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
}
int
virtio_mmio_attach_finish(struct virtio_softc *vsc,
struct virtio_attach_args *va)
{
struct virtio_mmio_softc *sc = (struct virtio_mmio_softc *)vsc;
struct virtio_mmio_attach_args *vma =
(struct virtio_mmio_attach_args *)va;
sc->sc_ih = fdt_intr_establish(vma->vma_fa->fa_node, vsc->sc_ipl,
virtio_mmio_intr, sc, vsc->sc_dev.dv_xname);
if (sc->sc_ih == NULL) {
printf("%s: couldn't establish interrupt\n",
vsc->sc_dev.dv_xname);
return -EIO;
}
return 0;
}
int
virtio_mmio_detach(struct device *self, int flags)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: virtio_pci.c,v 1.47 2024/12/03 19:14:40 sf Exp $ */
/* $OpenBSD: virtio_pci.c,v 1.48 2024/12/20 22:18:27 sf Exp $ */
/* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */
/*
@ -74,6 +74,7 @@ void virtio_pci_write_device_config_8(struct virtio_softc *, int, uint64_t);
uint16_t virtio_pci_read_queue_size(struct virtio_softc *, uint16_t);
void virtio_pci_setup_queue(struct virtio_softc *, struct virtqueue *, uint64_t);
void virtio_pci_setup_intrs(struct virtio_softc *);
int virtio_pci_attach_finish(struct virtio_softc *, struct virtio_attach_args *);
int virtio_pci_get_status(struct virtio_softc *);
void virtio_pci_set_status(struct virtio_softc *, int);
int virtio_pci_negotiate_features(struct virtio_softc *, const struct virtio_feature_name *);
@ -175,6 +176,7 @@ const struct virtio_ops virtio_pci_ops = {
virtio_pci_get_status,
virtio_pci_set_status,
virtio_pci_negotiate_features,
virtio_pci_attach_finish,
virtio_pci_poll_intr,
virtio_pci_intr_barrier,
};
@ -592,8 +594,6 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
pcitag_t tag = pa->pa_tag;
int revision, ret = ENODEV;
pcireg_t id;
char const *intrstr;
pci_intr_handle_t ih;
struct virtio_pci_attach_args vpa = { { 0 }, pa };
revision = PCI_REVISION(pa->pa_class);
@ -645,13 +645,13 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
}
if (ret != 0) {
printf(": Cannot attach (%d)\n", ret);
goto fail_0;
goto free;
}
sc->sc_devcfg_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI;
sc->sc_irq_type = IRQ_NO_MSIX;
if (virtio_pci_adjust_config_region(sc) != 0)
goto fail_0;
goto err;
virtio_device_reset(vsc);
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
@ -664,25 +664,47 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
if (vsc->sc_child == NULL) {
printf("%s: no matching child driver; not configured\n",
vsc->sc_dev.dv_xname);
goto fail_1;
goto err;
}
if (vsc->sc_child == VIRTIO_CHILD_ERROR) {
printf("%s: virtio configuration failed\n",
vsc->sc_dev.dv_xname);
goto fail_1;
goto err;
}
if (virtio_pci_setup_msix(sc, &vpa, 0) == 0) {
return;
err:
/* no pci_mapreg_unmap() or pci_intr_unmap() */
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_FAILED);
free:
free(sc->sc_intr, M_DEVBUF, sc->sc_nintr * sizeof(*sc->sc_intr));
}
int
virtio_pci_attach_finish(struct virtio_softc *vsc,
struct virtio_attach_args *va)
{
struct virtio_pci_softc *sc = (struct virtio_pci_softc *)vsc;
struct virtio_pci_attach_args *vpa =
(struct virtio_pci_attach_args *)va;
pci_intr_handle_t ih;
pci_chipset_tag_t pc = vpa->vpa_pa->pa_pc;
char const *intrstr;
if (virtio_pci_setup_msix(sc, vpa, 0) == 0) {
sc->sc_irq_type = IRQ_MSIX_PER_VQ;
intrstr = "msix per-VQ";
} else if (virtio_pci_setup_msix(sc, &vpa, 1) == 0) {
} else if (virtio_pci_setup_msix(sc, vpa, 1) == 0) {
sc->sc_irq_type = IRQ_MSIX_SHARED;
intrstr = "msix shared";
} else {
int (*ih_func)(void *) = virtio_pci_legacy_intr;
if (pci_intr_map_msi(pa, &ih) != 0 && pci_intr_map(pa, &ih) != 0) {
printf("%s: couldn't map interrupt\n", vsc->sc_dev.dv_xname);
goto fail_2;
if (pci_intr_map_msi(vpa->vpa_pa, &ih) != 0 &&
pci_intr_map(vpa->vpa_pa, &ih) != 0) {
printf("%s: couldn't map interrupt\n",
vsc->sc_dev.dv_xname);
return -EIO;
}
intrstr = pci_intr_string(pc, ih);
/*
@ -696,25 +718,17 @@ virtio_pci_attach(struct device *parent, struct device *self, void *aux)
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);
printf("%s: couldn't establish interrupt",
vsc->sc_dev.dv_xname);
if (intrstr != NULL)
printf(" at %s", intrstr);
printf("\n");
goto fail_2;
return -EIO;
}
}
virtio_pci_setup_intrs(vsc);
printf("%s: %s\n", vsc->sc_dev.dv_xname, intrstr);
return;
fail_2:
config_detach(vsc->sc_child, 0);
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));
return 0;
}
int

View File

@ -1,4 +1,4 @@
/* $OpenBSD: if_vio.c,v 1.61 2024/12/03 19:14:40 sf Exp $ */
/* $OpenBSD: if_vio.c,v 1.62 2024/12/20 22:18:27 sf Exp $ */
/*
* Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg.
@ -597,6 +597,7 @@ vio_attach(struct device *parent, struct device *self, void *aux)
{
struct vio_softc *sc = (struct vio_softc *)self;
struct virtio_softc *vsc = (struct virtio_softc *)parent;
struct virtio_attach_args *va = aux;
int i, tx_max_segments;
struct ifnet *ifp = &sc->sc_ac.ac_if;
@ -610,7 +611,6 @@ vio_attach(struct device *parent, struct device *self, void *aux)
vsc->sc_child = self;
vsc->sc_ipl = IPL_NET | IPL_MPSAFE;
vsc->sc_config_change = NULL;
vsc->sc_driver_features = VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS |
VIRTIO_NET_F_CTRL_VQ | VIRTIO_NET_F_CTRL_RX |
VIRTIO_NET_F_MRG_RXBUF | VIRTIO_NET_F_CSUM |
@ -623,7 +623,8 @@ vio_attach(struct device *parent, struct device *self, void *aux)
vsc->sc_driver_features |= VIRTIO_NET_F_GUEST_TSO4;
vsc->sc_driver_features |= VIRTIO_NET_F_GUEST_TSO6;
virtio_negotiate_features(vsc, virtio_net_feature_names);
if (virtio_negotiate_features(vsc, virtio_net_feature_names) != 0)
goto err;
sc->sc_nqueues = 1;
vsc->sc_nvqs = 2 * sc->sc_nqueues;
@ -756,7 +757,9 @@ vio_attach(struct device *parent, struct device *self, void *aux)
timeout_set(&sc->sc_txtick, vio_txtick, sc);
timeout_set(&sc->sc_rxtick, vio_rxtick, sc);
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
if (virtio_attach_finish(vsc, va) != 0)
goto err;
if_attach(ifp);
ether_ifattach(ifp);
vio_link_state(ifp);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: vioblk.c,v 1.43 2024/08/27 18:44:12 sf Exp $ */
/* $OpenBSD: vioblk.c,v 1.44 2024/12/20 22:18:27 sf Exp $ */
/*
* Copyright (c) 2012 Stefan Fritsch.
@ -170,12 +170,12 @@ vioblk_attach(struct device *parent, struct device *self, void *aux)
{
struct vioblk_softc *sc = (struct vioblk_softc *)self;
struct virtio_softc *vsc = (struct virtio_softc *)parent;
struct virtio_attach_args *va = aux;
struct scsibus_attach_args saa;
int qsize;
vsc->sc_vqs = &sc->sc_vq[0];
vsc->sc_nvqs = 1;
vsc->sc_config_change = NULL;
if (vsc->sc_child)
panic("already attached to something else");
vsc->sc_child = self;
@ -184,7 +184,8 @@ vioblk_attach(struct device *parent, struct device *self, void *aux)
vsc->sc_driver_features = VIRTIO_BLK_F_RO | VIRTIO_F_NOTIFY_ON_EMPTY |
VIRTIO_BLK_F_SIZE_MAX | VIRTIO_BLK_F_SEG_MAX | VIRTIO_BLK_F_FLUSH;
virtio_negotiate_features(vsc, vioblk_feature_names);
if (virtio_negotiate_features(vsc, vioblk_feature_names) != 0)
goto err;
if (virtio_has_feature(vsc, VIRTIO_BLK_F_SIZE_MAX)) {
uint32_t size_max = virtio_read_device_config_4(vsc,
@ -252,10 +253,11 @@ vioblk_attach(struct device *parent, struct device *self, void *aux)
saa.saa_quirks = 0;
saa.saa_wwpn = saa.saa_wwnn = 0;
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
if (virtio_attach_finish(vsc, va) != 0)
goto err;
config_found(self, &saa, scsiprint);
return;
err:
vsc->sc_child = VIRTIO_CHILD_ERROR;
return;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: viocon.c,v 1.15 2024/08/27 18:44:12 sf Exp $ */
/* $OpenBSD: viocon.c,v 1.16 2024/12/20 22:18:27 sf Exp $ */
/*
* Copyright (c) 2013-2015 Stefan Fritsch <sf@sfritsch.de>
@ -179,7 +179,6 @@ viocon_attach(struct device *parent, struct device *self, void *aux)
panic("already attached to something else");
vsc->sc_child = self;
vsc->sc_ipl = IPL_TTY;
vsc->sc_config_change = NULL;
sc->sc_virtio = vsc;
sc->sc_max_ports = maxports;
@ -193,7 +192,8 @@ viocon_attach(struct device *parent, struct device *self, void *aux)
}
vsc->sc_driver_features = VIRTIO_CONSOLE_F_SIZE;
virtio_negotiate_features(vsc, viocon_feature_names);
if (virtio_negotiate_features(vsc, viocon_feature_names) != 0)
goto err;
printf("\n");
DPRINTF("%s: softc: %p\n", __func__, sc);
@ -201,10 +201,11 @@ viocon_attach(struct device *parent, struct device *self, void *aux)
printf("\n%s: viocon_port_create failed\n", __func__);
goto err;
}
if (virtio_attach_finish(vsc, va) != 0)
goto err;
viocon_rx_fill(sc->sc_ports[0]);
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
return;
err:
vsc->sc_child = VIRTIO_CHILD_ERROR;
free(vsc->sc_vqs, M_DEVBUF, 2 * (maxports + 1) * sizeof(struct virtqueue));

View File

@ -1,4 +1,4 @@
/* $OpenBSD: viogpu.c,v 1.10 2024/11/04 15:43:10 sf Exp $ */
/* $OpenBSD: viogpu.c,v 1.11 2024/12/20 22:18:27 sf Exp $ */
/*
* Copyright (c) 2021-2023 joshua stein <jcs@openbsd.org>
@ -150,6 +150,7 @@ viogpu_attach(struct device *parent, struct device *self, void *aux)
{
struct viogpu_softc *sc = (struct viogpu_softc *)self;
struct virtio_softc *vsc = (struct virtio_softc *)parent;
struct virtio_attach_args *va = aux;
struct wsemuldisplaydev_attach_args waa;
struct rasops_info *ri = &sc->sc_ri;
uint32_t defattr;
@ -161,10 +162,11 @@ viogpu_attach(struct device *parent, struct device *self, void *aux)
}
vsc->sc_child = self;
virtio_negotiate_features(vsc, viogpu_feature_names);
if (virtio_negotiate_features(vsc, viogpu_feature_names) != 0)
goto err;
if (!vsc->sc_version_1) {
printf(": requires virtio version 1\n");
return;
goto err;
}
vsc->sc_ipl = IPL_TTY;
@ -175,13 +177,13 @@ viogpu_attach(struct device *parent, struct device *self, void *aux)
vsc->sc_vqs = sc->sc_vqs;
if (virtio_alloc_vq(vsc, &sc->sc_vqs[VQCTRL], VQCTRL, 1, "control")) {
printf(": alloc_vq failed\n");
return;
goto err;
}
sc->sc_vqs[VQCTRL].vq_done = viogpu_vq_done;
if (virtio_alloc_vq(vsc, &sc->sc_vqs[VQCURS], VQCURS, 1, "cursor")) {
printf(": alloc_vq failed\n");
return;
goto err;
}
vsc->sc_nvqs = nitems(sc->sc_vqs);
@ -191,7 +193,7 @@ viogpu_attach(struct device *parent, struct device *self, void *aux)
sc->sc_dma_size, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
&sc->sc_dma_map) != 0) {
printf(": create failed");
goto err;
goto errdma;
}
if (bus_dmamem_alloc(vsc->sc_dmat, sc->sc_dma_size, 16, 0,
&sc->sc_dma_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0) {
@ -209,7 +211,8 @@ viogpu_attach(struct device *parent, struct device *self, void *aux)
goto unmap;
}
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
if (virtio_attach_finish(vsc, va) != 0)
goto unmap;
if (viogpu_get_display_info(sc) != 0)
goto unmap;
@ -302,8 +305,10 @@ free:
bus_dmamem_free(vsc->sc_dmat, &sc->sc_dma_seg, 1);
destroy:
bus_dmamap_destroy(vsc->sc_dmat, sc->sc_dma_map);
err:
errdma:
printf(": DMA setup failed\n");
err:
vsc->sc_child = VIRTIO_CHILD_ERROR;
return;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: viomb.c,v 1.12 2024/08/27 18:44:12 sf Exp $ */
/* $OpenBSD: viomb.c,v 1.13 2024/12/20 22:18:27 sf Exp $ */
/* $NetBSD: viomb.c,v 1.1 2011/10/30 12:12:21 hannken Exp $ */
/*
@ -135,6 +135,7 @@ viomb_attach(struct device *parent, struct device *self, void *aux)
{
struct viomb_softc *sc = (struct viomb_softc *)self;
struct virtio_softc *vsc = (struct virtio_softc *)parent;
struct virtio_attach_args *va = aux;
int i;
if (vsc->sc_child != NULL) {
@ -219,8 +220,10 @@ viomb_attach(struct device *parent, struct device *self, void *aux)
sensordev_install(&sc->sc_sensdev);
printf("\n");
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
if (virtio_attach_finish(vsc, va) != 0)
goto err_dmamap;
return;
err_dmamap:
bus_dmamap_destroy(vsc->sc_dmat, sc->sc_req.bl_dmamap);
err:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: viornd.c,v 1.11 2024/08/27 18:44:12 sf Exp $ */
/* $OpenBSD: viornd.c,v 1.12 2024/12/20 22:18:27 sf Exp $ */
/*
* Copyright (c) 2014 Stefan Fritsch <sf@sfritsch.de>
@ -83,18 +83,19 @@ viornd_attach(struct device *parent, struct device *self, void *aux)
{
struct viornd_softc *sc = (struct viornd_softc *)self;
struct virtio_softc *vsc = (struct virtio_softc *)parent;
struct virtio_attach_args *va = aux;
unsigned int shift;
vsc->sc_vqs = &sc->sc_vq;
vsc->sc_nvqs = 1;
vsc->sc_config_change = NULL;
if (vsc->sc_child != NULL)
panic("already attached to something else");
vsc->sc_child = self;
vsc->sc_ipl = IPL_NET;
sc->sc_virtio = vsc;
virtio_negotiate_features(vsc, NULL);
if (virtio_negotiate_features(vsc, NULL) != 0)
goto err;
if (sc->sc_dev.dv_cfdata->cf_flags & VIORND_ONESHOT) {
sc->sc_interval = 0;
@ -136,7 +137,8 @@ viornd_attach(struct device *parent, struct device *self, void *aux)
timeout_add(&sc->sc_tick, 1);
printf("\n");
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
if (virtio_attach_finish(vsc, va) != 0)
goto err2;
return;
err2:
bus_dmamap_destroy(vsc->sc_dmat, sc->sc_dmamap);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: vioscsi.c,v 1.34 2024/08/27 18:44:12 sf Exp $ */
/* $OpenBSD: vioscsi.c,v 1.35 2024/12/20 22:18:27 sf Exp $ */
/*
* Copyright (c) 2013 Google Inc.
*
@ -105,6 +105,7 @@ vioscsi_attach(struct device *parent, struct device *self, void *aux)
{
struct virtio_softc *vsc = (struct virtio_softc *)parent;
struct vioscsi_softc *sc = (struct vioscsi_softc *)self;
struct virtio_attach_args *va = aux;
struct scsibus_attach_args saa;
int i, rv;
@ -120,7 +121,8 @@ vioscsi_attach(struct device *parent, struct device *self, void *aux)
vsc->sc_vqs = sc->sc_vqs;
vsc->sc_nvqs = nitems(sc->sc_vqs);
virtio_negotiate_features(vsc, NULL);
if (virtio_negotiate_features(vsc, NULL) != 0)
goto err;
uint32_t cmd_per_lun = virtio_read_device_config_4(vsc,
VIRTIO_SCSI_CONFIG_CMD_PER_LUN);
uint32_t seg_max = virtio_read_device_config_4(vsc,
@ -166,7 +168,8 @@ vioscsi_attach(struct device *parent, struct device *self, void *aux)
saa.saa_quirks = saa.saa_flags = 0;
saa.saa_wwpn = saa.saa_wwnn = 0;
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
if (virtio_attach_finish(vsc, va) != 0)
goto err;
config_found(self, &saa, scsiprint);
return;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: virtio.c,v 1.35 2024/12/03 19:14:40 sf Exp $ */
/* $OpenBSD: virtio.c,v 1.36 2024/12/20 22:18:27 sf Exp $ */
/* $NetBSD: virtio.c,v 1.3 2011/11/02 23:05:52 njoly Exp $ */
/*
@ -154,6 +154,25 @@ virtio_reset(struct virtio_softc *sc)
sc->sc_active_features = 0;
}
int
virtio_attach_finish(struct virtio_softc *sc, struct virtio_attach_args *va)
{
int i, ret;
ret = sc->sc_ops->attach_finish(sc, va);
if (ret != 0)
return ret;
sc->sc_ops->setup_intrs(sc);
for (i = 0; i < sc->sc_nvqs; i++) {
struct virtqueue *vq = &sc->sc_vqs[i];
virtio_setup_queue(sc, vq, vq->vq_dmamap->dm_segs[0].ds_addr);
}
virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
return 0;
}
void
virtio_reinit_start(struct virtio_softc *sc)
{
@ -162,6 +181,7 @@ virtio_reinit_start(struct virtio_softc *sc)
virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_ACK);
virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER);
virtio_negotiate_features(sc, NULL);
sc->sc_ops->setup_intrs(sc);
for (i = 0; i < sc->sc_nvqs; i++) {
int n;
struct virtqueue *vq = &sc->sc_vqs[i];
@ -175,7 +195,6 @@ virtio_reinit_start(struct virtio_softc *sc)
virtio_init_vq(sc, vq);
virtio_setup_queue(sc, vq, vq->vq_dmamap->dm_segs[0].ds_addr);
}
sc->sc_ops->setup_intrs(sc);
}
void
@ -421,7 +440,6 @@ virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int index,
}
virtio_init_vq(sc, vq);
virtio_setup_queue(sc, vq, vq->vq_dmamap->dm_segs[0].ds_addr);
#if VIRTIO_DEBUG
printf("\nallocated %u byte for virtqueue %d for %s, size %d\n",

View File

@ -1,4 +1,4 @@
/* $OpenBSD: virtiovar.h,v 1.25 2024/12/03 19:14:40 sf Exp $ */
/* $OpenBSD: virtiovar.h,v 1.26 2024/12/20 22:18:27 sf Exp $ */
/* $NetBSD: virtiovar.h,v 1.1 2011/10/30 12:12:21 hannken Exp $ */
/*
@ -161,6 +161,7 @@ struct virtio_ops {
int (*get_status)(struct virtio_softc *);
void (*set_status)(struct virtio_softc *, int);
int (*neg_features)(struct virtio_softc *, const struct virtio_feature_name *);
int (*attach_finish)(struct virtio_softc *, struct virtio_attach_args *);
int (*poll_intr)(void *);
void (*intr_barrier)(struct virtio_softc *);
};
@ -220,6 +221,7 @@ virtio_has_feature(struct virtio_softc *sc, uint64_t fbit)
int virtio_alloc_vq(struct virtio_softc*, struct virtqueue*, int, int,
const char*);
int virtio_free_vq(struct virtio_softc*, struct virtqueue*);
int virtio_attach_finish(struct virtio_softc *, struct virtio_attach_args *);
void virtio_reset(struct virtio_softc *);
void virtio_reinit_start(struct virtio_softc *);
void virtio_reinit_end(struct virtio_softc *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: vmmci.c,v 1.12 2024/08/26 19:37:54 sf Exp $ */
/* $OpenBSD: vmmci.c,v 1.13 2024/12/20 22:18:27 sf Exp $ */
/*
* Copyright (c) 2017 Reyk Floeter <reyk@openbsd.org>
@ -89,6 +89,7 @@ vmmci_attach(struct device *parent, struct device *self, void *aux)
{
struct vmmci_softc *sc = (struct vmmci_softc *)self;
struct virtio_softc *vsc = (struct virtio_softc *)parent;
struct virtio_attach_args *va = aux;
if (vsc->sc_child != NULL)
panic("already attached to something else");
@ -101,7 +102,8 @@ vmmci_attach(struct device *parent, struct device *self, void *aux)
vsc->sc_driver_features = VMMCI_F_TIMESYNC | VMMCI_F_ACK |
VMMCI_F_SYNCRTC;
virtio_negotiate_features(vsc, NULL);
if (virtio_negotiate_features(vsc, NULL) != 0)
goto err;
if (virtio_has_feature(vsc, VMMCI_F_TIMESYNC)) {
strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
@ -115,7 +117,12 @@ vmmci_attach(struct device *parent, struct device *self, void *aux)
}
printf("\n");
virtio_set_status(vsc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
if (virtio_attach_finish(vsc, va) != 0)
goto err;
return;
err:
vsc->sc_child = VIRTIO_CHILD_ERROR;
}
int