Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
[linux-block.git] / drivers / media / v4l2-core / videobuf-dma-contig.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * helper functions for physically contiguous capture buffers
4  *
5  * The functions support hardware lacking scatter gather support
6  * (i.e. the buffers must be linear in physical memory)
7  *
8  * Copyright (c) 2008 Magnus Damm
9  *
10  * Based on videobuf-vmalloc.c,
11  * (c) 2007 Mauro Carvalho Chehab, <mchehab@kernel.org>
12  */
13
14 #include <linux/init.h>
15 #include <linux/module.h>
16 #include <linux/mm.h>
17 #include <linux/pagemap.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/sched.h>
20 #include <linux/slab.h>
21 #include <media/videobuf-dma-contig.h>
22
23 struct videobuf_dma_contig_memory {
24         u32 magic;
25         void *vaddr;
26         dma_addr_t dma_handle;
27         unsigned long size;
28 };
29
30 #define MAGIC_DC_MEM 0x0733ac61
31 #define MAGIC_CHECK(is, should)                                             \
32         if (unlikely((is) != (should))) {                                   \
33                 pr_err("magic mismatch: %x expected %x\n", (is), (should)); \
34                 BUG();                                                      \
35         }
36
37 static int __videobuf_dc_alloc(struct device *dev,
38                                struct videobuf_dma_contig_memory *mem,
39                                unsigned long size)
40 {
41         mem->size = size;
42         mem->vaddr = dma_alloc_coherent(dev, mem->size, &mem->dma_handle,
43                                         GFP_KERNEL);
44         if (!mem->vaddr) {
45                 dev_err(dev, "memory alloc size %ld failed\n", mem->size);
46                 return -ENOMEM;
47         }
48
49         dev_dbg(dev, "dma mapped data is at %p (%ld)\n", mem->vaddr, mem->size);
50
51         return 0;
52 }
53
54 static void __videobuf_dc_free(struct device *dev,
55                                struct videobuf_dma_contig_memory *mem)
56 {
57         dma_free_coherent(dev, mem->size, mem->vaddr, mem->dma_handle);
58
59         mem->vaddr = NULL;
60 }
61
62 static void videobuf_vm_open(struct vm_area_struct *vma)
63 {
64         struct videobuf_mapping *map = vma->vm_private_data;
65
66         dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
67                 map, map->count, vma->vm_start, vma->vm_end);
68
69         map->count++;
70 }
71
72 static void videobuf_vm_close(struct vm_area_struct *vma)
73 {
74         struct videobuf_mapping *map = vma->vm_private_data;
75         struct videobuf_queue *q = map->q;
76         int i;
77
78         dev_dbg(q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
79                 map, map->count, vma->vm_start, vma->vm_end);
80
81         map->count--;
82         if (0 == map->count) {
83                 struct videobuf_dma_contig_memory *mem;
84
85                 dev_dbg(q->dev, "munmap %p q=%p\n", map, q);
86                 videobuf_queue_lock(q);
87
88                 /* We need first to cancel streams, before unmapping */
89                 if (q->streaming)
90                         videobuf_queue_cancel(q);
91
92                 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
93                         if (NULL == q->bufs[i])
94                                 continue;
95
96                         if (q->bufs[i]->map != map)
97                                 continue;
98
99                         mem = q->bufs[i]->priv;
100                         if (mem) {
101                                 /* This callback is called only if kernel has
102                                    allocated memory and this memory is mmapped.
103                                    In this case, memory should be freed,
104                                    in order to do memory unmap.
105                                  */
106
107                                 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
108
109                                 /* vfree is not atomic - can't be
110                                    called with IRQ's disabled
111                                  */
112                                 dev_dbg(q->dev, "buf[%d] freeing %p\n",
113                                         i, mem->vaddr);
114
115                                 __videobuf_dc_free(q->dev, mem);
116                                 mem->vaddr = NULL;
117                         }
118
119                         q->bufs[i]->map = NULL;
120                         q->bufs[i]->baddr = 0;
121                 }
122
123                 kfree(map);
124
125                 videobuf_queue_unlock(q);
126         }
127 }
128
129 static const struct vm_operations_struct videobuf_vm_ops = {
130         .open   = videobuf_vm_open,
131         .close  = videobuf_vm_close,
132 };
133
134 /**
135  * videobuf_dma_contig_user_put() - reset pointer to user space buffer
136  * @mem: per-buffer private videobuf-dma-contig data
137  *
138  * This function resets the user space pointer
139  */
140 static void videobuf_dma_contig_user_put(struct videobuf_dma_contig_memory *mem)
141 {
142         mem->dma_handle = 0;
143         mem->size = 0;
144 }
145
146 /**
147  * videobuf_dma_contig_user_get() - setup user space memory pointer
148  * @mem: per-buffer private videobuf-dma-contig data
149  * @vb: video buffer to map
150  *
151  * This function validates and sets up a pointer to user space memory.
152  * Only physically contiguous pfn-mapped memory is accepted.
153  *
154  * Returns 0 if successful.
155  */
156 static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem,
157                                         struct videobuf_buffer *vb)
158 {
159         unsigned long untagged_baddr = untagged_addr(vb->baddr);
160         struct mm_struct *mm = current->mm;
161         struct vm_area_struct *vma;
162         unsigned long prev_pfn, this_pfn;
163         unsigned long pages_done, user_address;
164         unsigned int offset;
165         int ret;
166
167         offset = untagged_baddr & ~PAGE_MASK;
168         mem->size = PAGE_ALIGN(vb->size + offset);
169         ret = -EINVAL;
170
171         mmap_read_lock(mm);
172
173         vma = find_vma(mm, untagged_baddr);
174         if (!vma)
175                 goto out_up;
176
177         if ((untagged_baddr + mem->size) > vma->vm_end)
178                 goto out_up;
179
180         pages_done = 0;
181         prev_pfn = 0; /* kill warning */
182         user_address = untagged_baddr;
183
184         while (pages_done < (mem->size >> PAGE_SHIFT)) {
185                 ret = follow_pfn(vma, user_address, &this_pfn);
186                 if (ret)
187                         break;
188
189                 if (pages_done == 0)
190                         mem->dma_handle = (this_pfn << PAGE_SHIFT) + offset;
191                 else if (this_pfn != (prev_pfn + 1))
192                         ret = -EFAULT;
193
194                 if (ret)
195                         break;
196
197                 prev_pfn = this_pfn;
198                 user_address += PAGE_SIZE;
199                 pages_done++;
200         }
201
202 out_up:
203         mmap_read_unlock(current->mm);
204
205         return ret;
206 }
207
208 static struct videobuf_buffer *__videobuf_alloc(size_t size)
209 {
210         struct videobuf_dma_contig_memory *mem;
211         struct videobuf_buffer *vb;
212
213         vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
214         if (vb) {
215                 vb->priv = ((char *)vb) + size;
216                 mem = vb->priv;
217                 mem->magic = MAGIC_DC_MEM;
218         }
219
220         return vb;
221 }
222
223 static void *__videobuf_to_vaddr(struct videobuf_buffer *buf)
224 {
225         struct videobuf_dma_contig_memory *mem = buf->priv;
226
227         BUG_ON(!mem);
228         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
229
230         return mem->vaddr;
231 }
232
233 static int __videobuf_iolock(struct videobuf_queue *q,
234                              struct videobuf_buffer *vb,
235                              struct v4l2_framebuffer *fbuf)
236 {
237         struct videobuf_dma_contig_memory *mem = vb->priv;
238
239         BUG_ON(!mem);
240         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
241
242         switch (vb->memory) {
243         case V4L2_MEMORY_MMAP:
244                 dev_dbg(q->dev, "%s memory method MMAP\n", __func__);
245
246                 /* All handling should be done by __videobuf_mmap_mapper() */
247                 if (!mem->vaddr) {
248                         dev_err(q->dev, "memory is not allocated/mmapped.\n");
249                         return -EINVAL;
250                 }
251                 break;
252         case V4L2_MEMORY_USERPTR:
253                 dev_dbg(q->dev, "%s memory method USERPTR\n", __func__);
254
255                 /* handle pointer from user space */
256                 if (vb->baddr)
257                         return videobuf_dma_contig_user_get(mem, vb);
258
259                 /* allocate memory for the read() method */
260                 if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size)))
261                         return -ENOMEM;
262                 break;
263         case V4L2_MEMORY_OVERLAY:
264         default:
265                 dev_dbg(q->dev, "%s memory method OVERLAY/unknown\n", __func__);
266                 return -EINVAL;
267         }
268
269         return 0;
270 }
271
272 static int __videobuf_mmap_mapper(struct videobuf_queue *q,
273                                   struct videobuf_buffer *buf,
274                                   struct vm_area_struct *vma)
275 {
276         struct videobuf_dma_contig_memory *mem;
277         struct videobuf_mapping *map;
278         int retval;
279
280         dev_dbg(q->dev, "%s\n", __func__);
281
282         /* create mapping + update buffer list */
283         map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
284         if (!map)
285                 return -ENOMEM;
286
287         buf->map = map;
288         map->q = q;
289
290         buf->baddr = vma->vm_start;
291
292         mem = buf->priv;
293         BUG_ON(!mem);
294         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
295
296         if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize)))
297                 goto error;
298
299         /* the "vm_pgoff" is just used in v4l2 to find the
300          * corresponding buffer data structure which is allocated
301          * earlier and it does not mean the offset from the physical
302          * buffer start address as usual. So set it to 0 to pass
303          * the sanity check in dma_mmap_coherent().
304          */
305         vma->vm_pgoff = 0;
306         retval = dma_mmap_coherent(q->dev, vma, mem->vaddr, mem->dma_handle,
307                                    mem->size);
308         if (retval) {
309                 dev_err(q->dev, "mmap: remap failed with error %d. ",
310                         retval);
311                 dma_free_coherent(q->dev, mem->size,
312                                   mem->vaddr, mem->dma_handle);
313                 goto error;
314         }
315
316         vma->vm_ops = &videobuf_vm_ops;
317         vm_flags_set(vma, VM_DONTEXPAND);
318         vma->vm_private_data = map;
319
320         dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
321                 map, q, vma->vm_start, vma->vm_end,
322                 (long int)buf->bsize, vma->vm_pgoff, buf->i);
323
324         videobuf_vm_open(vma);
325
326         return 0;
327
328 error:
329         kfree(map);
330         return -ENOMEM;
331 }
332
333 static struct videobuf_qtype_ops qops = {
334         .magic          = MAGIC_QTYPE_OPS,
335         .alloc_vb       = __videobuf_alloc,
336         .iolock         = __videobuf_iolock,
337         .mmap_mapper    = __videobuf_mmap_mapper,
338         .vaddr          = __videobuf_to_vaddr,
339 };
340
341 void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
342                                     const struct videobuf_queue_ops *ops,
343                                     struct device *dev,
344                                     spinlock_t *irqlock,
345                                     enum v4l2_buf_type type,
346                                     enum v4l2_field field,
347                                     unsigned int msize,
348                                     void *priv,
349                                     struct mutex *ext_lock)
350 {
351         videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
352                                  priv, &qops, ext_lock);
353 }
354 EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init);
355
356 dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf)
357 {
358         struct videobuf_dma_contig_memory *mem = buf->priv;
359
360         BUG_ON(!mem);
361         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
362
363         return mem->dma_handle;
364 }
365 EXPORT_SYMBOL_GPL(videobuf_to_dma_contig);
366
367 void videobuf_dma_contig_free(struct videobuf_queue *q,
368                               struct videobuf_buffer *buf)
369 {
370         struct videobuf_dma_contig_memory *mem = buf->priv;
371
372         /* mmapped memory can't be freed here, otherwise mmapped region
373            would be released, while still needed. In this case, the memory
374            release should happen inside videobuf_vm_close().
375            So, it should free memory only if the memory were allocated for
376            read() operation.
377          */
378         if (buf->memory != V4L2_MEMORY_USERPTR)
379                 return;
380
381         if (!mem)
382                 return;
383
384         MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
385
386         /* handle user space pointer case */
387         if (buf->baddr) {
388                 videobuf_dma_contig_user_put(mem);
389                 return;
390         }
391
392         /* read() method */
393         if (mem->vaddr) {
394                 __videobuf_dc_free(q->dev, mem);
395                 mem->vaddr = NULL;
396         }
397 }
398 EXPORT_SYMBOL_GPL(videobuf_dma_contig_free);
399
400 MODULE_DESCRIPTION("helper module to manage video4linux dma contig buffers");
401 MODULE_AUTHOR("Magnus Damm");
402 MODULE_LICENSE("GPL");