struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
        struct cx23885_buffer *buf = container_of(vb,
                struct cx23885_buffer, vb);
-       struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
        cx23885_free_buffer(dev, buf);
-
-       dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void buffer_queue(struct vb2_buffer *vb)
 
        struct cx23885_dev *dev = port->dev;
        int size = port->ts_packet_size * port->ts_packet_count;
        struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
-       int rc;
 
        dprintk(1, "%s: %p\n", __func__, buf);
        if (vb2_plane_size(&buf->vb, 0) < size)
                return -EINVAL;
        vb2_set_plane_payload(&buf->vb, 0, size);
 
-       rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
-       if (!rc)
-               return -EIO;
-
        cx23885_risc_databuffer(dev->pci, &buf->risc,
                                sgt->sgl,
                                port->ts_packet_size, port->ts_packet_count, 0);
 
        struct cx23885_dev *dev = port->dev;
        struct cx23885_buffer *buf = container_of(vb,
                struct cx23885_buffer, vb);
-       struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
        cx23885_free_buffer(dev, buf);
-
-       dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 static void buffer_queue(struct vb2_buffer *vb)
 
                struct cx23885_buffer, vb);
        struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
        unsigned lines = VBI_PAL_LINE_COUNT;
-       int ret;
 
        if (dev->tvnorm & V4L2_STD_525_60)
                lines = VBI_NTSC_LINE_COUNT;
                return -EINVAL;
        vb2_set_plane_payload(vb, 0, lines * VBI_LINE_LENGTH * 2);
 
-       ret = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
-       if (!ret)
-               return -EIO;
-
        cx23885_risc_vbibuffer(dev->pci, &buf->risc,
                         sgt->sgl,
                         0, VBI_LINE_LENGTH * lines,
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
-       struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
        struct cx23885_buffer *buf = container_of(vb,
                struct cx23885_buffer, vb);
-       struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
        cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
-
-       dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 /*
 
        u32 line0_offset, line1_offset;
        struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
        int field_tff;
-       int ret;
 
        buf->bpl = (dev->width * dev->fmt->depth) >> 3;
 
                return -EINVAL;
        vb2_set_plane_payload(vb, 0, dev->height * buf->bpl);
 
-       ret = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
-       if (!ret)
-               return -EIO;
-
        switch (dev->field) {
        case V4L2_FIELD_TOP:
                cx23885_risc_buffer(dev->pci, &buf->risc,
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
-       struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
        struct cx23885_buffer *buf = container_of(vb,
                struct cx23885_buffer, vb);
-       struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
        cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
-
-       dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
 }
 
 /*
 
        .queue_setup    = saa7134_ts_queue_setup,
        .buf_init       = saa7134_ts_buffer_init,
        .buf_prepare    = saa7134_ts_buffer_prepare,
-       .buf_finish     = saa7134_ts_buffer_finish,
        .buf_queue      = saa7134_vb2_buffer_queue,
        .wait_prepare   = vb2_ops_wait_prepare,
        .wait_finish    = vb2_ops_wait_finish,
 
        struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
        struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
        unsigned int lines, llength, size;
-       int ret;
 
        dprintk("buffer_prepare [%p]\n", buf);
 
        vb2_set_plane_payload(vb2, 0, size);
        vb2->v4l2_buf.field = dev->field;
 
-       ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-       if (!ret)
-               return -EIO;
        return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
                                    saa7134_buffer_startpage(buf));
 }
 EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
 
-void saa7134_ts_buffer_finish(struct vb2_buffer *vb2)
-{
-       struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
-       struct saa7134_dev *dev = dmaq->dev;
-       struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
-       struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
-
-       dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-}
-EXPORT_SYMBOL_GPL(saa7134_ts_buffer_finish);
-
 int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
        .queue_setup    = saa7134_ts_queue_setup,
        .buf_init       = saa7134_ts_buffer_init,
        .buf_prepare    = saa7134_ts_buffer_prepare,
-       .buf_finish     = saa7134_ts_buffer_finish,
        .buf_queue      = saa7134_vb2_buffer_queue,
        .wait_prepare   = vb2_ops_wait_prepare,
        .wait_finish    = vb2_ops_wait_finish,
 
        struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
        struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
        unsigned int size;
-       int ret;
 
        if (dma->sgl->offset) {
                pr_err("The buffer is not page-aligned\n");
 
        vb2_set_plane_payload(vb2, 0, size);
 
-       ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-       if (!ret)
-               return -EIO;
        return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
                                    saa7134_buffer_startpage(buf));
 }
        return 0;
 }
 
-static void buffer_finish(struct vb2_buffer *vb2)
-{
-       struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
-       struct saa7134_dev *dev = dmaq->dev;
-       struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
-       struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
-
-       dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-}
-
 struct vb2_ops saa7134_vbi_qops = {
        .queue_setup    = queue_setup,
        .buf_init       = buffer_init,
        .buf_prepare    = buffer_prepare,
-       .buf_finish     = buffer_finish,
        .buf_queue      = saa7134_vb2_buffer_queue,
        .wait_prepare   = vb2_ops_wait_prepare,
        .wait_finish    = vb2_ops_wait_finish,
 
        struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
        struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
        unsigned int size;
-       int ret;
 
        if (dma->sgl->offset) {
                pr_err("The buffer is not page-aligned\n");
        vb2_set_plane_payload(vb2, 0, size);
        vb2->v4l2_buf.field = dev->field;
 
-       ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-       if (!ret)
-               return -EIO;
        return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
                                    saa7134_buffer_startpage(buf));
 }
 
-static void buffer_finish(struct vb2_buffer *vb2)
-{
-       struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
-       struct saa7134_dev *dev = dmaq->dev;
-       struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
-       struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
-
-       dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-}
-
 static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[])
        .queue_setup    = queue_setup,
        .buf_init       = buffer_init,
        .buf_prepare    = buffer_prepare,
-       .buf_finish     = buffer_finish,
        .buf_queue      = saa7134_vb2_buffer_queue,
        .wait_prepare   = vb2_ops_wait_prepare,
        .wait_finish    = vb2_ops_wait_finish,
 
 
 int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
 int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
-void saa7134_ts_buffer_finish(struct vb2_buffer *vb2);
 int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
                           unsigned int *nbuffers, unsigned int *nplanes,
                           unsigned int sizes[], void *alloc_ctxs[]);
 
        struct solo_dev *solo_dev = solo_enc->solo_dev;
        struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
        int frame_size;
-       int ret;
 
        vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
 
        frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
        vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
 
-       /* may discard all previous data in vbuf->sgl */
-       if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-                       DMA_FROM_DEVICE))
-               return -ENOMEM;
-       ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
+       return solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
                             vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
                             frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
                             SOLO_JPEG_EXT_SIZE(solo_dev));
