Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 285427
b: refs/heads/master
c: b037c0f
h: refs/heads/master
i:
  285425: be63425
  285423: 45b8c3e
v: v3
  • Loading branch information
Marek Szyprowski authored and Mauro Carvalho Chehab committed Dec 30, 2011
1 parent 953612a commit 420f543
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 30 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f0b7c7fc6f15e823cb4a5d225d9ef28b884ab6ec
refs/heads/master: b037c0fde22b1d3cd0b3c3717d28e54619fc1592
51 changes: 42 additions & 9 deletions trunk/drivers/media/video/videobuf2-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1082,46 +1082,76 @@ EXPORT_SYMBOL_GPL(vb2_prepare_buf);
*/
int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
{
struct rw_semaphore *mmap_sem = NULL;
struct vb2_buffer *vb;
int ret;
int ret = 0;

/*
* In case of user pointer buffers vb2 allocator needs to get direct
* access to userspace pages. This requires getting read access on
* mmap semaphore in the current process structure. The same
* semaphore is taken before calling mmap operation, while both mmap
* and qbuf are called by the driver or v4l2 core with driver's lock
* held. To avoid a AB-BA deadlock (mmap_sem then driver's lock in
* mmap and driver's lock then mmap_sem in qbuf) the videobuf2 core
* release driver's lock, takes mmap_sem and then takes again driver's
* lock.
*
* To avoid race with other vb2 calls, which might be called after
* releasing driver's lock, this operation is performed at the
* beggining of qbuf processing. This way the queue status is
* consistent after getting driver's lock back.
*/
if (b->type == V4L2_MEMORY_USERPTR) {
mmap_sem = &current->mm->mmap_sem;
call_qop(q, wait_prepare, q);
down_read(mmap_sem);
call_qop(q, wait_finish, q);
}

if (q->fileio) {
dprintk(1, "qbuf: file io in progress\n");
return -EBUSY;
ret = -EBUSY;
goto unlock;
}

if (b->type != q->type) {
dprintk(1, "qbuf: invalid buffer type\n");
return -EINVAL;
ret = -EINVAL;
goto unlock;
}

if (b->index >= q->num_buffers) {
dprintk(1, "qbuf: buffer index out of range\n");
return -EINVAL;
ret = -EINVAL;
goto unlock;
}

vb = q->bufs[b->index];
if (NULL == vb) {
/* Should never happen */
dprintk(1, "qbuf: buffer is NULL\n");
return -EINVAL;
ret = -EINVAL;
goto unlock;
}

if (b->memory != q->memory) {
dprintk(1, "qbuf: invalid memory type\n");
return -EINVAL;
ret = -EINVAL;
goto unlock;
}

switch (vb->state) {
case VB2_BUF_STATE_DEQUEUED:
ret = __buf_prepare(vb, b);
if (ret)
return ret;
goto unlock;
case VB2_BUF_STATE_PREPARED:
break;
default:
dprintk(1, "qbuf: buffer already in use\n");
return -EINVAL;
ret = -EINVAL;
goto unlock;
}

/*
Expand All @@ -1142,7 +1172,10 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
__fill_v4l2_buffer(vb, b);

dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
return 0;
unlock:
if (mmap_sem)
up_read(mmap_sem);
return ret;
}
EXPORT_SYMBOL_GPL(vb2_qbuf);

Expand Down
3 changes: 1 addition & 2 deletions trunk/drivers/media/video/videobuf2-dma-sg.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,14 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
if (!buf->pages)
goto userptr_fail_pages_array_alloc;

down_read(&current->mm->mmap_sem);
num_pages_from_user = get_user_pages(current, current->mm,
vaddr & PAGE_MASK,
buf->sg_desc.num_pages,
write,
1, /* force */
buf->pages,
NULL);
up_read(&current->mm->mmap_sem);

if (num_pages_from_user != buf->sg_desc.num_pages)
goto userptr_fail_get_user_pages;

Expand Down
28 changes: 10 additions & 18 deletions trunk/drivers/media/video/videobuf2-memops.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,46 +100,38 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
unsigned long offset, start, end;
unsigned long this_pfn, prev_pfn;
dma_addr_t pa = 0;
int ret = -EFAULT;

start = vaddr;
offset = start & ~PAGE_MASK;
end = start + size;

down_read(&mm->mmap_sem);
vma = find_vma(mm, start);

if (vma == NULL || vma->vm_end < end)
goto done;
return -EFAULT;

for (prev_pfn = 0; start < end; start += PAGE_SIZE) {
ret = follow_pfn(vma, start, &this_pfn);
int ret = follow_pfn(vma, start, &this_pfn);
if (ret)
goto done;
return ret;

if (prev_pfn == 0)
pa = this_pfn << PAGE_SHIFT;
else if (this_pfn != prev_pfn + 1) {
ret = -EFAULT;
goto done;
}
else if (this_pfn != prev_pfn + 1)
return -EFAULT;

prev_pfn = this_pfn;
}

/*
* Memory is contigous, lock vma and return to the caller
*/
*res_vma = vb2_get_vma(vma);
if (*res_vma == NULL) {
ret = -ENOMEM;
goto done;
}
*res_pa = pa + offset;
ret = 0;
if (*res_vma == NULL)
return -ENOMEM;

done:
up_read(&mm->mmap_sem);
return ret;
*res_pa = pa + offset;
return 0;
}
EXPORT_SYMBOL_GPL(vb2_get_contig_userptr);

Expand Down

0 comments on commit 420f543

Please sign in to comment.