Home | History | Annotate | Download | only in pci

Lines Matching refs:vq

117 		struct virtqueue *vq = &sc->sc_vqs[i];
118 n = sc->sc_ops->read_queue_size(sc, vq->vq_index);
119 if (n == 0) /* vq disappeared */
121 if (n != vq->vq_num) {
122 panic("%s: virtqueue size changed, vq index %d\n",
124 vq->vq_index);
126 virtio_reset_vq(sc, vq);
127 sc->sc_ops->setup_queue(sc, vq->vq_index,
128 vq->vq_dmamap->dm_segs[0].ds_addr);
462 /* set to vq->vq_intrhand in virtio_init_vq_vqdone() */
466 struct virtqueue *vq = xvq;
468 return vq->vq_done(vq);
474 struct virtqueue *vq;
478 vq = &sc->sc_vqs[i];
479 if (virtio_vq_is_enqueued(sc, vq) == 1) {
480 r |= (*vq->vq_intrhand)(vq->vq_intrhand_arg);
491 vq_sync_descs(struct virtio_softc *sc, struct virtqueue *vq, int ops)
495 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap, 0, vq->vq_availoffset,
500 vq_sync_aring_all(struct virtio_softc *sc, struct virtqueue *vq, int ops)
503 size_t payloadlen = vq->vq_num * sizeof(uint16_t);
508 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
509 vq->vq_availoffset, hdrlen + payloadlen + usedlen, ops);
513 vq_sync_aring_header(struct virtio_softc *sc, struct virtqueue *vq, int ops)
517 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
518 vq->vq_availoffset, hdrlen, ops);
522 vq_sync_aring_payload(struct virtio_softc *sc, struct virtqueue *vq, int ops)
525 size_t payloadlen = vq->vq_num * sizeof(uint16_t);
527 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
528 vq->vq_availoffset + hdrlen, payloadlen, ops);
532 vq_sync_aring_used(struct virtio_softc *sc, struct virtqueue *vq, int ops)
535 size_t payloadlen = vq->vq_num * sizeof(uint16_t);
540 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
541 vq->vq_availoffset + hdrlen + payloadlen, usedlen, ops);
545 vq_sync_uring_all(struct virtio_softc *sc, struct virtqueue *vq, int ops)
548 size_t payloadlen = vq->vq_num * sizeof(struct vring_used_elem);
553 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
554 vq->vq_usedoffset, hdrlen + payloadlen + availlen, ops);
558 vq_sync_uring_header(struct virtio_softc *sc, struct virtqueue *vq, int ops)
562 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
563 vq->vq_usedoffset, hdrlen, ops);
567 vq_sync_uring_payload(struct virtio_softc *sc, struct virtqueue *vq, int ops)
570 size_t payloadlen = vq->vq_num * sizeof(struct vring_used_elem);
572 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
573 vq->vq_usedoffset + hdrlen, payloadlen, ops);
577 vq_sync_uring_avail(struct virtio_softc *sc, struct virtqueue *vq, int ops)
580 size_t payloadlen = vq->vq_num * sizeof(struct vring_used_elem);
585 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
586 vq->vq_usedoffset + hdrlen + payloadlen, availlen, ops);
590 vq_sync_indirect(struct virtio_softc *sc, struct virtqueue *vq, int slot,
593 int offset = vq->vq_indirectoffset +
594 sizeof(struct vring_desc) * vq->vq_maxnsegs * slot;
596 bus_dmamap_sync(sc->sc_dmat, vq->vq_dmamap,
597 offset, sizeof(struct vring_desc) * vq->vq_maxnsegs, ops);
601 virtio_vq_is_enqueued(struct virtio_softc *sc, struct virtqueue *vq)
604 if (vq->vq_queued) {
605 vq->vq_queued = 0;
606 vq_sync_aring_all(sc, vq, BUS_DMASYNC_POSTWRITE);
609 vq_sync_uring_header(sc, vq, BUS_DMASYNC_POSTREAD);
610 if (vq->vq_used_idx == virtio_rw16(sc, vq->vq_used->idx))
612 vq_sync_uring_payload(sc, vq, BUS_DMASYNC_POSTREAD);
620 virtio_postpone_intr(struct virtio_softc *sc, struct virtqueue *vq,
625 idx = vq->vq_used_idx + nslots;
628 *vq->vq_used_event = virtio_rw16(sc, idx);
629 vq_sync_aring_used(vq->vq_owner, vq, BUS_DMASYNC_PREWRITE);
630 vq->vq_queued++;
633 (virtio_rw16(sc, vq->vq_used->idx) - vq->vq_used_idx);
634 KASSERT(nused <= vq->vq_num);
644 virtio_postpone_intr_smart(struct virtio_softc *sc, struct virtqueue *vq)
649 (virtio_rw16(sc, vq->vq_avail->idx) - vq->vq_used_idx) * 3 / 4;
651 return virtio_postpone_intr(sc, vq, nslots);
659 virtio_postpone_intr_far(struct virtio_softc *sc, struct virtqueue *vq)
664 (virtio_rw16(sc, vq->vq_avail->idx) - vq->vq_used_idx);
666 return virtio_postpone_intr(sc, vq, nslots);
670 * Start/stop vq interrupt. No guarantee.
673 virtio_stop_vq_intr(struct virtio_softc *sc, struct virtqueue *vq)
683 *vq->vq_used_event = virtio_rw16(sc, vq->vq_used_idx + 0x8000);
684 vq_sync_aring_used(sc, vq, BUS_DMASYNC_PREWRITE);
686 vq->vq_avail->flags |=
688 vq_sync_aring_header(sc, vq, BUS_DMASYNC_PREWRITE);
690 vq->vq_queued++;
694 virtio_start_vq_intr(struct virtio_softc *sc, struct virtqueue *vq)
703 *vq->vq_used_event = virtio_rw16(sc, vq->vq_used_idx);
704 vq_sync_aring_used(sc, vq, BUS_DMASYNC_PREWRITE);
706 vq->vq_avail->flags &=
708 vq_sync_aring_header(sc, vq, BUS_DMASYNC_PREWRITE);
710 vq->vq_queued++;
719 vq_sync_uring_header(sc, vq, BUS_DMASYNC_POSTREAD);
720 if (vq->vq_used_idx == virtio_rw16(sc, vq->vq_used->idx))
722 vq_sync_uring_payload(sc, vq, BUS_DMASYNC_POSTREAD);
727 * Initialize vq structure.
733 virtio_reset_vq(struct virtio_softc *sc, struct virtqueue *vq)
737 int vq_size = vq->vq_num;
739 memset(vq->vq_vaddr, 0, vq->vq_bytesize);
742 vds = vq->vq_desc;
747 vq->vq_free_idx = 0;
750 if (vq->vq_indirect != NULL) {
754 vd = vq->vq_indirect;
755 vd += vq->vq_maxnsegs * i;
756 for (j = 0; j < vq->vq_maxnsegs - 1; j++) {
763 vq->vq_avail_idx = 0;
764 vq->vq_used_idx = 0;
765 vq->vq_queued = 0;
766 vq_sync_uring_all(sc, vq, BUS_DMASYNC_PREREAD);
767 vq->vq_queued++;
770 /* Initialize vq */
772 virtio_init_vq_vqdone(struct virtio_softc *sc, struct virtqueue *vq,
776 virtio_init_vq(sc, vq, index, virtio_vq_done, vq);
777 vq->vq_done = vq_done;
781 virtio_init_vq(struct virtio_softc *sc, struct virtqueue *vq, int index,
785 memset(vq, 0, sizeof(*vq));
787 vq->vq_owner = sc;
788 vq->vq_num = sc->sc_ops->read_queue_size(sc, index);
789 vq->vq_index = index;
790 vq->vq_intrhand = func;
791 vq->vq_intrhand_arg = arg;
795 * Allocate/free a vq.
798 virtio_alloc_vq(struct virtio_softc *sc, struct virtqueue *vq,
807 vq_num = vq->vq_num;
812 vq->vq_index, name);
818 size_desc = sizeof(vq->vq_desc[0]) * vq_num;
820 + sizeof(vq->vq_avail[0].ring[0]) * vq_num;
822 + sizeof(vq->vq_used[0].ring[0]) * vq_num;
833 &vq->vq_segs[0], 1, &rsegs, BUS_DMA_WAITOK);
837 "error code %d\n", vq->vq_index, name, r);
841 r = bus_dmamem_map(sc->sc_dmat, &vq->vq_segs[0], rsegs, allocsize,
842 &vq->vq_vaddr, BUS_DMA_WAITOK);
846 "error code %d\n", vq->vq_index, name, r);
851 BUS_DMA_WAITOK, &vq->vq_dmamap);
855 "error code %d\n", vq->vq_index, name, r);
859 r = bus_dmamap_load(sc->sc_dmat, vq->vq_dmamap,
860 vq->vq_vaddr, allocsize, NULL, BUS_DMA_WAITOK);
864 "error code %d\n", vq->vq_index, name, r);
868 vq->vq_bytesize = allocsize;
869 vq->vq_maxsegsize = maxsegsize;
870 vq->vq_maxnsegs = maxnsegs;
874 vq->vq_desc = VIRTIO_PTR(vq->vq_vaddr, 0);
875 vq->vq_availoffset = size_desc;
876 vq->vq_avail = VIRTIO_PTR(vq->vq_vaddr, vq->vq_availoffset);
877 vq->vq_used_event = VIRTIO_PTR(vq->vq_avail,
879 vq->vq_usedoffset = size_desc_avail;
880 vq->vq_used = VIRTIO_PTR(vq->vq_vaddr, vq->vq_usedoffset);
881 vq->vq_avail_event = VIRTIO_PTR(vq->vq_used,
885 vq->vq_indirectoffset = size_desc_avail + size_used;
886 vq->vq_indirect = VIRTIO_PTR(vq->vq_vaddr,
887 vq->vq_indirectoffset);
891 vq->vq_descx = kmem_zalloc(sizeof(vq->vq_descx[0]) * vq_num,
894 mutex_init(&vq->vq_freedesc_lock, MUTEX_SPIN, sc->sc_ipl);
895 mutex_init(&vq->vq_aring_lock, MUTEX_SPIN, sc->sc_ipl);
896 mutex_init(&vq->vq_uring_lock, MUTEX_SPIN, sc->sc_ipl);
898 virtio_reset_vq(sc, vq);
902 "size %d\n", allocsize, vq->vq_index, name, vq_num);
911 sc->sc_ops->setup_queue(sc, vq->vq_index, 0);
912 if (vq->vq_dmamap)
913 bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap);
914 if (vq->vq_vaddr)
915 bus_dmamem_unmap(sc->sc_dmat, vq->vq_vaddr, allocsize);
916 if (vq->vq_segs[0].ds_addr)
917 bus_dmamem_free(sc->sc_dmat, &vq->vq_segs[0], 1);
918 memset(vq, 0, sizeof(*vq));
924 virtio_free_vq(struct virtio_softc *sc, struct virtqueue *vq)
929 if (vq->vq_vaddr == NULL)
933 /* confirm the vq is empty */
934 s = vq->vq_free_idx;
937 s = vq->vq_desc[s].next;
940 if (i != vq->vq_num) {
941 printf("%s: freeing non-empty vq, index %d\n",
942 device_xname(sc->sc_dev), vq->vq_index);
947 sc->sc_ops->setup_queue(sc, vq->vq_index, 0);
949 vq_sync_aring_all(sc, vq, BUS_DMASYNC_POSTWRITE);
951 kmem_free(vq->vq_descx, sizeof(vq->vq_descx[0]) * vq->vq_num);
952 bus_dmamap_unload(sc->sc_dmat, vq->vq_dmamap);
953 bus_dmamap_destroy(sc->sc_dmat, vq->vq_dmamap);
954 bus_dmamem_unmap(sc->sc_dmat, vq->vq_vaddr, vq->vq_bytesize);
955 bus_dmamem_free(sc->sc_dmat, &vq->vq_segs[0], 1);
956 mutex_destroy(&vq->vq_freedesc_lock);
957 mutex_destroy(&vq->vq_uring_lock);
958 mutex_destroy(&vq->vq_aring_lock);
959 memset(vq, 0, sizeof(*vq));
968 vq_alloc_slot_locked(struct virtio_softc *sc, struct virtqueue *vq,
975 KASSERT(mutex_owned(&vq->vq_freedesc_lock));
977 head = tail = virtio_rw16(sc, vq->vq_free_idx);
982 vd = &vq->vq_desc[tail];
990 vd = &vq->vq_desc[tail];
992 vq->vq_free_idx = vd->next;
997 vq_alloc_slot(struct virtio_softc *sc, struct virtqueue *vq, size_t nslots)
1001 mutex_enter(&vq->vq_freedesc_lock);
1002 rv = vq_alloc_slot_locked(sc, vq, nslots);
1003 mutex_exit(&vq->vq_freedesc_lock);
1009 vq_free_slot(struct virtio_softc *sc, struct virtqueue *vq, uint16_t slot)
1014 mutex_enter(&vq->vq_freedesc_lock);
1015 vd = &vq->vq_desc[slot];
1018 vd = &vq->vq_desc[s];
1020 vd->next = vq->vq_free_idx;
1021 vq->vq_free_idx = virtio_rw16(sc, slot);
1022 mutex_exit(&vq->vq_freedesc_lock);
1034 * r = virtio_enqueue_prep(sc, vq, &slot); // allocate a slot
1039 * virtio_enqueue_abort(sc, vq, slot);
1042 * r = virtio_enqueue_reserve(sc, vq, slot,
1052 * virtio_enqueue(sc, vq, slot, dmamap_cmd[slot], false);
1053 * virtio_enqueue(sc, vq, slot, dmamap_payload[slot], iswrite);
1054 * virtio_enqueue_commit(sc, vq, slot, true);
1061 virtio_enqueue_prep(struct virtio_softc *sc, struct virtqueue *vq, int *slotp)
1068 slot = vq_alloc_slot(sc, vq, 1);
1081 virtio_enqueue_reserve(struct virtio_softc *sc, struct virtqueue *vq,
1089 KASSERT(nsegs <= vq->vq_num);
1091 vdx = &vq->vq_descx[slot];
1092 vd = &vq->vq_desc[slot];
1096 if ((vq->vq_indirect != NULL) &&
1098 (nsegs <= vq->vq_maxnsegs))
1106 addr = vq->vq_dmamap->dm_segs[0].ds_addr
1107 + vq->vq_indirectoffset;
1109 * vq->vq_maxnsegs * slot;
1115 vd = &vq->vq_indirect[vq->vq_maxnsegs * slot];
1127 s = vq_alloc_slot(sc, vq, nsegs - 1);
1129 vq_free_slot(sc, vq, slot);
1136 vdx->desc_base = &vq->vq_desc[0];
1147 virtio_enqueue(struct virtio_softc *sc, struct virtqueue *vq, int slot,
1157 vdx = &vq->vq_descx[slot];
1184 virtio_enqueue_p(struct virtio_softc *sc, struct virtqueue *vq, int slot,
1192 vdx = &vq->vq_descx[slot];
1222 virtio_enqueue_commit(struct virtio_softc *sc, struct virtqueue *vq, int slot,
1227 mutex_enter(&vq->vq_aring_lock);
1231 vq_sync_descs(sc, vq, BUS_DMASYNC_PREWRITE);
1232 if (vq->vq_descx[slot].use_indirect)
1233 vq_sync_indirect(sc, vq, slot, BUS_DMASYNC_PREWRITE);
1235 mutex_enter(&vq->vq_aring_lock);
1236 vq->vq_avail->ring[(vq->vq_avail_idx++) % vq->vq_num] =
1244 o = virtio_rw16(sc, vq->vq_avail->idx) - 1;
1245 n = vq->vq_avail_idx;
1250 * the vq->vq_avail->idx update to ensure we're not
1253 * vq->vq_avail->idx.
1255 vq_sync_uring_all(sc, vq, BUS_DMASYNC_PREREAD);
1258 vq_sync_aring_payload(sc, vq, BUS_DMASYNC_PREWRITE);
1259 vq->vq_avail->idx = virtio_rw16(sc, vq->vq_avail_idx);
1260 vq_sync_aring_header(sc, vq, BUS_DMASYNC_PREWRITE);
1261 vq->vq_queued++;
1270 vq_sync_uring_avail(sc, vq, BUS_DMASYNC_POSTREAD);
1271 t = virtio_rw16(sc, *vq->vq_avail_event) + 1;
1273 sc->sc_ops->kick(sc, vq->vq_index);
1275 vq_sync_uring_header(sc, vq, BUS_DMASYNC_POSTREAD);
1276 flags = virtio_rw16(sc, vq->vq_used->flags);
1278 sc->sc_ops->kick(sc, vq->vq_index);
1281 mutex_exit(&vq->vq_aring_lock);
1290 virtio_enqueue_abort(struct virtio_softc *sc, struct virtqueue *vq, int slot)
1294 vdx = &vq->vq_descx[slot];
1298 vq_free_slot(sc, vq, slot);
1311 virtio_dequeue(struct virtio_softc *sc, struct virtqueue *vq,
1316 if (vq->vq_used_idx == virtio_rw16(sc, vq->vq_used->idx))
1318 mutex_enter(&vq->vq_uring_lock);
1319 usedidx = vq->vq_used_idx++;
1320 mutex_exit(&vq->vq_uring_lock);
1321 usedidx %= vq->vq_num;
1322 slot = virtio_rw32(sc, vq->vq_used->ring[usedidx].id);
1324 if (vq->vq_descx[slot].use_indirect)
1325 vq_sync_indirect(sc, vq, slot, BUS_DMASYNC_POSTWRITE);
1330 *lenp = virtio_rw32(sc, vq->vq_used->ring[usedidx].len);
1340 virtio_dequeue_commit(struct virtio_softc *sc, struct virtqueue *vq, int slot)
1344 vdx = &vq->vq_descx[slot];
1348 vq_free_slot(sc, vq, slot);
1404 /* set the vq address */