Download raw body.
virtio: Support unused virtqueues
On Tue, Jan 07, 2025 at 09:09:30AM +0100, Stefan Fritsch wrote:
> Hi,
>
> another small preparatory diff that we will need for vio(4) multiqueue, if
> the hypervisor offers more packet queues than we want to use. The control
> queue comes after the packet queues.
>
> ok?
I have tested it. OK bluhm@
> Cheers,
> Stefan
>
>
> diff --git a/sys/dev/pv/virtio.c b/sys/dev/pv/virtio.c
> index 69eb26386ba..2d0c2386b87 100644
> --- a/sys/dev/pv/virtio.c
> +++ b/sys/dev/pv/virtio.c
> @@ -167,6 +167,8 @@ virtio_attach_finish(struct virtio_softc *sc, struct virtio_attach_args *va)
> for (i = 0; i < sc->sc_nvqs; i++) {
> struct virtqueue *vq = &sc->sc_vqs[i];
>
> + if (vq->vq_num == 0)
> + continue;
> virtio_setup_queue(sc, vq, vq->vq_dmamap->dm_segs[0].ds_addr);
> }
> virtio_set_status(sc, VIRTIO_CONFIG_DEVICE_STATUS_DRIVER_OK);
> @@ -185,9 +187,9 @@ virtio_reinit_start(struct virtio_softc *sc)
> for (i = 0; i < sc->sc_nvqs; i++) {
> int n;
> struct virtqueue *vq = &sc->sc_vqs[i];
> - n = virtio_read_queue_size(sc, vq->vq_index);
> - if (n == 0) /* vq disappeared */
> + if (vq->vq_num == 0) /* not used */
> continue;
> + n = virtio_read_queue_size(sc, vq->vq_index);
> if (n != vq->vq_num) {
> panic("%s: virtqueue size changed, vq index %d",
> sc->sc_dev.dv_xname, vq->vq_index);
> @@ -274,8 +276,11 @@ virtio_check_vqs(struct virtio_softc *sc)
> int i, r = 0;
>
> /* going backwards is better for if_vio */
> - for (i = sc->sc_nvqs - 1; i >= 0; i--)
> + for (i = sc->sc_nvqs - 1; i >= 0; i--) {
> + if (sc->sc_vqs[i].vq_num == 0) /* not used */
> + continue;
> r |= virtio_check_vq(sc, &sc->sc_vqs[i]);
> + }
>
> return r;
> }
> @@ -305,6 +310,7 @@ virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq)
> int i, j;
> int vq_size = vq->vq_num;
>
> + VIRTIO_ASSERT(vq_size > 0);
> memset(vq->vq_vaddr, 0, vq->vq_bytesize);
>
> /* build the indirect descriptor chain */
> @@ -468,6 +474,11 @@ virtio_free_vq(struct virtio_softc *sc, struct virtqueue *vq)
> struct vq_entry *qe;
> int i = 0;
>
> + if (vq->vq_num == 0) {
> + /* virtio_alloc_vq() was never called */
> + return 0;
> + }
> +
> /* device must be already deactivated */
> /* confirm the vq is empty */
> SLIST_FOREACH(qe, &vq->vq_freelist, qe_list) {
> @@ -1017,6 +1028,10 @@ virtio_vq_dump(struct virtqueue *vq)
> #endif
> /* Common fields */
> printf(" + addr: %p\n", vq);
> + if (vq->vq_num == 0) {
> + printf(" + vq is unused\n");
> + return;
> + }
> printf(" + vq num: %d\n", vq->vq_num);
> printf(" + vq mask: 0x%X\n", vq->vq_mask);
> printf(" + vq index: %d\n", vq->vq_index);
> diff --git a/sys/dev/pv/virtiovar.h b/sys/dev/pv/virtiovar.h
> index bed9ff0ce09..207e43ce9b8 100644
> --- a/sys/dev/pv/virtiovar.h
> +++ b/sys/dev/pv/virtiovar.h
> @@ -103,7 +103,8 @@ struct vq_entry {
>
> struct virtqueue {
> struct virtio_softc *vq_owner;
> - unsigned int vq_num; /* queue size (# of entries) */
> + unsigned int vq_num; /* queue size (# of entries),
> + * 0 if unused/non-existant */
> unsigned int vq_mask; /* (1 << vq_num - 1) */
> int vq_index; /* queue number (0, 1, ...) */
>
> @@ -180,7 +181,7 @@ struct virtio_softc {
> int sc_indirect;
> int sc_version_1;
>
> - int sc_nvqs; /* set by child */
> + int sc_nvqs; /* size of sc_vqs, set by child */
> struct virtqueue *sc_vqs; /* set by child */
>
> struct device *sc_child; /* set by child,
virtio: Support unused virtqueues