aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/v4l2-core/videobuf2-dma-sg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/v4l2-core/videobuf2-dma-sg.c')
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-sg.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 2529b831725b..2bf13dc4df34 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -30,7 +30,12 @@ module_param(debug, int, 0644);
30 printk(KERN_DEBUG "vb2-dma-sg: " fmt, ## arg); \ 30 printk(KERN_DEBUG "vb2-dma-sg: " fmt, ## arg); \
31 } while (0) 31 } while (0)
32 32
33struct vb2_dma_sg_conf {
34 struct device *dev;
35};
36
33struct vb2_dma_sg_buf { 37struct vb2_dma_sg_buf {
38 struct device *dev;
34 void *vaddr; 39 void *vaddr;
35 struct page **pages; 40 struct page **pages;
36 int offset; 41 int offset;
@@ -89,10 +94,13 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
89static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, 94static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
90 enum dma_data_direction dma_dir, gfp_t gfp_flags) 95 enum dma_data_direction dma_dir, gfp_t gfp_flags)
91{ 96{
97 struct vb2_dma_sg_conf *conf = alloc_ctx;
92 struct vb2_dma_sg_buf *buf; 98 struct vb2_dma_sg_buf *buf;
93 int ret; 99 int ret;
94 int num_pages; 100 int num_pages;
95 101
102 if (WARN_ON(alloc_ctx == NULL))
103 return NULL;
96 buf = kzalloc(sizeof *buf, GFP_KERNEL); 104 buf = kzalloc(sizeof *buf, GFP_KERNEL);
97 if (!buf) 105 if (!buf)
98 return NULL; 106 return NULL;
@@ -118,6 +126,8 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
118 if (ret) 126 if (ret)
119 goto fail_table_alloc; 127 goto fail_table_alloc;
120 128
129 /* Prevent the device from being released while the buffer is used */
130 buf->dev = get_device(conf->dev);
121 buf->handler.refcount = &buf->refcount; 131 buf->handler.refcount = &buf->refcount;
122 buf->handler.put = vb2_dma_sg_put; 132 buf->handler.put = vb2_dma_sg_put;
123 buf->handler.arg = buf; 133 buf->handler.arg = buf;
@@ -153,6 +163,7 @@ static void vb2_dma_sg_put(void *buf_priv)
153 while (--i >= 0) 163 while (--i >= 0)
154 __free_page(buf->pages[i]); 164 __free_page(buf->pages[i]);
155 kfree(buf->pages); 165 kfree(buf->pages);
166 put_device(buf->dev);
156 kfree(buf); 167 kfree(buf);
157 } 168 }
158} 169}
@@ -356,6 +367,27 @@ const struct vb2_mem_ops vb2_dma_sg_memops = {
356}; 367};
357EXPORT_SYMBOL_GPL(vb2_dma_sg_memops); 368EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
358 369
370void *vb2_dma_sg_init_ctx(struct device *dev)
371{
372 struct vb2_dma_sg_conf *conf;
373
374 conf = kzalloc(sizeof(*conf), GFP_KERNEL);
375 if (!conf)
376 return ERR_PTR(-ENOMEM);
377
378 conf->dev = dev;
379
380 return conf;
381}
382EXPORT_SYMBOL_GPL(vb2_dma_sg_init_ctx);
383
384void vb2_dma_sg_cleanup_ctx(void *alloc_ctx)
385{
386 if (!IS_ERR_OR_NULL(alloc_ctx))
387 kfree(alloc_ctx);
388}
389EXPORT_SYMBOL_GPL(vb2_dma_sg_cleanup_ctx);
390
359MODULE_DESCRIPTION("dma scatter/gather memory handling routines for videobuf2"); 391MODULE_DESCRIPTION("dma scatter/gather memory handling routines for videobuf2");
360MODULE_AUTHOR("Andrzej Pietrasiewicz"); 392MODULE_AUTHOR("Andrzej Pietrasiewicz");
361MODULE_LICENSE("GPL"); 393MODULE_LICENSE("GPL");