Blame view

drivers/media/video/videobuf-vmalloc.c 8.33 KB
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
1
2
3
  /*
   * helper functions for vmalloc video4linux capture buffers
   *
5d6aaf50e   Magnus Damm   V4L/DVB (8340): v...
4
   * The functions expect the hardware being able to scatter gather
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   * (i.e. the buffers are not linear in physical memory, but fragmented
   * into PAGE_SIZE chunks).  They also assume the driver does not need
   * to touch the video data.
   *
   * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2
   */
  
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/slab.h>
  #include <linux/interrupt.h>
  
  #include <linux/pci.h>
  #include <linux/vmalloc.h>
  #include <linux/pagemap.h>
  #include <asm/page.h>
  #include <asm/pgtable.h>
  
  #include <media/videobuf-vmalloc.h>
  
  #define MAGIC_DMABUF   0x17760309
  #define MAGIC_VMAL_MEM 0x18221223
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
32
33
34
35
36
37
38
  #define MAGIC_CHECK(is, should)						\
  	if (unlikely((is) != (should))) {				\
  		printk(KERN_ERR "magic mismatch: %x (expected %x)
  ",	\
  				is, should);				\
  		BUG();							\
  	}
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
39

ff699e6bd   Douglas Schilling Landgraf   V4L/DVB (7094): ...
40
  static int debug;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
41
42
43
44
45
  module_param(debug, int, 0644);
  
  MODULE_DESCRIPTION("helper module to manage video4linux vmalloc buffers");
  MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
  MODULE_LICENSE("GPL");
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
46
47
48
  #define dprintk(level, fmt, arg...)					\
  	if (debug >= level)						\
  		printk(KERN_DEBUG "vbuf-vmalloc: " fmt , ## arg)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
49
50
51
  
  
  /***************************************************************************/
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
52
  static void videobuf_vm_open(struct vm_area_struct *vma)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
53
54
  {
  	struct videobuf_mapping *map = vma->vm_private_data;
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
55
56
57
  	dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]
  ", map,
  		map->count, vma->vm_start, vma->vm_end);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
58
59
60
  
  	map->count++;
  }
aaea56afc   Mauro Carvalho Chehab   V4L/DVB (7553): v...
61
  static void videobuf_vm_close(struct vm_area_struct *vma)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
62
63
64
  {
  	struct videobuf_mapping *map = vma->vm_private_data;
  	struct videobuf_queue *q = map->q;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
65
  	int i;
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
66
67
  	dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]
  ", map,
aaea56afc   Mauro Carvalho Chehab   V4L/DVB (7553): v...
68
  		map->count, vma->vm_start, vma->vm_end);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
