[RFC PATCH 1/6] udmabuf: try fix udmabuf vmap
From: Huan Yang
Date: Thu Mar 27 2025 - 05:30:26 EST
vmap_pfn design to only allow none page based pfn map.
This patch try simple copy pfn vmap code to fix it.
Fix vunmap_udmabuf fix match with vmap_udmabuf, use vunmap.
Signed-off-by: Huan Yang <link@xxxxxxxx>
---
drivers/dma-buf/udmabuf.c | 49 +++++++++++++++++++++++++++++++++++----
1 file changed, 45 insertions(+), 4 deletions(-)
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index cc7398cc17d6..2dfe639230dc 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -106,6 +106,49 @@ static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
return 0;
}
+struct udmabuf_pfn_data {
+ unsigned long *pfns;
+ pgprot_t prot;
+ unsigned int idx;
+};
+
+static int udmabuf_vmap_pfn_apply(pte_t *pte, unsigned long addr, void *private)
+{
+ struct udmabuf_pfn_data *data = private;
+ pte_t ptent;
+
+ ptent = pte_mkspecial(pfn_pte(data->pfns[data->idx], data->prot));
+ set_pte_at(&init_mm, addr, pte, ptent);
+
+ data->idx++;
+ return 0;
+}
+
+static void *udmabuf_vmap_pfn(unsigned long *pfns, unsigned int count,
+ pgprot_t prot)
+{
+ struct udmabuf_pfn_data data = { .pfns = pfns,
+ .prot = pgprot_nx(prot) };
+ struct vm_struct *area;
+
+ area = get_vm_area_caller(count * PAGE_SIZE, 0,
+ __builtin_return_address(0));
+ if (!area)
+ return NULL;
+
+ if (apply_to_page_range(&init_mm, (unsigned long)area->addr,
+ count * PAGE_SIZE, udmabuf_vmap_pfn_apply,
+ &data)) {
+ free_vm_area(area);
+ return NULL;
+ }
+
+ flush_cache_vmap((unsigned long)area->addr,
+ (unsigned long)area->addr + count * PAGE_SIZE);
+
+ return area->addr;
+}
+
static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map)
{
struct udmabuf *ubuf = buf->priv;
@@ -130,7 +173,7 @@ static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map)
pfns[pg] = pfn;
}
- vaddr = vmap_pfn(pfns, ubuf->pagecount, PAGE_KERNEL);
+ vaddr = udmabuf_vmap_pfn(pfns, ubuf->pagecount, PAGE_KERNEL);
kvfree(pfns);
if (!vaddr)
return -EINVAL;
@@ -141,11 +184,9 @@ static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map)
static void vunmap_udmabuf(struct dma_buf *buf, struct iosys_map *map)
{
- struct udmabuf *ubuf = buf->priv;
-
dma_resv_assert_held(buf->resv);
- vm_unmap_ram(map->vaddr, ubuf->pagecount);
+ vunmap(map->vaddr);
}
static struct sg_table *get_sg_table(struct device *dev, struct dma_buf *buf,
--
2.48.1