--- zzzz-none-000/linux-3.10.107/drivers/media/v4l2-core/videobuf-dma-sg.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/media/v4l2-core/videobuf-dma-sg.c 2021-02-04 17:41:59.000000000 +0000 @@ -145,12 +145,11 @@ } EXPORT_SYMBOL_GPL(videobuf_to_dma); -void videobuf_dma_init(struct videobuf_dmabuf *dma) +static void videobuf_dma_init(struct videobuf_dmabuf *dma) { memset(dma, 0, sizeof(*dma)); dma->magic = MAGIC_DMABUF; } -EXPORT_SYMBOL_GPL(videobuf_dma_init); static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, int direction, unsigned long data, unsigned long size) @@ -195,7 +194,7 @@ return 0; } -int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, +static int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, unsigned long data, unsigned long size) { int ret; @@ -206,18 +205,40 @@ return ret; } -EXPORT_SYMBOL_GPL(videobuf_dma_init_user); -int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, +static int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, int nr_pages) { + int i; + dprintk(1, "init kernel [%d pages]\n", nr_pages); dma->direction = direction; - dma->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); + dma->vaddr_pages = kcalloc(nr_pages, sizeof(*dma->vaddr_pages), + GFP_KERNEL); + if (!dma->vaddr_pages) + return -ENOMEM; + + dma->dma_addr = kcalloc(nr_pages, sizeof(*dma->dma_addr), GFP_KERNEL); + if (!dma->dma_addr) { + kfree(dma->vaddr_pages); + return -ENOMEM; + } + for (i = 0; i < nr_pages; i++) { + void *addr; + + addr = dma_alloc_coherent(dma->dev, PAGE_SIZE, + &(dma->dma_addr[i]), GFP_KERNEL); + if (addr == NULL) + goto out_free_pages; + + dma->vaddr_pages[i] = virt_to_page(addr); + } + dma->vaddr = vmap(dma->vaddr_pages, nr_pages, VM_MAP | VM_IOREMAP, + PAGE_KERNEL); if (NULL == dma->vaddr) { dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); - return -ENOMEM; + goto out_free_pages; } dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", @@ -228,10 +249,24 @@ dma->nr_pages = nr_pages; return 0; +out_free_pages: + while (i > 0) { + void *addr; + + i--; + addr = page_address(dma->vaddr_pages[i]); + dma_free_coherent(dma->dev, PAGE_SIZE, addr, dma->dma_addr[i]); + } + kfree(dma->dma_addr); + dma->dma_addr = NULL; + kfree(dma->vaddr_pages); + dma->vaddr_pages = NULL; + + return -ENOMEM; + } -EXPORT_SYMBOL_GPL(videobuf_dma_init_kernel); -int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, +static int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, dma_addr_t addr, int nr_pages) { dprintk(1, "init overlay [%d pages @ bus 0x%lx]\n", @@ -246,9 +281,8 @@ return 0; } -EXPORT_SYMBOL_GPL(videobuf_dma_init_overlay); -int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma) +static int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma) { MAGIC_CHECK(dma->magic, MAGIC_DMABUF); BUG_ON(0 == dma->nr_pages); @@ -290,7 +324,6 @@ return 0; } -EXPORT_SYMBOL_GPL(videobuf_dma_map); int videobuf_dma_unmap(struct device *dev, struct videobuf_dmabuf *dma) { @@ -322,8 +355,21 @@ dma->pages = NULL; } - vfree(dma->vaddr); - dma->vaddr = NULL; + if (dma->dma_addr) { + for (i = 0; i < dma->nr_pages; i++) { + void *addr; + + addr = page_address(dma->vaddr_pages[i]); + dma_free_coherent(dma->dev, PAGE_SIZE, addr, + dma->dma_addr[i]); + } + kfree(dma->dma_addr); + dma->dma_addr = NULL; + kfree(dma->vaddr_pages); + dma->vaddr_pages = NULL; + vunmap(dma->vaddr); + dma->vaddr = NULL; + } if (dma->bus_addr) dma->bus_addr = 0; @@ -461,6 +507,11 @@ MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); + if (!mem->dma.dev) + mem->dma.dev = q->dev; + else + WARN_ON(mem->dma.dev != q->dev); + switch (vb->memory) { case V4L2_MEMORY_MMAP: case V4L2_MEMORY_USERPTR: