[PATCH] MA-21654 Use dma_alloc_pages in vb2_dma_sg_alloc_compacted

From: Fang Hui
Date: Thu Sep 14 2023 - 03:41:48 EST


On system with "CONFIG_ZONE_DMA32=y", if the allocated physical address is
greater than 4G, swiotlb will be used. It will lead below defects.
1) Impact performance due to an extra memcpy.
2) May meet below error due to swiotlb_max_mapping_size()
is 256K (IO_TLB_SIZE * IO_TLB_SEGSIZE).
"swiotlb buffer is full (sz: 393216 bytes), total 65536 (slots),
used 2358 (slots)"

To avoid those defects, use dma_alloc_pages() instead of alloc_pages()
in vb2_dma_sg_alloc_compacted().

Suggested-by: Tomasz Figa <tfiga@xxxxxxxxxxxx>
Signed-off-by: Fang Hui <hui.fang@xxxxxxx>
---
drivers/media/common/videobuf2/videobuf2-dma-sg.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index 28f3fdfe23a2..b938582c68f4 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -58,7 +58,7 @@ struct vb2_dma_sg_buf {
static void vb2_dma_sg_put(void *buf_priv);

static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
- gfp_t gfp_flags)
+ gfp_t gfp_flags, struct device *dev)
{
unsigned int last_page = 0;
unsigned long size = buf->size;
@@ -67,6 +67,7 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
struct page *pages;
int order;
int i;
+ dma_addr_t dma_handle;

order = get_order(size);
/* Don't over allocate*/
@@ -75,8 +76,9 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,

pages = NULL;
while (!pages) {
- pages = alloc_pages(GFP_KERNEL | __GFP_ZERO |
- __GFP_NOWARN | gfp_flags, order);
+ pages = dma_alloc_pages(dev, PAGE_SIZE << order, &dma_handle,
+ DMA_BIDIRECTIONAL,
+ GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN | gfp_flags);
if (pages)
break;

@@ -96,6 +98,7 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
}

return 0;
+
}

static void *vb2_dma_sg_alloc(struct vb2_buffer *vb, struct device *dev,
@@ -130,7 +133,7 @@ static void *vb2_dma_sg_alloc(struct vb2_buffer *vb, struct device *dev,
if (!buf->pages)
goto fail_pages_array_alloc;

- ret = vb2_dma_sg_alloc_compacted(buf, vb->vb2_queue->gfp_flags);
+ ret = vb2_dma_sg_alloc_compacted(buf, vb->vb2_queue->gfp_flags, dev);
if (ret)
goto fail_pages_alloc;

--
2.17.1