aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/videobuf-dma-sg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/videobuf-dma-sg.c')
-rw-r--r--drivers/media/video/videobuf-dma-sg.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
index 0939ede831ab..05dd38343fa3 100644
--- a/drivers/media/video/videobuf-dma-sg.c
+++ b/drivers/media/video/videobuf-dma-sg.c
@@ -134,8 +134,8 @@ void videobuf_dma_init(struct videobuf_dmabuf *dma)
134 dma->magic = MAGIC_DMABUF; 134 dma->magic = MAGIC_DMABUF;
135} 135}
136 136
137int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, 137static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
138 unsigned long data, unsigned long size) 138 int direction, unsigned long data, unsigned long size)
139{ 139{
140 unsigned long first,last; 140 unsigned long first,last;
141 int err, rw = 0; 141 int err, rw = 0;
@@ -160,12 +160,12 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
160 160
161 dma->varea = (void *) data; 161 dma->varea = (void *) data;
162 162
163 down_read(&current->mm->mmap_sem); 163
164 err = get_user_pages(current,current->mm, 164 err = get_user_pages(current,current->mm,
165 data & PAGE_MASK, dma->nr_pages, 165 data & PAGE_MASK, dma->nr_pages,
166 rw == READ, 1, /* force */ 166 rw == READ, 1, /* force */
167 dma->pages, NULL); 167 dma->pages, NULL);
168 up_read(&current->mm->mmap_sem); 168
169 if (err != dma->nr_pages) { 169 if (err != dma->nr_pages) {
170 dma->nr_pages = (err >= 0) ? err : 0; 170 dma->nr_pages = (err >= 0) ? err : 0;
171 dprintk(1,"get_user_pages: err=%d [%d]\n",err,dma->nr_pages); 171 dprintk(1,"get_user_pages: err=%d [%d]\n",err,dma->nr_pages);
@@ -174,6 +174,17 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
174 return 0; 174 return 0;
175} 175}
176 176
177int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction,
178 unsigned long data, unsigned long size)
179{
180 int ret;
181 down_read(&current->mm->mmap_sem);
182 ret = videobuf_dma_init_user_locked(dma, direction, data, size);
183 up_read(&current->mm->mmap_sem);
184
185 return ret;
186}
187
177int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, 188int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction,
178 int nr_pages) 189 int nr_pages)
179{ 190{
@@ -469,13 +480,24 @@ static int __videobuf_iolock (struct videobuf_queue* q,
469 pages ); 480 pages );
470 if (0 != err) 481 if (0 != err)
471 return err; 482 return err;
472 } else { 483 } else if (vb->memory == V4L2_MEMORY_USERPTR) {
473 /* dma directly to userspace */ 484 /* dma directly to userspace */
474 err = videobuf_dma_init_user( &mem->dma, 485 err = videobuf_dma_init_user( &mem->dma,
475 PCI_DMA_FROMDEVICE, 486 PCI_DMA_FROMDEVICE,
476 vb->baddr,vb->bsize ); 487 vb->baddr,vb->bsize );
477 if (0 != err) 488 if (0 != err)
478 return err; 489 return err;
490 } else {
491 /* NOTE: HACK: videobuf_iolock on V4L2_MEMORY_MMAP
492 buffers can only be called from videobuf_qbuf
493 we take current->mm->mmap_sem there, to prevent
494 locking inversion, so don't take it here */
495
496 err = videobuf_dma_init_user_locked(&mem->dma,
497 PCI_DMA_FROMDEVICE,
498 vb->baddr, vb->bsize);
499 if (0 != err)
500 return err;
479 } 501 }
480 break; 502 break;
481 case V4L2_MEMORY_OVERLAY: 503 case V4L2_MEMORY_OVERLAY: