1 --- a/drivers/media/video/videobuf-dma-sg.c 2011-11-15 06:09:03.031835263 -0500
2 +++ b/drivers/media/video/videobuf-dma-sg.c 2011-12-28 07:50:34.514877000 -0500
5 unsigned long first,last;
7 + struct vm_area_struct *vma;
9 dma->direction = direction;
10 switch (dma->direction) {
12 last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT;
13 dma->offset = data & ~PAGE_MASK;
14 dma->nr_pages = last-first+1;
16 + /* In case the buffer is user-allocated and is actually an IO buffer for
17 + some other hardware, we cannot map pages for it. It in fact behaves
18 + the same as an overlay. */
19 + vma = find_vma (current->mm, data);
20 + if (vma && (vma->vm_flags & VM_IO)) {
21 + /* Only a single contiguous buffer is supported. */
22 + if (vma->vm_end < data + size) {
23 + dprintk(1, "init user: non-contiguous IO buffer.\n");
24 + return -EFAULT; /* same error that get_user_pages() would give */
26 + dma->bus_addr = (vma->vm_pgoff << PAGE_SHIFT) + (data - vma->vm_start);
27 + dprintk(1,"init user IO [0x%lx+0x%lx => %d pages at 0x%x]\n",
28 + data, size, dma->nr_pages, dma->bus_addr);
32 dma->pages = kmalloc(dma->nr_pages * sizeof(struct page*),
34 if (NULL == dma->pages)
36 (dma->vmalloc,dma->nr_pages);
39 - dma->sglist = vmalloc(sizeof(*dma->sglist));
40 + unsigned long physp=dma->bus_addr;
44 + dma->sglist = vmalloc(len*sizeof(*dma->sglist));
45 + sg_init_table(dma->sglist, len);
46 if (NULL != dma->sglist) {
48 - sg_dma_address(&dma->sglist[0]) = dma->bus_addr & PAGE_MASK;
49 - dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK;
50 - sg_dma_len(&dma->sglist[0]) = dma->nr_pages * PAGE_SIZE;
51 + dma->sglist[0].offset = dma->bus_addr & ~PAGE_MASK;
52 + sg_dma_len(&dma->sglist[0]) = PAGE_SIZE - dma->offset;
53 + sg_dma_address(&dma->sglist[0]) = (dma_addr_t)physp & PAGE_MASK;
54 + physp += sg_dma_len(&dma->sglist[0]);
56 + * Iterate in a loop for the number of pages
58 + for (i = 1; i < len; i++) {
59 + dma->sglist[i].offset = 0;
60 + sg_dma_len(&dma->sglist[i]) = PAGE_SIZE;
61 + sg_dma_address(&dma->sglist[i]) = (dma_addr_t)physp;
67 if (NULL == dma->sglist) {
69 MAGIC_CHECK(dma->magic, MAGIC_DMABUF);
72 - dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->nr_pages, dma->direction);
73 + dma_sync_sg_for_cpu(q->dev, dma->sglist, dma->sglen, dma->direction);
81 - dma_unmap_sg(q->dev, dma->sglist, dma->nr_pages, dma->direction);
82 + dma_unmap_sg(q->dev, dma->sglist, dma->sglen, dma->direction);