69
70
71
  
  	map->count--;
  	if (0 == map->count) {
aaea56afc   Mauro Carvalho Chehab   V4L/DVB (7553): v...
72
73
74
75
  		struct videobuf_vmalloc_memory *mem;
  
  		dprintk(1, "munmap %p q=%p
  ", map, q);
973976878   Hans Verkuil   V4L/DVB: videobuf...
76
  		videobuf_queue_lock(q);
aa9479ed5   Mauro Carvalho Chehab   V4L/DVB (7561): v...
77
78
79
80
  
  		/* We need first to cancel streams, before unmapping */
  		if (q->streaming)
  			videobuf_queue_cancel(q);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
81
82
83
  		for (i = 0; i < VIDEO_MAX_FRAME; i++) {
  			if (NULL == q->bufs[i])
  				continue;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
84

851c0c96b   Mauro Carvalho Chehab   V4L/DVB (6266): v...
85
  			if (q->bufs[i]->map != map)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
86
  				continue;
123f8ef64   Mauro Carvalho Chehab   V4L/DVB (6263): F...
87

aaea56afc   Mauro Carvalho Chehab   V4L/DVB (7553): v...
88
89
90
91
92
93
94
  			mem = q->bufs[i]->priv;
  			if (mem) {
  				/* This callback is called only if kernel has
  				   allocated memory and this memory is mmapped.
  				   In this case, memory should be freed,
  				   in order to do memory unmap.
  				 */
aa9479ed5   Mauro Carvalho Chehab   V4L/DVB (7561): v...
95

aaea56afc   Mauro Carvalho Chehab   V4L/DVB (7553): v...
96
  				MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
aa9479ed5   Mauro Carvalho Chehab   V4L/DVB (7561): v...
97
98
99
100
101
102
  
  				/* vfree is not atomic - can't be
  				   called with IRQ's disabled
  				 */
  				dprintk(1, "%s: buf[%d] freeing (%p)
  ",
bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
103
  					__func__, i, mem->vaddr);
aa9479ed5   Mauro Carvalho Chehab   V4L/DVB (7561): v...
104

bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
105
106
  				vfree(mem->vaddr);
  				mem->vaddr = NULL;
aaea56afc   Mauro Carvalho Chehab   V4L/DVB (7553): v...
107
  			}
851c0c96b   Mauro Carvalho Chehab   V4L/DVB (6266): v...
108
  			q->bufs[i]->map   = NULL;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
109
  			q->bufs[i]->baddr = 0;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
110
  		}
aa9479ed5   Mauro Carvalho Chehab   V4L/DVB (7561): v...
111

87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
112
  		kfree(map);
aa9479ed5   Mauro Carvalho Chehab   V4L/DVB (7561): v...
113

973976878   Hans Verkuil   V4L/DVB: videobuf...
114
  		videobuf_queue_unlock(q);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
115
  	}
aa9479ed5   Mauro Carvalho Chehab   V4L/DVB (7561): v...
116

87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
117
118
  	return;
  }
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
119
  static const struct vm_operations_struct videobuf_vm_ops = {
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
120
121
122
123
124
125
126
127
128
129
130
  	.open     = videobuf_vm_open,
  	.close    = videobuf_vm_close,
  };
  
  /* ---------------------------------------------------------------------
   * vmalloc handlers for the generic methods
   */
  
  /* Allocated area consists on 3 parts:
  	struct video_buffer
  	struct <driver>_buffer (cx88_buffer, saa7134_buf, ...)
0705135e5   Guennadi Liakhovetski   V4L/DVB (7237): C...
131
  	struct videobuf_dma_sg_memory
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
132
   */
33c38283f   Pawel Osciak   V4L/DVB: videobuf...
133
  static struct videobuf_buffer *__videobuf_alloc_vb(size_t size)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
