V4L/DVB (5123): Buf_qbuf: fix: videobuf_queue->stream corruption and lockup
[sfrench/cifs-2.6.git] / drivers / media / video / video-buf.c
index d2ca0f08d0df635e4d2ae73669dfbec1f98e07d0..6504a5866849ab73d6058304d9b7dd91b9c85db7 100644 (file)
@@ -365,7 +365,12 @@ videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
                if (NULL == fbuf)
                        return -EINVAL;
                /* FIXME: need sanity checks for vb->boff */
-               bus   = (dma_addr_t)fbuf->base + vb->boff;
+               /*
+                * Using a double cast to avoid compiler warnings when
+                * building for PAE. Compiler doesn't like direct casting
+                * of a 32 bit ptr to 64 bit integer.
+                */
+               bus   = (dma_addr_t)(unsigned long)fbuf->base + vb->boff;
                pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
                err = videobuf_dma_init_overlay(&vb->dma,PCI_DMA_FROMDEVICE,
                                                bus, pages);
@@ -399,19 +404,25 @@ void videobuf_queue_pci(struct videobuf_queue* q)
 int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma)
 {
        struct videobuf_queue q;
+       struct videobuf_queue_ops qops;
 
        q.dev=pci;
-       q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+       qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
+       qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
+       q.ops = &qops;
 
-       return (videobuf_dma_unmap(&q,dma));
+       return (videobuf_dma_map(&q,dma));
 }
 
 int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma)
 {
        struct videobuf_queue q;
+       struct videobuf_queue_ops qops;
 
        q.dev=pci;
-       q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg;
+       qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg;
+       qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg;
+       q.ops = &qops;
 
        return (videobuf_dma_unmap(&q,dma));
 }
@@ -689,6 +700,7 @@ videobuf_qbuf(struct videobuf_queue *q,
                goto done;
        }
        if (buf->state == STATE_QUEUED ||
+           buf->state == STATE_PREPARED ||
            buf->state == STATE_ACTIVE) {
                dprintk(1,"qbuf: buffer is already queued or active.\n");
                goto done;
@@ -923,7 +935,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
                /* need to capture a new frame */
                retval = -ENOMEM;
                q->read_buf = videobuf_alloc(q->msize);
-               dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf);
+               dprintk(1,"video alloc=0x%p\n", q->read_buf);
                if (NULL == q->read_buf)
                        goto done;
                q->read_buf->memory = V4L2_MEMORY_USERPTR;
@@ -1218,7 +1230,7 @@ videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr,
                vaddr,vma->vm_start,vma->vm_end);
        if (vaddr > vma->vm_end)
                return NOPAGE_SIGBUS;
-       page = alloc_page(GFP_USER);
+       page = alloc_page(GFP_USER | __GFP_DMA32);
        if (!page)
                return NOPAGE_OOM;
        clear_user_page(page_address(page), vaddr, page);