.. | .. |
---|
| 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, |
---|