From: Will Deacon Date: Wed, 29 Mar 2023 14:24:59 +0000 (+0800) Subject: virtio: Allocate bounce buffers for devices with VIRTIO_F_IOMMU_PLATFORM X-Git-Url: http://git.dujemihanovic.xyz/login.html?a=commitdiff_plain;h=37e53db38bdbeb58732e36d1efcdf58f6ce3a138;p=u-boot.git virtio: Allocate bounce buffers for devices with VIRTIO_F_IOMMU_PLATFORM In preparation for bouncing virtio data for devices advertising the VIRTIO_F_IOMMU_PLATFORM feature, allocate an array of bounce buffer structures in the vring, one per descriptor. Signed-off-by: Will Deacon [ Paul: pick from the Android tree. Rebase to the upstream ] Signed-off-by: Ying-Chun Liu (PaulLiu) Cc: Bin Meng Link: https://android.googlesource.com/platform/external/u-boot/+/3e052749e7c50c4c1a6014e645ae3b9be3710c07 Reviewed-by: Simon Glass --- diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 1bd19add75..de75786ca7 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -6,6 +6,7 @@ * virtio ring implementation */ +#include #include #include #include @@ -292,6 +293,7 @@ struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num, struct udevice *vdev = uc_priv->vdev; struct virtqueue *vq; void *queue = NULL; + struct bounce_buffer *bbs = NULL; struct vring vring; /* We assume num is a power of 2 */ @@ -320,17 +322,29 @@ struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num, return NULL; memset(queue, 0, vring_size(num, vring_align)); - vring_init(&vring, num, queue, vring_align); - vq = __vring_new_virtqueue(index, vring, udev); - if (!vq) { - virtio_free_pages(vdev, queue, DIV_ROUND_UP(vring.size, PAGE_SIZE)); - return NULL; + if (virtio_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) { + bbs = calloc(num, sizeof(*bbs)); + if (!bbs) + goto err_free_queue; } + + vring_init(&vring, num, queue, vring_align, bbs); + + vq = __vring_new_virtqueue(index, vring, udev); + if (!vq) + goto err_free_bbs; + debug("(%s): created vring @ %p for vq @ %p with num %u\n", udev->name, queue, vq, num); return vq; + +err_free_bbs: + free(bbs); +err_free_queue: + virtio_free_pages(vdev, queue, DIV_ROUND_UP(vring.size, PAGE_SIZE)); + return NULL; } void vring_del_virtqueue(struct virtqueue *vq) @@ -339,6 +353,7 @@ void vring_del_virtqueue(struct virtqueue *vq) DIV_ROUND_UP(vq->vring.size, PAGE_SIZE)); free(vq->vring_desc_shadow); list_del(&vq->list); + free(vq->vring.bouncebufs); free(vq); } diff --git a/include/virtio_ring.h b/include/virtio_ring.h index 8f8a55c7bd..e8e91044a2 100644 --- a/include/virtio_ring.h +++ b/include/virtio_ring.h @@ -87,6 +87,7 @@ struct vring_used { struct vring { unsigned int num; size_t size; + struct bounce_buffer *bouncebufs; struct vring_desc *desc; struct vring_avail *avail; struct vring_used *used; @@ -146,10 +147,12 @@ static inline unsigned int vring_size(unsigned int num, unsigned long align) } static inline void vring_init(struct vring *vr, unsigned int num, void *p, - unsigned long align) + unsigned long align, + struct bounce_buffer *bouncebufs) { vr->num = num; vr->size = vring_size(num, align); + vr->bouncebufs = bouncebufs; vr->desc = p; vr->avail = p + num * sizeof(struct vring_desc); vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] +