This patch both compare pages and pfns based vmap, to show folios range vmap and pfn range vmap can work.
Signed-off-by: Huan Yang link@vivo.com --- drivers/dma-buf/udmabuf.c | 64 ++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 18 deletions(-)
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index f50e11f0f034..78549a9f24ca 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -556,6 +556,48 @@ static long udmabuf_ioctl_create_list(struct file *filp, unsigned long arg) return ret; }
+static void *udmabuf_vmap_by_pfns(struct udmabuf *udmabuf) +{ + unsigned long *pfns; + void *vaddr = NULL; + unsigned int i; + + pfns = kvmalloc_array(udmabuf->pagecount, sizeof(*pfns), GFP_KERNEL); + if (WARN_ON(!pfns)) + return NULL; + + for (i = 0; i < udmabuf->pagecount; ++i) + pfns[i] = folio_pfn(udmabuf->folios[i]) + + (udmabuf->offsets[i] >> PAGE_SHIFT); + + vaddr = udmabuf_vmap_pfn(pfns, udmabuf->pagecount, PAGE_KERNEL); + WARN_ON(!vaddr); + + kvfree(pfns); + return vaddr; +} + +static void *udmabuf_vmap_by_pages(struct udmabuf *udmabuf) +{ + struct page **pages; + void *vaddr = NULL; + unsigned int i; + + pages = kvmalloc_array(udmabuf->pagecount, sizeof(*pages), GFP_KERNEL); + if (WARN_ON(!pages)) + return NULL; + + for (i = 0; i < udmabuf->pagecount; ++i) + pages[i] = folio_page(udmabuf->folios[i], + udmabuf->offsets[i] >> PAGE_SHIFT); + + vaddr = vmap(pages, udmabuf->pagecount, 0, PAGE_KERNEL); + WARN_ON(!vaddr); + + kvfree(pages); + return vaddr; +} + static long udmabuf_vmap_test(struct file *filp, unsigned long arg) { struct udmabuf_vmap uv; @@ -563,7 +605,6 @@ static long udmabuf_vmap_test(struct file *filp, unsigned long arg) bool can_page = true; struct iosys_map map; struct udmabuf *ubuf; - struct page **pages; void *vaddr, *pvaddr; struct file *file; int ret = 0, i; @@ -591,31 +632,18 @@ static long udmabuf_vmap_test(struct file *filp, unsigned long arg) }
if (!can_page) - goto out_vaddr; + pvaddr = udmabuf_vmap_by_pfns(ubuf); + else + pvaddr = udmabuf_vmap_by_pages(ubuf);
- pages = kvmalloc_array(ubuf->pagecount, sizeof(*pages), GFP_KERNEL); - if (WARN_ON(!pages)) { - ret = -ENOMEM; + if (!pvaddr) goto out_vaddr; - } - - for (i = 0; i < ubuf->pagecount; ++i) - pages[i] = folio_page(ubuf->folios[i], - ubuf->offsets[i] >> PAGE_SHIFT); - - pvaddr = vmap(pages, ubuf->pagecount, 0, PAGE_KERNEL); - if (WARN_ON(!pvaddr)) { - ret = -ENOMEM; - goto out_pages; - }
// compare if pages and pfns is same? if (WARN_ON(memcmp(vaddr, pvaddr, ubuf->pagecount * PAGE_SIZE) != 0)) ret = -EINVAL;
vunmap(pvaddr); -out_pages: - kvfree(pages); out_vaddr: dma_buf_vunmap(dmabuf, &map); out: