Re: [PATCH 3/6] virtio: Allocate virtqueue in page-size units

2023-04-01 Thread Simon Glass
On Thu, 30 Mar 2023 at 03:26, Ying-Chun Liu (PaulLiu)
 wrote:
>
> From: Will Deacon 
>
> In preparation for explicit bouncing of virtqueue pages for devices
> advertising the VIRTIO_F_IOMMU_PLATFORM feature, introduce a couple
> of wrappers around virtqueue allocation and freeing operations,
> ensuring that buffers are handled in terms of page-size units.
>
> 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/+/b4bb5227d4cf4fdfcd8b4e1ff2692d3a54d1482a
> ---
>  drivers/virtio/virtio_ring.c | 24 
>  include/virtio_ring.h| 16 +---
>  2 files changed, 29 insertions(+), 11 deletions(-)
>

Reviewed-by: Simon Glass 


[PATCH 3/6] virtio: Allocate virtqueue in page-size units

2023-03-29 Thread Ying-Chun Liu (PaulLiu)
From: Will Deacon 

In preparation for explicit bouncing of virtqueue pages for devices
advertising the VIRTIO_F_IOMMU_PLATFORM feature, introduce a couple
of wrappers around virtqueue allocation and freeing operations,
ensuring that buffers are handled in terms of page-size units.

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/+/b4bb5227d4cf4fdfcd8b4e1ff2692d3a54d1482a
---
 drivers/virtio/virtio_ring.c | 24 
 include/virtio_ring.h| 16 +---
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index f71bab7847..5aeb13fd59 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -15,6 +15,17 @@
 #include 
 #include 
 #include 
+#include 
+
+static void *virtio_alloc_pages(struct udevice *vdev, u32 npages)
+{
+   return memalign(PAGE_SIZE, npages * PAGE_SIZE);
+}
+
+static void virtio_free_pages(struct udevice *vdev, void *ptr, u32 npages)
+{
+   free(ptr);
+}
 
 static unsigned int virtqueue_attach_desc(struct virtqueue *vq, unsigned int i,
  struct virtio_sg *sg, u16 flags)
@@ -271,6 +282,8 @@ struct virtqueue *vring_create_virtqueue(unsigned int 
index, unsigned int num,
 unsigned int vring_align,
 struct udevice *udev)
 {
+   struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
+   struct udevice *vdev = uc_priv->vdev;
struct virtqueue *vq;
void *queue = NULL;
struct vring vring;
@@ -283,7 +296,9 @@ struct virtqueue *vring_create_virtqueue(unsigned int 
index, unsigned int num,
 
/* TODO: allocate each queue chunk individually */
for (; num && vring_size(num, vring_align) > PAGE_SIZE; num /= 2) {
-   queue = memalign(PAGE_SIZE, vring_size(num, vring_align));
+   size_t sz = vring_size(num, vring_align);
+
+   queue = virtio_alloc_pages(vdev, DIV_ROUND_UP(sz, PAGE_SIZE));
if (queue)
break;
}
@@ -293,7 +308,7 @@ struct virtqueue *vring_create_virtqueue(unsigned int 
index, unsigned int num,
 
if (!queue) {
/* Try to get a single page. You are my only hope! */
-   queue = memalign(PAGE_SIZE, vring_size(num, vring_align));
+   queue = virtio_alloc_pages(vdev, 1);
}
if (!queue)
return NULL;
@@ -303,7 +318,7 @@ struct virtqueue *vring_create_virtqueue(unsigned int 
index, unsigned int num,
 
vq = __vring_new_virtqueue(index, vring, udev);
if (!vq) {
-   free(queue);
+   virtio_free_pages(vdev, queue, DIV_ROUND_UP(vring.size, 
PAGE_SIZE));
return NULL;
}
debug("(%s): created vring @ %p for vq @ %p with num %u\n", udev->name,
@@ -314,7 +329,8 @@ struct virtqueue *vring_create_virtqueue(unsigned int 
index, unsigned int num,
 
 void vring_del_virtqueue(struct virtqueue *vq)
 {
-   free(vq->vring.desc);
+   virtio_free_pages(vq->vdev, vq->vring.desc,
+ DIV_ROUND_UP(vq->vring.size, PAGE_SIZE));
free(vq->vring_desc_shadow);
list_del(>list);
free(vq);
diff --git a/include/virtio_ring.h b/include/virtio_ring.h
index c77c212cff..8f8a55c7bd 100644
--- a/include/virtio_ring.h
+++ b/include/virtio_ring.h
@@ -86,6 +86,7 @@ struct vring_used {
 
 struct vring {
unsigned int num;
+   size_t size;
struct vring_desc *desc;
struct vring_avail *avail;
struct vring_used *used;
@@ -137,23 +138,24 @@ struct virtqueue {
 #define vring_used_event(vr)   ((vr)->avail->ring[(vr)->num])
 #define vring_avail_event(vr)  (*(__virtio16 *)&(vr)->used->ring[(vr)->num])
 
+static inline unsigned int vring_size(unsigned int num, unsigned long align)
+{
+   return ((sizeof(struct vring_desc) * num +
+   sizeof(__virtio16) * (3 + num)  + align - 1) & ~(align - 1)) +
+   sizeof(__virtio16) * 3 + sizeof(struct vring_used_elem) * num;
+}
+
 static inline void vring_init(struct vring *vr, unsigned int num, void *p,
  unsigned long align)
 {
vr->num = num;
+   vr->size = vring_size(num, align);
vr->desc = p;
vr->avail = p + num * sizeof(struct vring_desc);
vr->used = (void *)(((uintptr_t)>avail->ring[num] +
   sizeof(__virtio16) + align - 1) & ~(align - 1));
 }
 
-static inline unsigned int vring_size(unsigned int num, unsigned long align)
-{
-   return ((sizeof(struct vring_desc) * num +
-   sizeof(__virtio16) * (3 + num)  + align - 1) & ~(align - 1)) +
-   sizeof(__virtio16) * 3 + sizeof(struct vring_used_elem) * num;