mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 10:26:10 +01:00 
			
		
		
		
	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 <willdeacon@google.com>
[ Paul: pick from the Android tree. Rebase to the upstream ]
Signed-off-by: Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
Cc: Bin Meng <bmeng.cn@gmail.com>
Link: 3e052749e7
Reviewed-by: Simon Glass <sjg@chromium.org>
			
			
This commit is contained in:
		| @@ -6,6 +6,7 @@ | |||||||
|  * virtio ring implementation |  * virtio ring implementation | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #include <bouncebuf.h> | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <dm.h> | #include <dm.h> | ||||||
| #include <log.h> | #include <log.h> | ||||||
| @@ -292,6 +293,7 @@ struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num, | |||||||
| 	struct udevice *vdev = uc_priv->vdev; | 	struct udevice *vdev = uc_priv->vdev; | ||||||
| 	struct virtqueue *vq; | 	struct virtqueue *vq; | ||||||
| 	void *queue = NULL; | 	void *queue = NULL; | ||||||
|  | 	struct bounce_buffer *bbs = NULL; | ||||||
| 	struct vring vring; | 	struct vring vring; | ||||||
|  |  | ||||||
| 	/* We assume num is a power of 2 */ | 	/* 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; | 		return NULL; | ||||||
|  |  | ||||||
| 	memset(queue, 0, vring_size(num, vring_align)); | 	memset(queue, 0, vring_size(num, vring_align)); | ||||||
| 	vring_init(&vring, num, queue, vring_align); |  | ||||||
|  | 	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); | 	vq = __vring_new_virtqueue(index, vring, udev); | ||||||
| 	if (!vq) { | 	if (!vq) | ||||||
| 		virtio_free_pages(vdev, queue, DIV_ROUND_UP(vring.size, PAGE_SIZE)); | 		goto err_free_bbs; | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	debug("(%s): created vring @ %p for vq @ %p with num %u\n", udev->name, | 	debug("(%s): created vring @ %p for vq @ %p with num %u\n", udev->name, | ||||||
| 	      queue, vq, num); | 	      queue, vq, num); | ||||||
|  |  | ||||||
| 	return vq; | 	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) | 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)); | 			  DIV_ROUND_UP(vq->vring.size, PAGE_SIZE)); | ||||||
| 	free(vq->vring_desc_shadow); | 	free(vq->vring_desc_shadow); | ||||||
| 	list_del(&vq->list); | 	list_del(&vq->list); | ||||||
|  | 	free(vq->vring.bouncebufs); | ||||||
| 	free(vq); | 	free(vq); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -87,6 +87,7 @@ struct vring_used { | |||||||
| struct vring { | struct vring { | ||||||
| 	unsigned int num; | 	unsigned int num; | ||||||
| 	size_t size; | 	size_t size; | ||||||
|  | 	struct bounce_buffer *bouncebufs; | ||||||
| 	struct vring_desc *desc; | 	struct vring_desc *desc; | ||||||
| 	struct vring_avail *avail; | 	struct vring_avail *avail; | ||||||
| 	struct vring_used *used; | 	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, | 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->num = num; | ||||||
| 	vr->size = vring_size(num, align); | 	vr->size = vring_size(num, align); | ||||||
|  | 	vr->bouncebufs = bouncebufs; | ||||||
| 	vr->desc = p; | 	vr->desc = p; | ||||||
| 	vr->avail = p + num * sizeof(struct vring_desc); | 	vr->avail = p + num * sizeof(struct vring_desc); | ||||||
| 	vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + | 	vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user