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:
parent
a15d67e01a
commit
37e53db38b
2 changed files with 24 additions and 6 deletions
|
@ -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] +
|
||||||
|
|
Loading…
Reference in a new issue