-       dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-                       DMA_FROM_DEVICE);
-
-       /* add the header only after dma_unmap_sg() */
-       sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
-                           solo_enc->jpeg_header, solo_enc->jpeg_len);
-
-       return ret;
 }
 
 static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
        struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
        int frame_off, frame_size;
        int skip = 0;
-       int ret;
 
        if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
                return -EIO;
                sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
        frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
 
-       /* may discard all previous data in vbuf->sgl */
-       if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-                       DMA_FROM_DEVICE))
-               return -ENOMEM;
-       ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
+       return solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
                        SOLO_MP4E_EXT_ADDR(solo_dev),
                        SOLO_MP4E_EXT_SIZE(solo_dev));
-       dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
-                       DMA_FROM_DEVICE);
-
-       /* add the header only after dma_unmap_sg() */
-       if (!vop_type(vh))
-               sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
-                                   solo_enc->vop, solo_enc->vop_len);
-       return ret;
 }
 
 static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
        spin_unlock_irqrestore(&solo_enc->av_lock, flags);
 }
 
+static void solo_enc_buf_finish(struct vb2_buffer *vb)
+{
+       struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue);
+       struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
+
+       switch (solo_enc->fmt) {
+       case V4L2_PIX_FMT_MPEG4:
+       case V4L2_PIX_FMT_H264:
+               if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME)
+                       sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+                                       solo_enc->vop, solo_enc->vop_len);
+               break;
+       default: /* V4L2_PIX_FMT_MJPEG */
+               sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+                               solo_enc->jpeg_header, solo_enc->jpeg_len);
+               break;
+       }
+}
+
 static struct vb2_ops solo_enc_video_qops = {
        .queue_setup    = solo_enc_queue_setup,
        .buf_queue      = solo_enc_buf_queue,
+       .buf_finish     = solo_enc_buf_finish,
        .start_streaming = solo_enc_start_streaming,
        .stop_streaming = solo_enc_stop_streaming,
        .wait_prepare   = vb2_ops_wait_prepare,
 
        struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
        struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
        unsigned size, bpl;
-       int rc;
 
        size = (dev->width * dev->height * dev->fmt->depth) >> 3;
        if (vb2_plane_size(vb, 0) < size)
                return -EINVAL;
        vb2_set_plane_payload(vb, 0, size);
 
-       rc = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-       if (!rc)
-               return -EIO;
-
        bpl = (dev->width * dev->fmt->depth) >> 3;
        switch (dev->field) {
        case V4L2_FIELD_TOP:
 {
        struct vb2_queue *vq = vb->vb2_queue;
        struct tw68_dev *dev = vb2_get_drv_priv(vq);
-       struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
        struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
 
-       dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
-
        pci_free_consistent(dev->pci, buf->size, buf->cpu, buf->dma);
 }
 
 
 static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
 {
        struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
-       struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
        struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
        struct mcam_dma_desc *desc = mvb->dma_desc;
        struct scatterlist *sg;
        int i;
 
-       mvb->dma_desc_nent = dma_map_sg(cam->dev, sg_table->sgl,
-                       sg_table->nents, DMA_FROM_DEVICE);
-       if (mvb->dma_desc_nent <= 0)
-               return -EIO;  /* Not sure what's right here */
-       for_each_sg(sg_table->sgl, sg, mvb->dma_desc_nent, i) {
+       for_each_sg(sg_table->sgl, sg, sg_table->nents, i) {
                desc->dma_addr = sg_dma_address(sg);
                desc->segment_len = sg_dma_len(sg);
                desc++;
        return 0;
 }
 
-static void mcam_vb_sg_buf_finish(struct vb2_buffer *vb)
-{
-       struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
-       struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
-
-       if (sg_table)
-               dma_unmap_sg(cam->dev, sg_table->sgl,
-                               sg_table->nents, DMA_FROM_DEVICE);
-}
-
 static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
 {
        struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
        .buf_init               = mcam_vb_sg_buf_init,
        .buf_prepare            = mcam_vb_sg_buf_prepare,
        .buf_queue              = mcam_vb_buf_queue,
-       .buf_finish             = mcam_vb_sg_buf_finish,
        .buf_cleanup            = mcam_vb_sg_buf_cleanup,
        .start_streaming        = mcam_vb_start_streaming,
        .stop_streaming         = mcam_vb_stop_streaming,
 
 {
        struct vb2_dma_sg_conf *conf = alloc_ctx;
        struct vb2_dma_sg_buf *buf;
+       struct sg_table *sgt;
        int ret;
        int num_pages;
 
 
        /* Prevent the device from being released while the buffer is used */
        buf->dev = get_device(conf->dev);
+
+       sgt = &buf->sg_table;
+       if (dma_map_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir) == 0)
+               goto fail_map;
+       dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+
        buf->handler.refcount = &buf->refcount;
        buf->handler.put = vb2_dma_sg_put;
        buf->handler.arg = buf;
                __func__, buf->num_pages);
        return buf;
 
+fail_map:
+       put_device(buf->dev);
+       sg_free_table(sgt);
 fail_table_alloc:
        num_pages = buf->num_pages;
        while (num_pages--)
 static void vb2_dma_sg_put(void *buf_priv)
 {
        struct vb2_dma_sg_buf *buf = buf_priv;
+       struct sg_table *sgt = &buf->sg_table;
        int i = buf->num_pages;
 
        if (atomic_dec_and_test(&buf->refcount)) {
                dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
                        buf->num_pages);
+               dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
                if (buf->vaddr)
                        vm_unmap_ram(buf->vaddr, buf->num_pages);
                sg_free_table(&buf->sg_table);
        }
 }
 
+static void vb2_dma_sg_prepare(void *buf_priv)
+{
+       struct vb2_dma_sg_buf *buf = buf_priv;
+       struct sg_table *sgt = &buf->sg_table;
+
+       dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
+static void vb2_dma_sg_finish(void *buf_priv)
+{
+       struct vb2_dma_sg_buf *buf = buf_priv;
+       struct sg_table *sgt = &buf->sg_table;
+
+       dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
+}
+
 static inline int vma_is_io(struct vm_area_struct *vma)
 {
        return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
                                    unsigned long size,
                                    enum dma_data_direction dma_dir)
 {
+       struct vb2_dma_sg_conf *conf = alloc_ctx;
        struct vb2_dma_sg_buf *buf;
        unsigned long first, last;
        int num_pages_from_user;
        struct vm_area_struct *vma;
+       struct sg_table *sgt;
 
        buf = kzalloc(sizeof *buf, GFP_KERNEL);
        if (!buf)
                return NULL;
 
        buf->vaddr = NULL;
+       buf->dev = conf->dev;
        buf->dma_dir = dma_dir;
        buf->offset = vaddr & ~PAGE_MASK;
        buf->size = size;
                        buf->num_pages, buf->offset, size, 0))
                goto userptr_fail_alloc_table_from_pages;
 
+       sgt = &buf->sg_table;
+       if (dma_map_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir) == 0)
+               goto userptr_fail_map;
+       dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
        return buf;
 
+userptr_fail_map:
+       sg_free_table(&buf->sg_table);
 userptr_fail_alloc_table_from_pages:
 userptr_fail_get_user_pages:
        dprintk(1, "get_user_pages requested/got: %d/%d]\n",
 static void vb2_dma_sg_put_userptr(void *buf_priv)
 {
        struct vb2_dma_sg_buf *buf = buf_priv;
+       struct sg_table *sgt = &buf->sg_table;
        int i = buf->num_pages;
 
        dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
               __func__, buf->num_pages);
+       dma_unmap_sg(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
        if (buf->vaddr)
                vm_unmap_ram(buf->vaddr, buf->num_pages);
        sg_free_table(&buf->sg_table);
        .put            = vb2_dma_sg_put,
        .get_userptr    = vb2_dma_sg_get_userptr,
        .put_userptr    = vb2_dma_sg_put_userptr,
+       .prepare        = vb2_dma_sg_prepare,
+       .finish         = vb2_dma_sg_finish,
        .vaddr          = vb2_dma_sg_vaddr,
        .mmap           = vb2_dma_sg_mmap,
        .num_users      = vb2_dma_sg_num_users,