From 3cf221fff2fe3344c151b9a2a73416769b2f4667 Mon Sep 17 00:00:00 2001 From: yamaguchi Date: Thu, 23 Mar 2023 03:55:11 +0000 Subject: [PATCH] Added functions to set interrupt handler and index into virtqueue --- sys/dev/pci/if_vioif.c | 23 ++-- sys/dev/pci/ld_virtio.c | 12 ++- sys/dev/pci/vio9p.c | 11 +- sys/dev/pci/viomb.c | 18 ++-- sys/dev/pci/viornd.c | 8 +- sys/dev/pci/vioscsi.c | 12 +-- sys/dev/pci/virtio.c | 227 +++++++++++++++++++++------------------- sys/dev/pci/virtiovar.h | 16 +-- sys/dev/virtio/viocon.c | 16 +-- 9 files changed, 183 insertions(+), 160 deletions(-) diff --git a/sys/dev/pci/if_vioif.c b/sys/dev/pci/if_vioif.c index 2e2c95eaf859..9d9cddfd8f0e 100644 --- a/sys/dev/pci/if_vioif.c +++ b/sys/dev/pci/if_vioif.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_vioif.c,v 1.103 2023/03/23 03:27:48 yamaguchi Exp $ */ +/* $NetBSD: if_vioif.c,v 1.104 2023/03/23 03:55:11 yamaguchi Exp $ */ /* * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.103 2023/03/23 03:27:48 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_vioif.c,v 1.104 2023/03/23 03:55:11 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -596,8 +596,10 @@ vioif_attach(device_t parent, device_t self, void *aux) * Allocating a virtqueue for control channel */ sc->sc_ctrlq.ctrlq_vq = &sc->sc_vqs[ctrlq_idx]; - r = virtio_alloc_vq(vsc, ctrlq->ctrlq_vq, ctrlq_idx, - NBPG, 1, "control"); + virtio_init_vq(vsc, ctrlq->ctrlq_vq, ctrlq_idx, + vioif_ctrl_intr, ctrlq); + + r = virtio_alloc_vq(vsc, ctrlq->ctrlq_vq, NBPG, 1, "control"); if (r != 0) { aprint_error_dev(self, "failed to allocate " "a virtqueue for control channel, error code %d\n", @@ -606,9 +608,6 @@ vioif_attach(device_t parent, device_t self, void *aux) sc->sc_has_ctrl = false; cv_destroy(&ctrlq->ctrlq_wait); mutex_destroy(&ctrlq->ctrlq_wait_lock); - } else { - ctrlq->ctrlq_vq->vq_intrhand = vioif_ctrl_intr; - ctrlq->ctrlq_vq->vq_intrhand_arg = (void *) ctrlq; } } @@ -623,7 +622,7 @@ vioif_attach(device_t parent, device_t self, void *aux) goto err; r = virtio_child_attach_finish(vsc, sc->sc_vqs, nvqs, - vioif_config_change, virtio_vq_intrhand, req_flags); + vioif_config_change, req_flags); if (r != 0) goto err; @@ -1470,15 +1469,15 @@ vioif_netqueue_init(struct vioif_softc *sc, struct virtio_softc *vsc, "%s-%s", device_xname(sc->sc_dev), qname); mutex_init(&netq->netq_lock, MUTEX_DEFAULT, IPL_NET); - r = virtio_alloc_vq(vsc, vq, qid, + virtio_init_vq(vsc, vq, qid, params[dir].intrhand, netq); + + r = virtio_alloc_vq(vsc, vq, params[dir].segsize + sc->sc_hdr_size, params[dir].nsegs, qname); if (r != 0) goto err; netq->netq_vq = vq; - netq->netq_vq->vq_intrhand = params[dir].intrhand; - netq->netq_vq->vq_intrhand_arg = netq; netq->netq_softint = softint_establish(softint_flags, params[dir].sihand, netq); if (netq->netq_softint == NULL) { @@ -1534,8 +1533,6 @@ err: softint_disestablish(netq->netq_softint); netq->netq_softint = NULL; } - netq->netq_vq->vq_intrhand = NULL; - netq->netq_vq->vq_intrhand_arg = NULL; virtio_free_vq(vsc, vq); mutex_destroy(&netq->netq_lock); diff --git a/sys/dev/pci/ld_virtio.c b/sys/dev/pci/ld_virtio.c index c360312e4f6c..0cea794c9a07 100644 --- a/sys/dev/pci/ld_virtio.c +++ b/sys/dev/pci/ld_virtio.c @@ -1,4 +1,4 @@ -/* $NetBSD: ld_virtio.c,v 1.31 2023/03/23 03:27:48 yamaguchi Exp $ */ +/* $NetBSD: ld_virtio.c,v 1.32 2023/03/23 03:55:11 yamaguchi Exp $ */ /* * Copyright (c) 2010 Minoura Makoto. @@ -26,7 +26,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.31 2023/03/23 03:27:48 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ld_virtio.c,v 1.32 2023/03/23 03:55:11 yamaguchi Exp $"); #include #include @@ -332,15 +332,17 @@ ld_virtio_attach(device_t parent, device_t self, void *aux) /* 2 for the minimum size */ maxnsegs += VIRTIO_BLK_MIN_SEGMENTS; - if (virtio_alloc_vq(vsc, &sc->sc_vq, 0, maxxfersize, maxnsegs, + virtio_init_vq_vqdone(vsc, &sc->sc_vq, 0, + ld_virtio_vq_done); + + if (virtio_alloc_vq(vsc, &sc->sc_vq, maxxfersize, maxnsegs, "I/O request") != 0) { goto err; } qsize = sc->sc_vq.vq_num; - sc->sc_vq.vq_done = ld_virtio_vq_done; if (virtio_child_attach_finish(vsc, &sc->sc_vq, 1, - NULL, virtio_vq_intr, VIRTIO_F_INTR_MSIX) != 0) + NULL, VIRTIO_F_INTR_MSIX) != 0) goto err; ld->sc_dv = self; diff --git a/sys/dev/pci/vio9p.c b/sys/dev/pci/vio9p.c index 5a4cfb4bf285..17189a4988e1 100644 --- a/sys/dev/pci/vio9p.c +++ b/sys/dev/pci/vio9p.c @@ -1,4 +1,4 @@ -/* $NetBSD: vio9p.c,v 1.10 2023/03/23 03:27:48 yamaguchi Exp $ */ +/* $NetBSD: vio9p.c,v 1.11 2023/03/23 03:55:11 yamaguchi Exp $ */ /* * Copyright (c) 2019 Internet Initiative Japan, Inc. @@ -26,7 +26,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vio9p.c,v 1.10 2023/03/23 03:27:48 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vio9p.c,v 1.11 2023/03/23 03:55:11 yamaguchi Exp $"); #include #include @@ -507,13 +507,12 @@ vio9p_attach(device_t parent, device_t self, void *aux) if ((features & VIO9P_F_MOUNT_TAG) == 0) goto err_none; - error = virtio_alloc_vq(vsc, &sc->sc_vq[0], 0, VIO9P_MAX_REQLEN, + virtio_init_vq_vqdone(vsc, &sc->sc_vq[0], 0, vio9p_request_done); + error = virtio_alloc_vq(vsc, &sc->sc_vq[0], VIO9P_MAX_REQLEN, VIO9P_N_SEGMENTS * 2, "vio9p"); if (error != 0) goto err_none; - sc->sc_vq[0].vq_done = vio9p_request_done; - sc->sc_buf_tx = kmem_alloc(VIO9P_MAX_REQLEN, KM_SLEEP); sc->sc_buf_rx = kmem_alloc(VIO9P_MAX_REQLEN, KM_SLEEP); @@ -555,7 +554,7 @@ vio9p_attach(device_t parent, device_t self, void *aux) aprint_normal_dev(self, "tagged as %s\n", sc->sc_tag); error = virtio_child_attach_finish(vsc, sc->sc_vq, - __arraycount(sc->sc_vq), NULL, virtio_vq_intr, + __arraycount(sc->sc_vq), NULL, VIRTIO_F_INTR_MPSAFE | VIRTIO_F_INTR_SOFTINT); if (error != 0) goto err_mutex; diff --git a/sys/dev/pci/viomb.c b/sys/dev/pci/viomb.c index ae23a4c2b09f..0eaeb5b9ca11 100644 --- a/sys/dev/pci/viomb.c +++ b/sys/dev/pci/viomb.c @@ -1,4 +1,4 @@ -/* $NetBSD: viomb.c,v 1.14 2023/03/23 03:27:48 yamaguchi Exp $ */ +/* $NetBSD: viomb.c,v 1.15 2023/03/23 03:55:11 yamaguchi Exp $ */ /* * Copyright (c) 2010 Minoura Makoto. @@ -26,7 +26,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: viomb.c,v 1.14 2023/03/23 03:27:48 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: viomb.c,v 1.15 2023/03/23 03:55:11 yamaguchi Exp $"); #include #include @@ -163,18 +163,20 @@ viomb_attach(device_t parent, device_t self, void *aux) mutex_init(&sc->sc_waitlock, MUTEX_DEFAULT, IPL_VM); /* spin */ cv_init(&sc->sc_wait, "balloon"); - if (virtio_alloc_vq(vsc, &sc->sc_vq[VQ_INFLATE], 0, + virtio_init_vq_vqdone(vsc, &sc->sc_vq[VQ_INFLATE], VQ_INFLATE, + inflateq_done); + virtio_init_vq_vqdone(vsc, &sc->sc_vq[VQ_DEFLATE], VQ_DEFLATE, + deflateq_done); + + if (virtio_alloc_vq(vsc, &sc->sc_vq[VQ_INFLATE], sizeof(uint32_t)*PGS_PER_REQ, 1, "inflate") != 0) goto err_mutex; - if (virtio_alloc_vq(vsc, &sc->sc_vq[VQ_DEFLATE], 1, + if (virtio_alloc_vq(vsc, &sc->sc_vq[VQ_DEFLATE], sizeof(uint32_t)*PGS_PER_REQ, 1, "deflate") != 0) goto err_vq0; - sc->sc_vq[VQ_INFLATE].vq_done = inflateq_done; - sc->sc_vq[VQ_DEFLATE].vq_done = deflateq_done; - if (bus_dmamap_create(virtio_dmat(vsc), sizeof(uint32_t)*PGS_PER_REQ, 1, sizeof(uint32_t)*PGS_PER_REQ, 0, BUS_DMA_NOWAIT, &sc->sc_req.bl_dmamap)) { @@ -190,7 +192,7 @@ viomb_attach(device_t parent, device_t self, void *aux) } if (virtio_child_attach_finish(vsc, sc->sc_vq, __arraycount(sc->sc_vq), - viomb_config_change, virtio_vq_intr, 0) != 0) + viomb_config_change, 0) != 0) goto err_out; if (kthread_create(PRI_IDLE, KTHREAD_MPSAFE, NULL, diff --git a/sys/dev/pci/viornd.c b/sys/dev/pci/viornd.c index 978883407879..46d6c2f9d02a 100644 --- a/sys/dev/pci/viornd.c +++ b/sys/dev/pci/viornd.c @@ -1,4 +1,4 @@ -/* $NetBSD: viornd.c,v 1.19 2023/03/23 03:27:48 yamaguchi Exp $ */ +/* $NetBSD: viornd.c,v 1.20 2023/03/23 03:55:11 yamaguchi Exp $ */ /* $OpenBSD: viornd.c,v 1.1 2014/01/21 21:14:58 sf Exp $ */ /* @@ -179,7 +179,9 @@ viornd_attach(device_t parent, device_t self, void *aux) virtio_child_attach_start(vsc, self, IPL_NET, 0, VIRTIO_COMMON_FLAG_BITS); - error = virtio_alloc_vq(vsc, &sc->sc_vq, 0, VIORND_BUFSIZE, 1, + virtio_init_vq_vqdone(vsc, &sc->sc_vq, 0, viornd_vq_done); + + error = virtio_alloc_vq(vsc, &sc->sc_vq, VIORND_BUFSIZE, 1, "Entropy request"); if (error) { aprint_error_dev(sc->sc_dev, "can't alloc virtqueue: %d\n", @@ -189,7 +191,7 @@ viornd_attach(device_t parent, device_t self, void *aux) sc->sc_vq.vq_done = viornd_vq_done; error = virtio_child_attach_finish(vsc, &sc->sc_vq, 1, - NULL, virtio_vq_intr, 0); + NULL, 0); if (error) { virtio_free_vq(vsc, &sc->sc_vq); goto vio_failed; diff --git a/sys/dev/pci/vioscsi.c b/sys/dev/pci/vioscsi.c index addd114a320b..e8502b39b86a 100644 --- a/sys/dev/pci/vioscsi.c +++ b/sys/dev/pci/vioscsi.c @@ -1,4 +1,4 @@ -/* $NetBSD: vioscsi.c,v 1.31 2023/03/23 03:27:48 yamaguchi Exp $ */ +/* $NetBSD: vioscsi.c,v 1.32 2023/03/23 03:55:11 yamaguchi Exp $ */ /* $OpenBSD: vioscsi.c,v 1.3 2015/03/14 03:38:49 jsg Exp $ */ /* @@ -18,7 +18,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vioscsi.c,v 1.31 2023/03/23 03:27:48 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vioscsi.c,v 1.32 2023/03/23 03:55:11 yamaguchi Exp $"); #include #include @@ -148,7 +148,9 @@ vioscsi_attach(device_t parent, device_t self, void *aux) sc->sc_seg_max = seg_max; for(i=0; i < __arraycount(sc->sc_vqs); i++) { - rv = virtio_alloc_vq(vsc, &sc->sc_vqs[i], i, MAXPHYS, + virtio_init_vq_vqdone(vsc, &sc->sc_vqs[i], i, + vioscsi_vq_done); + rv = virtio_alloc_vq(vsc, &sc->sc_vqs[i], MAXPHYS, VIRTIO_SCSI_MIN_SEGMENTS + howmany(MAXPHYS, NBPG), vioscsi_vq_names[i]); if (rv) { @@ -161,7 +163,6 @@ vioscsi_attach(device_t parent, device_t self, void *aux) sc->sc_vqs[i].vq_done = vioscsi_vq_done; } - qsize = sc->sc_vqs[VIOSCSI_VQ_REQUEST].vq_num; if (vioscsi_alloc_reqs(sc, vsc, qsize)) goto err; @@ -171,8 +172,7 @@ vioscsi_attach(device_t parent, device_t self, void *aux) cmd_per_lun, qsize, seg_max, max_target, max_lun); if (virtio_child_attach_finish(vsc, sc->sc_vqs, - __arraycount(sc->sc_vqs), NULL, virtio_vq_intr, - VIRTIO_F_INTR_MSIX) != 0) + __arraycount(sc->sc_vqs), NULL, VIRTIO_F_INTR_MSIX) != 0) goto err; /* diff --git a/sys/dev/pci/virtio.c b/sys/dev/pci/virtio.c index 9ff436809d82..3e870c4fcf41 100644 --- a/sys/dev/pci/virtio.c +++ b/sys/dev/pci/virtio.c @@ -1,4 +1,4 @@ -/* $NetBSD: virtio.c,v 1.66 2023/03/23 03:27:48 yamaguchi Exp $ */ +/* $NetBSD: virtio.c,v 1.67 2023/03/23 03:55:11 yamaguchi Exp $ */ /* * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -28,7 +28,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.66 2023/03/23 03:27:48 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: virtio.c,v 1.67 2023/03/23 03:55:11 yamaguchi Exp $"); #include #include @@ -61,8 +61,8 @@ static const char *virtio_device_name[] = { }; #define NDEVNAMES __arraycount(virtio_device_name) -static void virtio_init_vq(struct virtio_softc *, - struct virtqueue *, const bool); +static void virtio_reset_vq(struct virtio_softc *, + struct virtqueue *); void virtio_set_status(struct virtio_softc *sc, int status) @@ -108,7 +108,7 @@ virtio_reinit_start(struct virtio_softc *sc) device_xname(sc->sc_dev), vq->vq_index); } - virtio_init_vq(sc, vq, true); + virtio_reset_vq(sc, vq); sc->sc_ops->setup_queue(sc, vq->vq_index, vq->vq_dmamap->dm_segs[0].ds_addr); } @@ -434,6 +434,31 @@ virtio_soft_intr(void *arg) (*sc->sc_intrhand)(sc); } +/* set to vq->vq_intrhand in virtio_init_vq_vqdone() */ +static int +virtio_vq_done(void *xvq) +{ + struct virtqueue *vq = xvq; + + return vq->vq_done(vq); +} + +static int +virtio_vq_intr(struct virtio_softc *sc) +{ + struct virtqueue *vq; + int i, r = 0; + + for (i = 0; i < sc->sc_nvqs; i++) { + vq = &sc->sc_vqs[i]; + if (virtio_vq_is_enqueued(sc, vq) == 1) { + r |= (*vq->vq_intrhand)(vq->vq_intrhand_arg); + } + } + + return r; +} + /* * dmamap sync operations for a virtqueue. */ @@ -563,44 +588,6 @@ virtio_vq_is_enqueued(struct virtio_softc *sc, struct virtqueue *vq) return 1; } -/* - * Scan vq, bus_dmamap_sync for the vqs (not for the payload), - * and calls (*vq_done)() if some entries are consumed. - * - * Can be used as sc_intrhand. - */ -int -virtio_vq_intr(struct virtio_softc *sc) -{ - struct virtqueue *vq; - int i, r = 0; - - for (i = 0; i < sc->sc_nvqs; i++) { - vq = &sc->sc_vqs[i]; - if (virtio_vq_is_enqueued(sc, vq) == 1) { - if (vq->vq_done) - r |= (*vq->vq_done)(vq); - } - } - - return r; -} - -int -virtio_vq_intrhand(struct virtio_softc *sc) -{ - struct virtqueue *vq; - int i, r = 0; - - for (i = 0; i < sc->sc_nvqs; i++) { - vq = &sc->sc_vqs[i]; - r |= (*vq->vq_intrhand)(vq->vq_intrhand_arg); - } - - return r; -} - - /* * Increase the event index in order to delay interrupts. */ @@ -707,9 +694,11 @@ virtio_start_vq_intr(struct virtio_softc *sc, struct virtqueue *vq) /* * Initialize vq structure. */ +/* + * Reset virtqueue parameters + */ static void -virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq, - const bool reinit) +virtio_reset_vq(struct virtio_softc *sc, struct virtqueue *vq) { int i, j; int vq_size = vq->vq_num; @@ -736,56 +725,75 @@ virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq, qe_list); vq->vq_entries[i].qe_index = i; } - if (!reinit) - mutex_init(&vq->vq_freelist_lock, MUTEX_SPIN, sc->sc_ipl); /* enqueue/dequeue status */ vq->vq_avail_idx = 0; vq->vq_used_idx = 0; vq->vq_queued = 0; - if (!reinit) { - mutex_init(&vq->vq_aring_lock, MUTEX_SPIN, sc->sc_ipl); - mutex_init(&vq->vq_uring_lock, MUTEX_SPIN, sc->sc_ipl); - } vq_sync_uring_all(sc, vq, BUS_DMASYNC_PREREAD); vq->vq_queued++; } +/* Initialize vq */ +void +virtio_init_vq_vqdone(struct virtio_softc *sc, struct virtqueue *vq, + int index, int (*vq_done)(struct virtqueue *)) +{ + + virtio_init_vq(sc, vq, index, virtio_vq_done, vq); + vq->vq_done = vq_done; +} + +void +virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq, int index, + int (*intrhand)(void *), void *arg) +{ + + memset(vq, 0, sizeof(*vq)); + + vq->vq_owner = sc; + vq->vq_num = sc->sc_ops->read_queue_size(sc, index); + vq->vq_index = index; + vq->vq_intrhand = intrhand; + vq->vq_intrhand_arg = arg; +} + /* * Allocate/free a vq. */ int -virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int index, +virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int maxsegsize, int maxnsegs, const char *name) { - int vq_size, allocsize1, allocsize2, allocsize3, allocsize = 0; + bus_size_t size_desc, size_avail, size_used, size_indirect; + bus_size_t allocsize = 0, size_desc_avail; int rsegs, r, hdrlen; + unsigned int vq_num; #define VIRTQUEUE_ALIGN(n) roundup(n, VIRTIO_PAGE_SIZE) - memset(vq, 0, sizeof(*vq)); + vq_num = vq->vq_num; - vq_size = sc->sc_ops->read_queue_size(sc, index); - if (vq_size == 0) { + if (vq_num == 0) { aprint_error_dev(sc->sc_dev, "virtqueue not exist, index %d for %s\n", - index, name); + vq->vq_index, name); goto err; } hdrlen = sc->sc_active_features & VIRTIO_F_RING_EVENT_IDX ? 3 : 2; - /* allocsize1: descriptor table + avail ring + pad */ - allocsize1 = VIRTQUEUE_ALIGN(sizeof(struct vring_desc) * vq_size - + sizeof(uint16_t) * (hdrlen + vq_size)); - /* allocsize2: used ring + pad */ - allocsize2 = VIRTQUEUE_ALIGN(sizeof(uint16_t) * hdrlen - + sizeof(struct vring_used_elem) * vq_size); - /* allocsize3: indirect table */ - if (sc->sc_indirect && maxnsegs >= MINSEG_INDIRECT) - allocsize3 = sizeof(struct vring_desc) * maxnsegs * vq_size; - else - allocsize3 = 0; - allocsize = allocsize1 + allocsize2 + allocsize3; + size_desc = sizeof(vq->vq_desc[0]) * vq_num; + size_avail = sizeof(uint16_t) * hdrlen + + sizeof(vq->vq_avail[0].ring) * vq_num; + size_used = sizeof(uint16_t) *hdrlen + + sizeof(vq->vq_used[0].ring) * vq_num; + size_indirect = (sc->sc_indirect && maxnsegs >= MINSEG_INDIRECT) ? + sizeof(struct vring_desc) * maxnsegs * vq_num : 0; + + size_desc_avail = VIRTQUEUE_ALIGN(size_desc + size_avail); + size_used = VIRTQUEUE_ALIGN(size_used); + + allocsize = size_desc_avail + size_used + size_indirect; /* alloc and map the memory */ r = bus_dmamem_alloc(sc->sc_dmat, allocsize, VIRTIO_PAGE_SIZE, 0, @@ -793,78 +801,86 @@ virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq, int index, if (r != 0) { aprint_error_dev(sc->sc_dev, "virtqueue %d for %s allocation failed, " - "error code %d\n", index, name, r); + "error code %d\n", vq->vq_index, name, r); goto err; } + r = bus_dmamem_map(sc->sc_dmat, &vq->vq_segs[0], rsegs, allocsize, &vq->vq_vaddr, BUS_DMA_WAITOK); if (r != 0) { aprint_error_dev(sc->sc_dev, "virtqueue %d for %s map failed, " - "error code %d\n", index, name, r); + "error code %d\n", vq->vq_index, name, r); goto err; } + r = bus_dmamap_create(sc->sc_dmat, allocsize, 1, allocsize, 0, BUS_DMA_WAITOK, &vq->vq_dmamap); if (r != 0) { aprint_error_dev(sc->sc_dev, "virtqueue %d for %s dmamap creation failed, " - "error code %d\n", index, name, r); + "error code %d\n", vq->vq_index, name, r); goto err; } + r = bus_dmamap_load(sc->sc_dmat, vq->vq_dmamap, vq->vq_vaddr, allocsize, NULL, BUS_DMA_WAITOK); if (r != 0) { aprint_error_dev(sc->sc_dev, "virtqueue %d for %s dmamap load failed, " - "error code %d\n", index, name, r); + "error code %d\n", vq->vq_index, name, r); goto err; } - /* remember addresses and offsets for later use */ - vq->vq_owner = sc; - vq->vq_num = vq_size; - vq->vq_index = index; - vq->vq_desc = vq->vq_vaddr; - vq->vq_availoffset = sizeof(struct vring_desc) * vq_size; - vq->vq_avail = (void *)(((char *)vq->vq_desc) + vq->vq_availoffset); - vq->vq_used_event = (uint16_t *)((char *)vq->vq_avail + - offsetof(struct vring_avail, ring[vq->vq_num])); - vq->vq_usedoffset = allocsize1; - vq->vq_used = (void *)(((char *)vq->vq_desc) + vq->vq_usedoffset); - vq->vq_avail_event = (uint16_t *)((char *)vq->vq_used + - offsetof(struct vring_used, ring[vq->vq_num])); - - if (allocsize3 > 0) { - vq->vq_indirectoffset = allocsize1 + allocsize2; - vq->vq_indirect = (void *)(((char *)vq->vq_desc) - + vq->vq_indirectoffset); - } vq->vq_bytesize = allocsize; vq->vq_maxsegsize = maxsegsize; vq->vq_maxnsegs = maxnsegs; +#define VIRTIO_PTR(base, offset) (void *)((intptr_t)(base) + (offset)) + /* initialize vring pointers */ + vq->vq_desc = VIRTIO_PTR(vq->vq_vaddr, 0); + vq->vq_availoffset = size_desc; + vq->vq_avail = VIRTIO_PTR(vq->vq_vaddr, vq->vq_availoffset); + vq->vq_used_event = VIRTIO_PTR(vq->vq_avail, + offsetof(struct vring_avail, ring[vq_num])); + vq->vq_usedoffset = size_desc_avail; + vq->vq_used = VIRTIO_PTR(vq->vq_vaddr, vq->vq_usedoffset); + vq->vq_avail_event = VIRTIO_PTR(vq->vq_used, + offsetof(struct vring_used, ring[vq_num])); + + if (size_indirect > 0) { + vq->vq_indirectoffset = size_desc_avail + size_used; + vq->vq_indirect = VIRTIO_PTR(vq->vq_vaddr, + vq->vq_indirectoffset); + } +#undef VIRTIO_PTR + /* free slot management */ - vq->vq_entries = kmem_zalloc(sizeof(struct vq_entry) * vq_size, + vq->vq_entries = kmem_zalloc(sizeof(struct vq_entry) * vq_num, KM_SLEEP); - virtio_init_vq(sc, vq, false); + + mutex_init(&vq->vq_freelist_lock, MUTEX_SPIN, sc->sc_ipl); + mutex_init(&vq->vq_aring_lock, MUTEX_SPIN, sc->sc_ipl); + mutex_init(&vq->vq_uring_lock, MUTEX_SPIN, sc->sc_ipl); + + virtio_reset_vq(sc, vq); /* set the vq address */ - sc->sc_ops->setup_queue(sc, index, + sc->sc_ops->setup_queue(sc, vq->vq_index, vq->vq_dmamap->dm_segs[0].ds_addr); aprint_verbose_dev(sc->sc_dev, - "allocated %u byte for virtqueue %d for %s, size %d\n", - allocsize, index, name, vq_size); - if (allocsize3 > 0) + "allocated %zu byte for virtqueue %d for %s, size %d\n", + allocsize, vq->vq_index, name, vq_num); + if (size_indirect > 0) aprint_verbose_dev(sc->sc_dev, - "using %d byte (%d entries) indirect descriptors\n", - allocsize3, maxnsegs * vq_size); + "using %zu byte (%d entries) indirect descriptors\n", + size_indirect, maxnsegs * vq_num); return 0; err: - sc->sc_ops->setup_queue(sc, index, 0); + sc->sc_ops->setup_queue(sc, vq->vq_index, 0); if (vq->vq_dmamap) bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap); if (vq->vq_vaddr) @@ -1279,7 +1295,7 @@ virtio_child_attach_start(struct virtio_softc *sc, device_t child, int ipl, int virtio_child_attach_finish(struct virtio_softc *sc, struct virtqueue *vqs, size_t nvqs, - virtio_callback config_change, virtio_callback intr_hand, + virtio_callback config_change, int req_flags) { int r; @@ -1292,8 +1308,9 @@ virtio_child_attach_finish(struct virtio_softc *sc, for (size_t _i = 0; _i < nvqs; _i++){ KASSERT(vqs[_i].vq_index == _i); - KASSERT((req_flags & VIRTIO_F_INTR_PERVQ) == 0 || - vqs[_i].vq_intrhand != NULL); + KASSERT(vqs[_i].vq_intrhand != NULL); + KASSERT(vqs[_i].vq_done == NULL || + vqs[_i].vq_intrhand == virtio_vq_done); } #endif @@ -1302,7 +1319,7 @@ virtio_child_attach_finish(struct virtio_softc *sc, sc->sc_vqs = vqs; sc->sc_nvqs = nvqs; sc->sc_config_change = config_change; - sc->sc_intrhand = intr_hand; + sc->sc_intrhand = virtio_vq_intr; sc->sc_flags = req_flags; r = sc->sc_ops->alloc_interrupts(sc); diff --git a/sys/dev/pci/virtiovar.h b/sys/dev/pci/virtiovar.h index 9a2ad02644a1..2a6fc7d28654 100644 --- a/sys/dev/pci/virtiovar.h +++ b/sys/dev/pci/virtiovar.h @@ -1,4 +1,4 @@ -/* $NetBSD: virtiovar.h,v 1.25 2023/03/23 03:27:48 yamaguchi Exp $ */ +/* $NetBSD: virtiovar.h,v 1.26 2023/03/23 03:55:11 yamaguchi Exp $ */ /* * Copyright (c) 2010 Minoura Makoto. @@ -118,7 +118,7 @@ struct virtqueue { kmutex_t vq_uring_lock; /* interrupt handler */ - int (*vq_done)(struct virtqueue*); + int (*vq_done)(struct virtqueue*); /* for compatibility */ int (*vq_intrhand)(void *); void *vq_intrhand_arg; @@ -172,7 +172,7 @@ struct virtio_softc { int sc_childdevid; device_t sc_child; /* set by child */ virtio_callback sc_config_change; /* set by child */ - virtio_callback sc_intrhand; /* set by child */ + virtio_callback sc_intrhand; }; #else struct virtio_softc; @@ -204,7 +204,11 @@ void virtio_write_device_config_8(struct virtio_softc *, int, uint64_t); void virtio_write_device_config_le_2(struct virtio_softc *, int, uint16_t); void virtio_write_device_config_le_4(struct virtio_softc *, int, uint32_t); -int virtio_alloc_vq(struct virtio_softc*, struct virtqueue*, int, int, int, +void virtio_init_vq(struct virtio_softc *, struct virtqueue *, int, + int (*)(void *), void *); +void virtio_init_vq_vqdone(struct virtio_softc *,struct virtqueue *, int, + int (*)(struct virtqueue *)); +int virtio_alloc_vq(struct virtio_softc*, struct virtqueue*, int, int, const char*); int virtio_free_vq(struct virtio_softc*, struct virtqueue*); void virtio_reset(struct virtio_softc *); @@ -214,7 +218,7 @@ void virtio_child_attach_start(struct virtio_softc *, device_t, int, uint64_t, const char *); int virtio_child_attach_finish(struct virtio_softc *, struct virtqueue *, size_t, - virtio_callback, virtio_callback, int); + virtio_callback, int); void virtio_child_attach_failed(struct virtio_softc *); void virtio_child_detach(struct virtio_softc *); @@ -231,8 +235,6 @@ int virtio_dequeue(struct virtio_softc*, struct virtqueue*, int *, int *); int virtio_dequeue_commit(struct virtio_softc*, struct virtqueue*, int); bool virtio_vq_is_enqueued(struct virtio_softc *, struct virtqueue *); -int virtio_vq_intr(struct virtio_softc *); -int virtio_vq_intrhand(struct virtio_softc *); int virtio_postpone_intr(struct virtio_softc *sc, struct virtqueue *vq, uint16_t nslots); int virtio_postpone_intr_smart(struct virtio_softc *sc, struct virtqueue *vq); diff --git a/sys/dev/virtio/viocon.c b/sys/dev/virtio/viocon.c index a113e23d9fbe..9d80be1fdc2d 100644 --- a/sys/dev/virtio/viocon.c +++ b/sys/dev/virtio/viocon.c @@ -1,4 +1,4 @@ -/* $NetBSD: viocon.c,v 1.7 2023/03/23 03:44:28 yamaguchi Exp $ */ +/* $NetBSD: viocon.c,v 1.8 2023/03/23 03:55:11 yamaguchi Exp $ */ /* $OpenBSD: viocon.c,v 1.8 2021/11/05 11:38:29 mpi Exp $ */ /* @@ -18,7 +18,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.7 2023/03/23 03:44:28 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.8 2023/03/23 03:55:11 yamaguchi Exp $"); #include #include @@ -225,7 +225,7 @@ viocon_attach(struct device *parent, struct device *self, void *aux) viocon_rx_fill(sc->sc_ports[0]); if (virtio_child_attach_finish(vsc, sc->sc_vqs, nvqs, - /*config_change*/NULL, virtio_vq_intr, /*req_flags*/0) != 0) + /*config_change*/NULL, /*req_flags*/0) != 0) goto err; return; @@ -256,24 +256,26 @@ viocon_port_create(struct viocon_softc *sc, int portidx) txidx = (portidx * VIOCON_PORT_NQS) + VIOCON_PORT_TX; snprintf(name, sizeof(name), "p%drx", portidx); - if (virtio_alloc_vq(vsc, &sc->sc_vqs[rxidx], rxidx, BUFSIZE, 1, + virtio_init_vq_vqdone(vsc, &sc->sc_vqs[rxidx], rxidx, + viocon_rx_intr); + if (virtio_alloc_vq(vsc, &sc->sc_vqs[rxidx], BUFSIZE, 1, name) != 0) { printf("\nCan't alloc %s virtqueue\n", name); goto err; } vp->vp_rx = &sc->sc_vqs[rxidx]; - vp->vp_rx->vq_done = viocon_rx_intr; vp->vp_si = softint_establish(SOFTINT_SERIAL, viocon_rx_soft, vp); DPRINTF("%s: rx: %p\n", __func__, vp->vp_rx); snprintf(name, sizeof(name), "p%dtx", portidx); - if (virtio_alloc_vq(vsc, &sc->sc_vqs[txidx], txidx, BUFSIZE, 1, + virtio_init_vq_vqdone(vsc, &sc->sc_vqs[txidx], txidx, + viocon_tx_intr); + if (virtio_alloc_vq(vsc, &sc->sc_vqs[txidx], BUFSIZE, 1, name) != 0) { printf("\nCan't alloc %s virtqueue\n", name); goto err; } vp->vp_tx = &sc->sc_vqs[txidx]; - vp->vp_tx->vq_done = viocon_tx_intr; DPRINTF("%s: tx: %p\n", __func__, vp->vp_tx); allocsize = (vp->vp_rx->vq_num + vp->vp_tx->vq_num) * BUFSIZE;