| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * helper functions for SG DMA video4linux capture buffers |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 12 | 13 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> |
|---|
| 13 | 14 | * (c) 2006 Mauro Carvalho Chehab, <mchehab@kernel.org> |
|---|
| 14 | 15 | * (c) 2006 Ted Walther and John Sokol |
|---|
| 15 | | - * |
|---|
| 16 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 17 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 18 | | - * the Free Software Foundation; either version 2 |
|---|
| 19 | 16 | */ |
|---|
| 20 | 17 | |
|---|
| 21 | 18 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 24 | 21 | #include <linux/sched/mm.h> |
|---|
| 25 | 22 | #include <linux/slab.h> |
|---|
| 26 | 23 | #include <linux/interrupt.h> |
|---|
| 24 | +#include <linux/pgtable.h> |
|---|
| 27 | 25 | |
|---|
| 28 | 26 | #include <linux/dma-mapping.h> |
|---|
| 29 | 27 | #include <linux/vmalloc.h> |
|---|
| 30 | 28 | #include <linux/pagemap.h> |
|---|
| 31 | 29 | #include <linux/scatterlist.h> |
|---|
| 32 | 30 | #include <asm/page.h> |
|---|
| 33 | | -#include <asm/pgtable.h> |
|---|
| 34 | 31 | |
|---|
| 35 | 32 | #include <media/videobuf-dma-sg.h> |
|---|
| 36 | 33 | |
|---|
| .. | .. |
|---|
| 183 | 180 | if (rw == READ) |
|---|
| 184 | 181 | flags |= FOLL_WRITE; |
|---|
| 185 | 182 | |
|---|
| 186 | | - dprintk(1, "init user [0x%lx+0x%lx => %d pages]\n", |
|---|
| 183 | + dprintk(1, "init user [0x%lx+0x%lx => %lu pages]\n", |
|---|
| 187 | 184 | data, size, dma->nr_pages); |
|---|
| 188 | 185 | |
|---|
| 189 | | - err = get_user_pages_longterm(data & PAGE_MASK, dma->nr_pages, |
|---|
| 190 | | - flags, dma->pages, NULL); |
|---|
| 186 | + err = pin_user_pages(data & PAGE_MASK, dma->nr_pages, |
|---|
| 187 | + flags | FOLL_LONGTERM, dma->pages, NULL); |
|---|
| 191 | 188 | |
|---|
| 192 | 189 | if (err != dma->nr_pages) { |
|---|
| 193 | 190 | dma->nr_pages = (err >= 0) ? err : 0; |
|---|
| 194 | | - dprintk(1, "get_user_pages_longterm: err=%d [%d]\n", err, |
|---|
| 191 | + dprintk(1, "pin_user_pages: err=%d [%lu]\n", err, |
|---|
| 195 | 192 | dma->nr_pages); |
|---|
| 196 | 193 | return err < 0 ? err : -EINVAL; |
|---|
| 197 | 194 | } |
|---|
| .. | .. |
|---|
| 203 | 200 | { |
|---|
| 204 | 201 | int ret; |
|---|
| 205 | 202 | |
|---|
| 206 | | - down_read(¤t->mm->mmap_sem); |
|---|
| 203 | + mmap_read_lock(current->mm); |
|---|
| 207 | 204 | ret = videobuf_dma_init_user_locked(dma, direction, data, size); |
|---|
| 208 | | - up_read(¤t->mm->mmap_sem); |
|---|
| 205 | + mmap_read_unlock(current->mm); |
|---|
| 209 | 206 | |
|---|
| 210 | 207 | return ret; |
|---|
| 211 | 208 | } |
|---|
| 212 | 209 | |
|---|
| 213 | 210 | static int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, |
|---|
| 214 | | - int nr_pages) |
|---|
| 211 | + unsigned long nr_pages) |
|---|
| 215 | 212 | { |
|---|
| 216 | 213 | int i; |
|---|
| 217 | 214 | |
|---|
| 218 | | - dprintk(1, "init kernel [%d pages]\n", nr_pages); |
|---|
| 215 | + dprintk(1, "init kernel [%lu pages]\n", nr_pages); |
|---|
| 219 | 216 | |
|---|
| 220 | 217 | dma->direction = direction; |
|---|
| 221 | 218 | dma->vaddr_pages = kcalloc(nr_pages, sizeof(*dma->vaddr_pages), |
|---|
| .. | .. |
|---|
| 241 | 238 | dma->vaddr = vmap(dma->vaddr_pages, nr_pages, VM_MAP | VM_IOREMAP, |
|---|
| 242 | 239 | PAGE_KERNEL); |
|---|
| 243 | 240 | if (NULL == dma->vaddr) { |
|---|
| 244 | | - dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); |
|---|
| 241 | + dprintk(1, "vmalloc_32(%lu pages) failed\n", nr_pages); |
|---|
| 245 | 242 | goto out_free_pages; |
|---|
| 246 | 243 | } |
|---|
| 247 | 244 | |
|---|
| 248 | | - dprintk(1, "vmalloc is at addr %p, size=%d\n", |
|---|
| 245 | + dprintk(1, "vmalloc is at addr %p, size=%lu\n", |
|---|
| 249 | 246 | dma->vaddr, nr_pages << PAGE_SHIFT); |
|---|
| 250 | 247 | |
|---|
| 251 | 248 | memset(dma->vaddr, 0, nr_pages << PAGE_SHIFT); |
|---|
| .. | .. |
|---|
| 270 | 267 | } |
|---|
| 271 | 268 | |
|---|
| 272 | 269 | static int videobuf_dma_init_overlay(struct videobuf_dmabuf *dma, int direction, |
|---|
| 273 | | - dma_addr_t addr, int nr_pages) |
|---|
| 270 | + dma_addr_t addr, unsigned long nr_pages) |
|---|
| 274 | 271 | { |
|---|
| 275 | | - dprintk(1, "init overlay [%d pages @ bus 0x%lx]\n", |
|---|
| 272 | + dprintk(1, "init overlay [%lu pages @ bus 0x%lx]\n", |
|---|
| 276 | 273 | nr_pages, (unsigned long)addr); |
|---|
| 277 | 274 | dma->direction = direction; |
|---|
| 278 | 275 | |
|---|
| .. | .. |
|---|
| 352 | 349 | BUG_ON(dma->sglen); |
|---|
| 353 | 350 | |
|---|
| 354 | 351 | if (dma->pages) { |
|---|
| 355 | | - for (i = 0; i < dma->nr_pages; i++) { |
|---|
| 356 | | - if (dma->direction == DMA_FROM_DEVICE) |
|---|
| 357 | | - set_page_dirty_lock(dma->pages[i]); |
|---|
| 358 | | - put_page(dma->pages[i]); |
|---|
| 359 | | - } |
|---|
| 352 | + unpin_user_pages_dirty_lock(dma->pages, dma->nr_pages, |
|---|
| 353 | + dma->direction == DMA_FROM_DEVICE); |
|---|
| 360 | 354 | kfree(dma->pages); |
|---|
| 361 | 355 | dma->pages = NULL; |
|---|
| 362 | 356 | } |
|---|
| .. | .. |
|---|
| 506 | 500 | struct videobuf_buffer *vb, |
|---|
| 507 | 501 | struct v4l2_framebuffer *fbuf) |
|---|
| 508 | 502 | { |
|---|
| 509 | | - int err, pages; |
|---|
| 510 | | - dma_addr_t bus; |
|---|
| 511 | 503 | struct videobuf_dma_sg_memory *mem = vb->priv; |
|---|
| 504 | + unsigned long pages; |
|---|
| 505 | + dma_addr_t bus; |
|---|
| 506 | + int err; |
|---|
| 507 | + |
|---|
| 512 | 508 | BUG_ON(!mem); |
|---|
| 513 | 509 | |
|---|
| 514 | 510 | MAGIC_CHECK(mem->magic, MAGIC_SG_MEM); |
|---|
| .. | .. |
|---|
| 539 | 535 | } else { |
|---|
| 540 | 536 | /* NOTE: HACK: videobuf_iolock on V4L2_MEMORY_MMAP |
|---|
| 541 | 537 | buffers can only be called from videobuf_qbuf |
|---|
| 542 | | - we take current->mm->mmap_sem there, to prevent |
|---|
| 538 | + we take current->mm->mmap_lock there, to prevent |
|---|
| 543 | 539 | locking inversion, so don't take it here */ |
|---|
| 544 | 540 | |
|---|
| 545 | 541 | err = videobuf_dma_init_user_locked(&mem->dma, |
|---|