Lines Matching defs:vq
109 struct virtqueue *vq = &sc->sc_vqs[i];
110 n = sc->sc_ops->read_queue_size(sc, vq->vq_index);
111 if (n == 0) /* vq disappeared */
113 if (n != vq->vq_num) {
114 panic("%s: virtqueue size changed, vq index %d\n",
116 vq->vq_index);
118 virtio_reset_vq(sc, vq);
119 sc->sc_ops->setup_queue(sc, vq->vq_index,
120 vq->vq_dmamap->dm_segs[0].ds_addr);
454 /* set to vq->vq_intrhand in virtio_init_vq_vqdone() */
458 struct virtqueue *vq = xvq;
460 return vq->vq_done(vq);
466 struct virtqueue *vq;
470 vq = &sc->sc_vqs[i];
471 if (virtio_vq_is_enqueued(sc, vq) == 1) {
472 r |= (*vq->vq_intrhand)(vq->vq_intrhand_arg);
483 vq_sync_descs(struct virtio_softc *sc, struct virtqueue *vq, int ops)
487 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, 0, vq->vq_availoffset,
492 vq_sync_aring_all(struct virtio_softc *sc, struct virtqueue *vq, int ops)
495 size_t payloadlen = vq->vq_num * sizeof(uint16_t);
500 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
501 vq->vq_availoffset, hdrlen + payloadlen + usedlen, ops);
505 vq_sync_aring_header(struct virtio_softc *sc, struct virtqueue *vq, int ops)
509 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
510 vq->vq_availoffset, hdrlen, ops);
514 vq_sync_aring_payload(struct virtio_softc *sc, struct virtqueue *vq, int ops)
517 size_t payloadlen = vq->vq_num * sizeof(uint16_t);
519 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
520 vq->vq_availoffset + hdrlen, payloadlen, ops);
524 vq_sync_aring_used(struct virtio_softc *sc, struct virtqueue *vq, int ops)
527 size_t payloadlen = vq->vq_num * sizeof(uint16_t);
532 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
533 vq->vq_availoffset + hdrlen + payloadlen, usedlen, ops);
537 vq_sync_uring_all(struct virtio_softc *sc, struct virtqueue *vq, int ops)
540 size_t payloadlen = vq->vq_num * sizeof(struct vring_used_elem);
545 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
546 vq->vq_usedoffset, hdrlen + payloadlen + availlen, ops);
550 vq_sync_uring_header(struct virtio_softc *sc, struct virtqueue *vq, int ops)
554 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
555 vq->vq_usedoffset, hdrlen, ops);
559 vq_sync_uring_payload(struct virtio_softc *sc, struct virtqueue *vq, int ops)
562 size_t payloadlen = vq->vq_num * sizeof(struct vring_used_elem);
564 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
565 vq->vq_usedoffset + hdrlen, payloadlen, ops);
569 vq_sync_uring_avail(struct virtio_softc *sc, struct virtqueue *vq, int ops)
572 size_t payloadlen = vq->vq_num * sizeof(struct vring_used_elem);
577 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
578 vq->vq_usedoffset + hdrlen + payloadlen, availlen, ops);
582 vq_sync_indirect(struct virtio_softc *sc, struct virtqueue *vq, int slot,
585 int offset = vq->vq_indirectoffset +
586 sizeof(struct vring_desc) * vq->vq_maxnsegs * slot;
588 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
589 offset, sizeof(struct vring_desc) * vq->vq_maxnsegs, ops);
593 virtio_vq_is_enqueued(struct virtio_softc *sc, struct virtqueue *vq)
596 if (vq->vq_queued) {
597 vq->vq_queued = 0;
598 vq_sync_aring_all(sc, vq, BUS_DMASYNC_POSTWRITE);
601 vq_sync_uring_header(sc, vq, BUS_DMASYNC_POSTREAD);
602 if (vq->vq_used_idx == virtio_rw16(sc, vq->vq_used->idx))
604 vq_sync_uring_payload(sc, vq, BUS_DMASYNC_POSTREAD);
612 virtio_postpone_intr(struct virtio_softc *sc, struct virtqueue *vq,
617 idx = vq->vq_used_idx + nslots;
620 *vq->vq_used_event = virtio_rw16(sc, idx);
621 vq_sync_aring_used(vq->vq_owner, vq, BUS_DMASYNC_PREWRITE);
622 vq->vq_queued++;
625 (virtio_rw16(sc, vq->vq_used->idx) - vq->vq_used_idx);
626 KASSERT(nused <= vq->vq_num);
636 virtio_postpone_intr_smart(struct virtio_softc *sc, struct virtqueue *vq)
641 (virtio_rw16(sc, vq->vq_avail->idx) - vq->vq_used_idx) * 3 / 4;
643 return virtio_postpone_intr(sc, vq, nslots);
651 virtio_postpone_intr_far(struct virtio_softc *sc, struct virtqueue *vq)
656 (virtio_rw16(sc, vq->vq_avail->idx) - vq->vq_used_idx);
658 return virtio_postpone_intr(sc, vq, nslots);
662 * Start/stop vq interrupt. No guarantee.
665 virtio_stop_vq_intr(struct virtio_softc *sc, struct virtqueue *vq)
675 *vq->vq_used_event = virtio_rw16(sc, vq->vq_used_idx + 0x8000);
676 vq_sync_aring_used(sc, vq, BUS_DMASYNC_PREWRITE);
678 vq->vq_avail->flags |=
680 vq_sync_aring_header(sc, vq, BUS_DMASYNC_PREWRITE);
682 vq->vq_queued++;
686 virtio_start_vq_intr(struct virtio_softc *sc, struct virtqueue *vq)
695 *vq->vq_used_event = virtio_rw16(sc, vq->vq_used_idx);
696 vq_sync_aring_used(sc, vq, BUS_DMASYNC_PREWRITE);
698 vq->vq_avail->flags &=
700 vq_sync_aring_header(sc, vq, BUS_DMASYNC_PREWRITE);
702 vq->vq_queued++;
704 vq_sync_uring_header(sc, vq, BUS_DMASYNC_POSTREAD);
705 if (vq->vq_used_idx == virtio_rw16(sc, vq->vq_used->idx))
707 vq_sync_uring_payload(sc, vq, BUS_DMASYNC_POSTREAD);
712 * Initialize vq structure.
718 virtio_reset_vq(struct virtio_softc *sc, struct virtqueue *vq)
722 int vq_size = vq->vq_num;
724 memset(vq->vq_vaddr, 0, vq->vq_bytesize);
727 vds = vq->vq_desc;
732 vq->vq_free_idx = 0;
735 if (vq->vq_indirect != NULL) {
739 vd = vq->vq_indirect;
740 vd += vq->vq_maxnsegs * i;
741 for (j = 0; j < vq->vq_maxnsegs - 1; j++) {
748 vq->vq_avail_idx = 0;
749 vq->vq_used_idx = 0;
750 vq->vq_queued = 0;
751 vq_sync_uring_all(sc, vq, BUS_DMASYNC_PREREAD);
752 vq->vq_queued++;
755 /* Initialize vq */
757 virtio_init_vq_vqdone(struct virtio_softc *sc, struct virtqueue *vq,
761 virtio_init_vq(sc, vq, index, virtio_vq_done, vq);
762 vq->vq_done = vq_done;
766 virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq, int index,
770 memset(vq, 0, sizeof(*vq));
772 vq->vq_owner = sc;
773 vq->vq_num = sc->sc_ops->read_queue_size(sc, index);
774 vq->vq_index = index;
775 vq->vq_intrhand = func;
776 vq->vq_intrhand_arg = arg;
780 * Allocate/free a vq.
783 virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq,
792 vq_num = vq->vq_num;
797 vq->vq_index, name);
803 size_desc = sizeof(vq->vq_desc[0]) * vq_num;
805 + sizeof(vq->vq_avail[0].ring[0]) * vq_num;
807 + sizeof(vq->vq_used[0].ring[0]) * vq_num;
818 &vq->vq_segs[0], 1, &rsegs, BUS_DMA_WAITOK);
822 "error code %d\n", vq->vq_index, name, r);
826 r = bus_dmamem_map(sc->sc_dmat, &vq->vq_segs[0], rsegs, allocsize,
827 &vq->vq_vaddr, BUS_DMA_WAITOK);
831 "error code %d\n", vq->vq_index, name, r);
836 BUS_DMA_WAITOK, &vq->vq_dmamap);
840 "error code %d\n", vq->vq_index, name, r);
844 r = bus_dmamap_load(sc->sc_dmat, vq->vq_dmamap,
845 vq->vq_vaddr, allocsize, NULL, BUS_DMA_WAITOK);
849 "error code %d\n", vq->vq_index, name, r);
853 vq->vq_bytesize = allocsize;
854 vq->vq_maxsegsize = maxsegsize;
855 vq->vq_maxnsegs = maxnsegs;
859 vq->vq_desc = VIRTIO_PTR(vq->vq_vaddr, 0);
860 vq->vq_availoffset = size_desc;
861 vq->vq_avail = VIRTIO_PTR(vq->vq_vaddr, vq->vq_availoffset);
862 vq->vq_used_event = VIRTIO_PTR(vq->vq_avail,
864 vq->vq_usedoffset = size_desc_avail;
865 vq->vq_used = VIRTIO_PTR(vq->vq_vaddr, vq->vq_usedoffset);
866 vq->vq_avail_event = VIRTIO_PTR(vq->vq_used,
870 vq->vq_indirectoffset = size_desc_avail + size_used;
871 vq->vq_indirect = VIRTIO_PTR(vq->vq_vaddr,
872 vq->vq_indirectoffset);
876 vq->vq_descx = kmem_zalloc(sizeof(vq->vq_descx[0]) * vq_num,
879 mutex_init(&vq->vq_freedesc_lock, MUTEX_SPIN, sc->sc_ipl);
880 mutex_init(&vq->vq_aring_lock, MUTEX_SPIN, sc->sc_ipl);
881 mutex_init(&vq->vq_uring_lock, MUTEX_SPIN, sc->sc_ipl);
883 virtio_reset_vq(sc, vq);
887 "size %d\n", allocsize, vq->vq_index, name, vq_num);
896 sc->sc_ops->setup_queue(sc, vq->vq_index, 0);
897 if (vq->vq_dmamap)
898 bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap);
899 if (vq->vq_vaddr)
900 bus_dmamem_unmap(sc->sc_dmat, vq->vq_vaddr, allocsize);
901 if (vq->vq_segs[0].ds_addr)
902 bus_dmamem_free(sc->sc_dmat, &vq->vq_segs[0], 1);
903 memset(vq, 0, sizeof(*vq));
909 virtio_free_vq(struct virtio_softc *sc, struct virtqueue *vq)
914 if (vq->vq_vaddr == NULL)
918 /* confirm the vq is empty */
919 s = vq->vq_free_idx;
922 s = vq->vq_desc[s].next;
925 if (i != vq->vq_num) {
926 printf("%s: freeing non-empty vq, index %d\n",
927 device_xname(sc->sc_dev), vq->vq_index);
932 sc->sc_ops->setup_queue(sc, vq->vq_index, 0);
934 vq_sync_aring_all(sc, vq, BUS_DMASYNC_POSTWRITE);
936 kmem_free(vq->vq_descx, sizeof(vq->vq_descx[0]) * vq->vq_num);
937 bus_dmamap_unload(sc->sc_dmat, vq->vq_dmamap);
938 bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap);
939 bus_dmamem_unmap(sc->sc_dmat, vq->vq_vaddr, vq->vq_bytesize);
940 bus_dmamem_free(sc->sc_dmat, &vq->vq_segs[0], 1);
941 mutex_destroy(&vq->vq_freedesc_lock);
942 mutex_destroy(&vq->vq_uring_lock);
943 mutex_destroy(&vq->vq_aring_lock);
944 memset(vq, 0, sizeof(*vq));
953 vq_alloc_slot_locked(struct virtio_softc *sc, struct virtqueue *vq,
960 KASSERT(mutex_owned(&vq->vq_freedesc_lock));
962 head = tail = virtio_rw16(sc, vq->vq_free_idx);
967 vd = &vq->vq_desc[tail];
975 vd = &vq->vq_desc[tail];
977 vq->vq_free_idx = vd->next;
982 vq_alloc_slot(struct virtio_softc *sc, struct virtqueue *vq, size_t nslots)
986 mutex_enter(&vq->vq_freedesc_lock);
987 rv = vq_alloc_slot_locked(sc, vq, nslots);
988 mutex_exit(&vq->vq_freedesc_lock);
994 vq_free_slot(struct virtio_softc *sc, struct virtqueue *vq, uint16_t slot)
999 mutex_enter(&vq->vq_freedesc_lock);
1000 vd = &vq->vq_desc[slot];
1003 vd = &vq->vq_desc[s];
1005 vd->next = vq->vq_free_idx;
1006 vq->vq_free_idx = virtio_rw16(sc, slot);
1007 mutex_exit(&vq->vq_freedesc_lock);
1019 * r = virtio_enqueue_prep(sc, vq, &slot); // allocate a slot
1024 * virtio_enqueue_abort(sc, vq, slot);
1027 * r = virtio_enqueue_reserve(sc, vq, slot,
1037 * virtio_enqueue(sc, vq, slot, dmamap_cmd[slot], false);
1038 * virtio_enqueue(sc, vq, slot, dmamap_payload[slot], iswrite);
1039 * virtio_enqueue_commit(sc, vq, slot, true);
1046 virtio_enqueue_prep(struct virtio_softc *sc, struct virtqueue *vq, int *slotp)
1053 slot = vq_alloc_slot(sc, vq, 1);
1066 virtio_enqueue_reserve(struct virtio_softc *sc, struct virtqueue *vq,
1074 KASSERT(nsegs <= vq->vq_num);
1076 vdx = &vq->vq_descx[slot];
1077 vd = &vq->vq_desc[slot];
1081 if ((vq->vq_indirect != NULL) &&
1083 (nsegs <= vq->vq_maxnsegs))
1091 addr = vq->vq_dmamap->dm_segs[0].ds_addr
1092 + vq->vq_indirectoffset;
1094 * vq->vq_maxnsegs * slot;
1100 vd = &vq->vq_indirect[vq->vq_maxnsegs * slot];
1112 s = vq_alloc_slot(sc, vq, nsegs - 1);
1114 vq_free_slot(sc, vq, slot);
1121 vdx->desc_base = &vq->vq_desc[0];
1132 virtio_enqueue(struct virtio_softc *sc, struct virtqueue *vq, int slot,
1142 vdx = &vq->vq_descx[slot];
1169 virtio_enqueue_p(struct virtio_softc *sc, struct virtqueue *vq, int slot,
1177 vdx = &vq->vq_descx[slot];
1207 virtio_enqueue_commit(struct virtio_softc *sc, struct virtqueue *vq, int slot,
1212 mutex_enter(&vq->vq_aring_lock);
1216 vq_sync_descs(sc, vq, BUS_DMASYNC_PREWRITE);
1217 if (vq->vq_descx[slot].use_indirect)
1218 vq_sync_indirect(sc, vq, slot, BUS_DMASYNC_PREWRITE);
1220 mutex_enter(&vq->vq_aring_lock);
1221 vq->vq_avail->ring[(vq->vq_avail_idx++) % vq->vq_num] =
1229 o = virtio_rw16(sc, vq->vq_avail->idx) - 1;
1230 n = vq->vq_avail_idx;
1235 * the vq->vq_avail->idx update to ensure we're not
1238 * vq->vq_avail->idx.
1240 vq_sync_uring_all(sc, vq, BUS_DMASYNC_PREREAD);
1243 vq_sync_aring_payload(sc, vq, BUS_DMASYNC_PREWRITE);
1244 vq->vq_avail->idx = virtio_rw16(sc, vq->vq_avail_idx);
1245 vq_sync_aring_header(sc, vq, BUS_DMASYNC_PREWRITE);
1246 vq->vq_queued++;
1249 vq_sync_uring_avail(sc, vq, BUS_DMASYNC_POSTREAD);
1250 t = virtio_rw16(sc, *vq->vq_avail_event) + 1;
1252 sc->sc_ops->kick(sc, vq->vq_index);
1254 vq_sync_uring_header(sc, vq, BUS_DMASYNC_POSTREAD);
1255 flags = virtio_rw16(sc, vq->vq_used->flags);
1257 sc->sc_ops->kick(sc, vq->vq_index);
1260 mutex_exit(&vq->vq_aring_lock);
1269 virtio_enqueue_abort(struct virtio_softc *sc, struct virtqueue *vq, int slot)
1273 vdx = &vq->vq_descx[slot];
1277 vq_free_slot(sc, vq, slot);
1290 virtio_dequeue(struct virtio_softc *sc, struct virtqueue *vq,
1295 if (vq->vq_used_idx == virtio_rw16(sc, vq->vq_used->idx))
1297 mutex_enter(&vq->vq_uring_lock);
1298 usedidx = vq->vq_used_idx++;
1299 mutex_exit(&vq->vq_uring_lock);
1300 usedidx %= vq->vq_num;
1301 slot = virtio_rw32(sc, vq->vq_used->ring[usedidx].id);
1303 if (vq->vq_descx[slot].use_indirect)
1304 vq_sync_indirect(sc, vq, slot, BUS_DMASYNC_POSTWRITE);
1309 *lenp = virtio_rw32(sc, vq->vq_used->ring[usedidx].len);
1319 virtio_dequeue_commit(struct virtio_softc *sc, struct virtqueue *vq, int slot)
1323 vdx = &vq->vq_descx[slot];
1327 vq_free_slot(sc, vq, slot);
1383 /* set the vq address */