134
  {
384b835ae   Brandon Philips   V4L/DVB (7150): [...
135
  	struct videobuf_vmalloc_memory *mem;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
136
  	struct videobuf_buffer *vb;
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
137
  	vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
bee527f97   Pawel Osciak   V4L/DVB: videobuf...
138
139
  	if (!vb)
  		return vb;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
140

7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
141
142
  	mem = vb->priv = ((char *)vb) + size;
  	mem->magic = MAGIC_VMAL_MEM;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
143

7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
144
145
146
147
  	dprintk(1, "%s: allocated at %p(%ld+%ld) & %p(%ld)
  ",
  		__func__, vb, (long)sizeof(*vb), (long)size - sizeof(*vb),
  		mem, (long)sizeof(*mem));
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
148
149
150
  
  	return vb;
  }
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
151
152
153
  static int __videobuf_iolock(struct videobuf_queue *q,
  			     struct videobuf_buffer *vb,
  			     struct v4l2_framebuffer *fbuf)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
154
  {
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
155
  	struct videobuf_vmalloc_memory *mem = vb->priv;
aa9479ed5   Mauro Carvalho Chehab   V4L/DVB (7561): v...
156
  	int pages;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
157
158
  
  	BUG_ON(!mem);
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
159
  	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
160

968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
161
162
163
164
  	switch (vb->memory) {
  	case V4L2_MEMORY_MMAP:
  		dprintk(1, "%s memory method MMAP
  ", __func__);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
165

968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
166
  		/* All handling should be done by __videobuf_mmap_mapper() */
bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
167
  		if (!mem->vaddr) {
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
168
169
170
171
172
173
  			printk(KERN_ERR "memory is not alloced/mmapped.
  ");
  			return -EINVAL;
  		}
  		break;
  	case V4L2_MEMORY_USERPTR:
aa9479ed5   Mauro Carvalho Chehab   V4L/DVB (7561): v...
174
  		pages = PAGE_ALIGN(vb->size);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
175

968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
176
177
  		dprintk(1, "%s memory method USERPTR
  ", __func__);
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
178
179
180
181
182
  		if (vb->baddr) {
  			printk(KERN_ERR "USERPTR is currently not supported
  ");
  			return -EINVAL;
  		}
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
183

968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
184
  		/* The only USERPTR currently supported is the one needed for
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
185
  		 * read() method.
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
186
  		 */
bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
187
188
  		mem->vaddr = vmalloc_user(pages);
  		if (!mem->vaddr) {
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
189
190
191
  			printk(KERN_ERR "vmalloc (%d pages) failed
  ", pages);
  			return -ENOMEM;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
192
  		}
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
193
194
  		dprintk(1, "vmalloc is at addr %p (%d pages)
  ",
bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
195
  			mem->vaddr, pages);
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
196
197
198
199
200
201
202
203
204
205
  
  #if 0
  		int rc;
  		/* Kernel userptr is used also by read() method. In this case,
  		   there's no need to remap, since data will be copied to user
  		 */
  		if (!vb->baddr)
  			return 0;
  
  		/* FIXME: to properly support USERPTR, remap should occur.
de1e575db   Hans Verkuil   V4L/DVB (8525): f...
206
  		   The code below won't work, since mem->vma = NULL
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
207
208
209
210
  		 */
  		/* Try to remap memory */
  		rc = remap_vmalloc_range(mem->vma, (void *)vb->baddr, 0);
  		if (rc < 0) {
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
211
  			printk(KERN_ERR "mmap: remap failed with error %d", rc);
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
212
213
214
215
216
  			return -ENOMEM;
  		}
  #endif
  
  		break;
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
217
218
219
220
221
222
223
224
225
  	case V4L2_MEMORY_OVERLAY:
  	default:
  		dprintk(1, "%s memory method OVERLAY/unknown
  ", __func__);
  
  		/* Currently, doesn't support V4L2_MEMORY_OVERLAY */
  		printk(KERN_ERR "Memory method currently unsupported.
  ");
  		return -EINVAL;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
226
227
228
229
  	}
  
  	return 0;
  }
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
230
  static int __videobuf_mmap_mapper(struct videobuf_queue *q,
0b62b7377   Hans Verkuil   V4L/DVB: v4l vide...
231
232
  				  struct videobuf_buffer *buf,
  				  struct vm_area_struct *vma)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
233
  {
384b835ae   Brandon Philips   V4L/DVB (7150): [...
234
  	struct videobuf_vmalloc_memory *mem;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
235
  	struct videobuf_mapping *map;
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
236
  	int retval, pages;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
237

968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
238
239
  	dprintk(1, "%s
  ", __func__);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
240
241
  
  	/* create mapping + update buffer list */
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
242
  	map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
243
244
  	if (NULL == map)
  		return -ENOMEM;
0b62b7377   Hans Verkuil   V4L/DVB: v4l vide...
245
  	buf->map = map;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
246
  	map->q     = q;
0b62b7377   Hans Verkuil   V4L/DVB: v4l vide...
247
  	buf->baddr = vma->vm_start;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
248

0b62b7377   Hans Verkuil   V4L/DVB: v4l vide...
249
  	mem = buf->priv;
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
250
251
  	BUG_ON(!mem);
  	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
252

968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
253
  	pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
254
255
  	mem->vaddr = vmalloc_user(pages);
  	if (!mem->vaddr) {
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
256
257
258
259
  		printk(KERN_ERR "vmalloc (%d pages) failed
  ", pages);
  		goto error;
  	}
bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
260
261
  	dprintk(1, "vmalloc is at addr %p (%d pages)
  ", mem->vaddr, pages);
851c0c96b   Mauro Carvalho Chehab   V4L/DVB (6266): v...
262

87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
263
  	/* Try to remap memory */
bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
264
  	retval = remap_vmalloc_range(vma, mem->vaddr, 0);
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
265
266
  	if (retval < 0) {
  		printk(KERN_ERR "mmap: remap failed with error %d. ", retval);
bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
267
  		vfree(mem->vaddr);
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
268
  		goto error;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
269
  	}
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
270
271
272
  	vma->vm_ops          = &videobuf_vm_ops;
  	vma->vm_flags       |= VM_DONTEXPAND | VM_RESERVED;
  	vma->vm_private_data = map;
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
273
274
  	dprintk(1, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d
  ",
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
275
  		map, q, vma->vm_start, vma->vm_end,
0b62b7377   Hans Verkuil   V4L/DVB: v4l vide...
276
277
  		(long int)buf->bsize,
  		vma->vm_pgoff, buf->i);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
278
279
  
  	videobuf_vm_open(vma);
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
280
281
282
283
284
285
  	return 0;
  
  error:
  	mem = NULL;
  	kfree(map);
  	return -ENOMEM;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
286
  }
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
287
288
  static struct videobuf_qtype_ops qops = {
  	.magic        = MAGIC_QTYPE_OPS,
33c38283f   Pawel Osciak   V4L/DVB: videobuf...
289
  	.alloc_vb     = __videobuf_alloc_vb,
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
290
  	.iolock       = __videobuf_iolock,
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
291
  	.mmap_mapper  = __videobuf_mmap_mapper,
037c75eb1   Hans Verkuil   V4L/DVB: v4l vide...
292
  	.vaddr        = videobuf_to_vmalloc,
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
293
  };
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
294
  void videobuf_queue_vmalloc_init(struct videobuf_queue *q,
38a54f35a   Jonathan Corbet   V4L/DVB (13377): ...
295
  			 const struct videobuf_queue_ops *ops,
f8b0bca1a   Jonathan Corbet   V4L/DVB (13417): ...
296
  			 struct device *dev,
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
297
298
299
300
  			 spinlock_t *irqlock,
  			 enum v4l2_buf_type type,
  			 enum v4l2_field field,
  			 unsigned int msize,
08bff03ed   Hans Verkuil   V4L/DVB: videobuf...
301
302
  			 void *priv,
  			 struct mutex *ext_lock)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
303
  {
d4cae5a50   Mauro Carvalho Chehab   V4L/DVB (6292): v...
304
  	videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
08bff03ed   Hans Verkuil   V4L/DVB: videobuf...
305
  				 priv, &qops, ext_lock);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
306
  }
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
307
  EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init);
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
308
  void *videobuf_to_vmalloc(struct videobuf_buffer *buf)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
309
  {
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
310
311
312
  	struct videobuf_vmalloc_memory *mem = buf->priv;
  	BUG_ON(!mem);
  	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
313

bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
314
  	return mem->vaddr;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
315
316
  }
  EXPORT_SYMBOL_GPL(videobuf_to_vmalloc);
7a02264ca   Pawel Osciak   V4L/DVB: v4l: vid...
317
  void videobuf_vmalloc_free(struct videobuf_buffer *buf)
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
318
  {
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
319
  	struct videobuf_vmalloc_memory *mem = buf->priv;
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
320

aaea56afc   Mauro Carvalho Chehab   V4L/DVB (7553): v...
321
322
323
324
325
326
  	/* mmapped memory can't be freed here, otherwise mmapped region
  	   would be released, while still needed. In this case, the memory
  	   release should happen inside videobuf_vm_close().
  	   So, it should free memory only if the memory were allocated for
  	   read() operation.
  	 */
5993a663a   Mauro Carvalho Chehab   V4L/DVB (10305): ...
327
  	if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
aaea56afc   Mauro Carvalho Chehab   V4L/DVB (7553): v...
328
  		return;
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
329
330
331
332
  	if (!mem)
  		return;
  
  	MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);
87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
333

bb6dbe748   Laurent Pinchart   V4L/DVB: videobuf...
334
335
  	vfree(mem->vaddr);
  	mem->vaddr = NULL;
968ced78a   Mauro Carvalho Chehab   V4L/DVB (7552): v...
336

87b9ad070   Mauro Carvalho Chehab   V4L/DVB (6254): A...
337
338
339
  	return;
  }
  EXPORT_SYMBOL_GPL(videobuf_vmalloc_free);