linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v3 0/5] Refactoring Videobuf2 for common use
@ 2015-08-26 11:59 Junghak Sung
  2015-08-26 11:59 ` [RFC PATCH v3 1/5] media: videobuf2: Replace videobuf2-core with videobuf2-v4l2 Junghak Sung
                   ` (4 more replies)
  0 siblings, 5 replies; 23+ messages in thread
From: Junghak Sung @ 2015-08-26 11:59 UTC (permalink / raw)
  To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, jh1009.sung, rany.kwon

Hello everybody,

This is the 3rd round for refactoring Videobuf2(a.k.a VB2).
The purpose of this patch series is to separate existing VB2 framework
into core part and V4L2 specific part. So that not only V4L2 but also other
frameworks can use them to manage buffer and utilize queue.

Why do we try to make the VB2 framework to be common?

As you may know, current DVB framework uses ringbuffer mechanism to demux
MPEG-2 TS data and pass it to userspace. However, this mechanism requires
extra memory copy because DVB framework provides only read() system call for
application - read() system call copies the kernel data to user-space buffer.
So if we can use VB2 framework which supports streaming I/O and buffer
sharing mechanism, then we could enhance existing DVB framework by removing
the extra memory copy - with VB2 framework, application can access the kernel
data directly through mmap system call.

We have a plan for this work as follows:
1. Separate existing VB2 framework into three parts - VB2 common, VB2-v4l2.
   Of course, this change will not affect other v4l2-based
   device drivers. This patch series corresponds to this step.

2. Add and implement new APIs for DVB streaming I/O.
   We can remove unnecessary memory copy between kernel-space and user-space
   by using these new APIs. However, we leaves legacy interfaces as-is
   for backward compatibility.

This patch series is the first step for it.
The previous version of this patch series can be found at [1] and [2].

[1] RFC PATCH v1 - http://www.spinics.net/lists/linux-media/msg90688.html
[2] RFC PATCH v2 - http://www.spinics.net/lists/linux-media/msg92130.html


Changes since v2

1. Remove v4l2 stuffs completely from vb2_buffer
The v4l2 stuffs - v4l2_buf and v4l2_planes - are removed completely from
struct vb2_buffer. New member variables - index, type, memory - are added
to struct vb2_buffer, all of which can be used commonly. And bytesused,
length, offset, userptr, fd, data_offset are added to struct vb2_plane
for the same reason. So, we can manage video buffer by only using
struct vb2_buffer.
And, v4l2 stuffs - flags, field, timestamp, timecode, sequence - are defined
as member variables of struct vb2_v4l2_buffer.

2. Create new header file for VB2 internal use
videobuf2-internal.h is created, which is referred by videobuf2-core
and videobuf2-v4l2. The header file contains dprintk() for debug,
macro functions to invoke various callbacks, and vb2_core_* function prototypes
referred by inside of videobuf2.

3. Remove buffer-specific callbacks as much as possible
There were many callback functions to handle video buffer information
in previous patch series. In this patch series, I try to remove these callbacks
as much as possible without breaking the existing function flow.
As a result, only four callbacks are remained - fill_user_buffer(),
fill_vb2_buffer(), fill_vb2_timestamp() and is_last().

All ideas above are from Hans and it seems to be better and right way.


Changes since v1

1. Divide patch set into more pieces
v1 was not reviewed normally because the 2/3 patch is failed to send to mailing
list with size problem - over 300kb. So I have divided the patch set into five
pieces and refined them neatly, which was pointed by Hans.

2. Add shell scripts for renaming patch
In case of renaming patch, shell scripts are included inside the body of the
patches by Mauro's advice. 1/5 and 5/5 patches include these scripts, which can
be used by reviewers or maintainers to regenerate big patch file if something
goes wrong during patch apply.

3. Remove dependency on v4l2 from videobuf2
In previous patch set, videobuf2-core uses v4l2-specific stuff as it is.
e.g. enum v4l2_buf_type and enum v4l2_memory. That prevented other frameworks
from using videobuf2 independently and made them forced to include
v4l2-specific stuff.
In this version, these dependent stuffs are replaced with VB2 own stuffs.
e.g. enum vb2_buf_type and enum vb2_memory. So, v4l2-specific header file isn't
required to use videobuf2 in other modules. Please, note that videobuf2 stuffs
will be translated to v4l2-specific stuffs in videobuf2-v4l2.c file for
backward compatibility.

4. Unify duplicated definitions
VB2_DEBUG() is newly defined in videobuf2-core header file in order to unify
duplicated macro functions that invoke callback functions implemented in vb2
backends - i.e., videobuf2-vmalloc and videobuf2-dma-sg - and queue relevant
callbacks of device drivers.
In previous patch set, these macro functions were defined
in both videobuf2-core.c and videobuf2-v4l2.c.


This patch series is based on media_tree.git [3]. I have applied this patches
to my own git [4] for review, and tested this patch series on ubuntu
PC(Intel i7-3770) for x86 system and odroid-xu3(exynos5422) for ARM.

[3] media_tree.git - http://git.linuxtv.org/cgit.cgi/media_tree.git/
[4] jsung/dvb-vb2.git - http://git.linuxtv.org/cgit.cgi/jsung/dvb-vb2.git/
    (branch: vb2-refactoring)

Any suggestions and comments are welcome.

Regards,
Junghak

Junghak Sung (5):
  media: videobuf2: Replace videobuf2-core with videobuf2-v4l2
  media: videobuf2: Restructure vb2_buffer for common use.
  media: videobuf2: Modify all device drivers related with previous
    change.
  media: videobuf2: Change queue_setup argument
  media: videobuf2: Divide videobuf2-core into 2 parts

 drivers/input/touchscreen/sur40.c                  |   20 +-
 drivers/media/dvb-frontends/rtl2832_sdr.c          |   16 +-
 drivers/media/pci/cobalt/cobalt-driver.h           |    2 +-
 drivers/media/pci/cobalt/cobalt-irq.c              |    8 +-
 drivers/media/pci/cobalt/cobalt-v4l2.c             |   11 +-
 drivers/media/pci/cx23885/cx23885-417.c            |   13 +-
 drivers/media/pci/cx23885/cx23885-core.c           |   24 +-
 drivers/media/pci/cx23885/cx23885-dvb.c            |   11 +-
 drivers/media/pci/cx23885/cx23885-vbi.c            |   18 +-
 drivers/media/pci/cx23885/cx23885-video.c          |   29 +-
 drivers/media/pci/cx23885/cx23885.h                |    2 +-
 drivers/media/pci/cx25821/cx25821-video.c          |   24 +-
 drivers/media/pci/cx25821/cx25821.h                |    3 +-
 drivers/media/pci/cx88/cx88-blackbird.c            |   15 +-
 drivers/media/pci/cx88/cx88-core.c                 |    8 +-
 drivers/media/pci/cx88/cx88-dvb.c                  |   13 +-
 drivers/media/pci/cx88/cx88-mpeg.c                 |   14 +-
 drivers/media/pci/cx88/cx88-vbi.c                  |   19 +-
 drivers/media/pci/cx88/cx88-video.c                |   21 +-
 drivers/media/pci/cx88/cx88.h                      |    2 +-
 drivers/media/pci/dt3155/dt3155.c                  |   20 +-
 drivers/media/pci/dt3155/dt3155.h                  |    3 +-
 drivers/media/pci/netup_unidvb/netup_unidvb_core.c |   21 +-
 drivers/media/pci/saa7134/saa7134-core.c           |   14 +-
 drivers/media/pci/saa7134/saa7134-ts.c             |   16 +-
 drivers/media/pci/saa7134/saa7134-vbi.c            |   12 +-
 drivers/media/pci/saa7134/saa7134-video.c          |   23 +-
 drivers/media/pci/saa7134/saa7134.h                |    4 +-
 drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c     |    4 +-
 drivers/media/pci/solo6x10/solo6x10-v4l2.c         |    2 +-
 drivers/media/pci/solo6x10/solo6x10.h              |    4 +-
 drivers/media/pci/sta2x11/sta2x11_vip.c            |   14 +-
 drivers/media/pci/tw68/tw68-video.c                |   13 +-
 drivers/media/pci/tw68/tw68.h                      |    2 +-
 drivers/media/platform/am437x/am437x-vpfe.c        |   23 +-
 drivers/media/platform/am437x/am437x-vpfe.h        |    2 +-
 drivers/media/platform/blackfin/bfin_capture.c     |   13 +-
 drivers/media/platform/coda/coda-bit.c             |    2 +-
 drivers/media/platform/coda/coda-common.c          |    4 +-
 drivers/media/platform/coda/coda.h                 |    2 +-
 drivers/media/platform/coda/trace.h                |    2 +-
 drivers/media/platform/davinci/vpbe_display.c      |    3 +-
 drivers/media/platform/davinci/vpif_capture.c      |   20 +-
 drivers/media/platform/davinci/vpif_capture.h      |    2 +-
 drivers/media/platform/davinci/vpif_display.c      |   30 +-
 drivers/media/platform/davinci/vpif_display.h      |    2 +-
 drivers/media/platform/exynos-gsc/gsc-core.h       |    4 +-
 drivers/media/platform/exynos-gsc/gsc-m2m.c        |    2 +-
 drivers/media/platform/exynos4-is/fimc-capture.c   |   18 +-
 drivers/media/platform/exynos4-is/fimc-core.c      |    2 +-
 drivers/media/platform/exynos4-is/fimc-core.h      |    4 +-
 drivers/media/platform/exynos4-is/fimc-is.h        |    2 +-
 drivers/media/platform/exynos4-is/fimc-isp-video.c |    5 +-
 drivers/media/platform/exynos4-is/fimc-isp-video.h |    2 +-
 drivers/media/platform/exynos4-is/fimc-isp.h       |    4 +-
 drivers/media/platform/exynos4-is/fimc-lite.c      |   15 +-
 drivers/media/platform/exynos4-is/fimc-lite.h      |    4 +-
 drivers/media/platform/exynos4-is/fimc-m2m.c       |    4 +-
 drivers/media/platform/m2m-deinterlace.c           |   25 +-
 drivers/media/platform/marvell-ccic/mcam-core.c    |   46 +-
 drivers/media/platform/marvell-ccic/mcam-core.h    |    2 +-
 drivers/media/platform/mx2_emmaprp.c               |    2 +-
 drivers/media/platform/omap3isp/ispvideo.c         |   21 +-
 drivers/media/platform/omap3isp/ispvideo.h         |    4 +-
 drivers/media/platform/rcar_jpu.c                  |    5 +-
 drivers/media/platform/s3c-camif/camif-capture.c   |   15 +-
 drivers/media/platform/s3c-camif/camif-core.c      |    2 +-
 drivers/media/platform/s3c-camif/camif-core.h      |    4 +-
 drivers/media/platform/s5p-g2d/g2d.c               |    4 +-
 drivers/media/platform/s5p-jpeg/jpeg-core.c        |    4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc.c           |    2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h    |    2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c       |    4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c       |    4 +-
 drivers/media/platform/s5p-tv/mixer.h              |    4 +-
 drivers/media/platform/s5p-tv/mixer_reg.c          |    2 +-
 drivers/media/platform/s5p-tv/mixer_video.c        |   10 +-
 drivers/media/platform/sh_veu.c                    |   22 +-
 drivers/media/platform/sh_vou.c                    |   18 +-
 drivers/media/platform/soc_camera/atmel-isi.c      |    8 +-
 drivers/media/platform/soc_camera/mx2_camera.c     |    7 +-
 drivers/media/platform/soc_camera/mx3_camera.c     |    7 +-
 drivers/media/platform/soc_camera/rcar_vin.c       |    5 +-
 .../platform/soc_camera/sh_mobile_ceu_camera.c     |    8 +-
 drivers/media/platform/soc_camera/soc_camera.c     |    2 +-
 drivers/media/platform/sti/bdisp/bdisp-v4l2.c      |    3 +-
 drivers/media/platform/ti-vpe/vpe.c                |    4 +-
 drivers/media/platform/vim2m.c                     |    3 +-
 drivers/media/platform/vivid/vivid-core.h          |    4 +-
 drivers/media/platform/vivid/vivid-kthread-cap.c   |   54 +-
 drivers/media/platform/vivid/vivid-kthread-out.c   |   34 +-
 drivers/media/platform/vivid/vivid-sdr-cap.c       |   17 +-
 drivers/media/platform/vivid/vivid-vbi-cap.c       |   25 +-
 drivers/media/platform/vivid/vivid-vbi-out.c       |    5 +-
 drivers/media/platform/vivid/vivid-vid-cap.c       |    6 +-
 drivers/media/platform/vivid/vivid-vid-out.c       |    6 +-
 drivers/media/platform/vsp1/vsp1_video.c           |   15 +-
 drivers/media/platform/vsp1/vsp1_video.h           |    4 +-
 drivers/media/platform/xilinx/xilinx-dma.c         |   23 +-
 drivers/media/platform/xilinx/xilinx-dma.h         |    2 +-
 drivers/media/usb/airspy/airspy.c                  |   19 +-
 drivers/media/usb/au0828/au0828-vbi.c              |    9 +-
 drivers/media/usb/au0828/au0828-video.c            |   48 +-
 drivers/media/usb/au0828/au0828.h                  |    3 +-
 drivers/media/usb/em28xx/em28xx-vbi.c              |    5 +-
 drivers/media/usb/em28xx/em28xx-video.c            |   25 +-
 drivers/media/usb/em28xx/em28xx.h                  |    3 +-
 drivers/media/usb/go7007/go7007-driver.c           |   24 +-
 drivers/media/usb/go7007/go7007-priv.h             |    4 +-
 drivers/media/usb/go7007/go7007-v4l2.c             |   22 +-
 drivers/media/usb/hackrf/hackrf.c                  |   17 +-
 drivers/media/usb/msi2500/msi2500.c                |   12 +-
 drivers/media/usb/pwc/pwc-if.c                     |   31 +-
 drivers/media/usb/pwc/pwc-uncompress.c             |    8 +-
 drivers/media/usb/pwc/pwc.h                        |    3 +-
 drivers/media/usb/s2255/s2255drv.c                 |   29 +-
 drivers/media/usb/stk1160/stk1160-v4l.c            |   17 +-
 drivers/media/usb/stk1160/stk1160-video.c          |   12 +-
 drivers/media/usb/stk1160/stk1160.h                |    4 +-
 drivers/media/usb/usbtv/usbtv-video.c              |   24 +-
 drivers/media/usb/usbtv/usbtv.h                    |    3 +-
 drivers/media/usb/uvc/uvc_queue.c                  |   29 +-
 drivers/media/usb/uvc/uvc_video.c                  |   20 +-
 drivers/media/usb/uvc/uvcvideo.h                   |    6 +-
 drivers/media/v4l2-core/Makefile                   |    2 +-
 drivers/media/v4l2-core/v4l2-ioctl.c               |    2 +-
 drivers/media/v4l2-core/v4l2-mem2mem.c             |   10 +-
 drivers/media/v4l2-core/v4l2-trace.c               |    2 +-
 drivers/media/v4l2-core/videobuf2-core.c           | 2039 +++-----------------
 drivers/media/v4l2-core/videobuf2-internal.h       |  184 ++
 drivers/media/v4l2-core/videobuf2-v4l2.c           | 1671 ++++++++++++++++
 drivers/staging/media/davinci_vpfe/vpfe_video.c    |    2 +-
 drivers/staging/media/omap4iss/iss_video.c         |    2 +-
 drivers/usb/gadget/function/uvc_queue.c            |   28 +-
 drivers/usb/gadget/function/uvc_queue.h            |    4 +-
 include/media/soc_camera.h                         |    2 +-
 include/media/v4l2-mem2mem.h                       |   11 +-
 include/media/videobuf2-core.h                     |  212 +-
 include/media/videobuf2-dvb.h                      |    2 +-
 include/media/videobuf2-v4l2.h                     |  159 ++
 include/trace/events/v4l2.h                        |   39 +-
 141 files changed, 3163 insertions(+), 2625 deletions(-)
 create mode 100644 drivers/media/v4l2-core/videobuf2-internal.h
 create mode 100644 drivers/media/v4l2-core/videobuf2-v4l2.c
 create mode 100644 include/media/videobuf2-v4l2.h

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [RFC PATCH v3 1/5] media: videobuf2: Replace videobuf2-core with videobuf2-v4l2
  2015-08-26 11:59 [RFC PATCH v3 0/5] Refactoring Videobuf2 for common use Junghak Sung
@ 2015-08-26 11:59 ` Junghak Sung
  2015-08-27  8:51   ` Mauro Carvalho Chehab
  2015-08-26 11:59 ` [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer Junghak Sung
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 23+ messages in thread
From: Junghak Sung @ 2015-08-26 11:59 UTC (permalink / raw)
  To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, jh1009.sung, rany.kwon

Make videobuf2-v4l2 as a wrapper of videobuf2-core for v4l2-use.
And replace videobuf2-core.h with videobuf2-v4l2.h.
This renaming change should be accompanied by the modifications
of all device drivers that include videobuf2-core.h.
It can be done with just running this shell script.

replace()
{
str1=$1
str2=$2
dir=$3
for file in $(find $dir -name *.h -o -name *.c -o -name Makefile)
do
    echo $file
    sed "s/$str1/$str2/g" $file > $file.out
    mv $file.out $file
done
}

replace "videobuf2-core" "videobuf2-v4l2" "include/media/"
replace "videobuf2-core" "videobuf2-v4l2" "drivers/media/"
replace "videobuf2-core" "videobuf2-v4l2" "drivers/usb/gadget/"

Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
 drivers/media/pci/solo6x10/solo6x10.h              |    2 +-
 drivers/media/platform/coda/coda-bit.c             |    2 +-
 drivers/media/platform/coda/coda-common.c          |    2 +-
 drivers/media/platform/coda/coda.h                 |    2 +-
 drivers/media/platform/coda/trace.h                |    2 +-
 drivers/media/platform/exynos-gsc/gsc-core.h       |    2 +-
 drivers/media/platform/exynos4-is/fimc-capture.c   |    2 +-
 drivers/media/platform/exynos4-is/fimc-core.c      |    2 +-
 drivers/media/platform/exynos4-is/fimc-core.h      |    2 +-
 drivers/media/platform/exynos4-is/fimc-is.h        |    2 +-
 drivers/media/platform/exynos4-is/fimc-isp-video.c |    2 +-
 drivers/media/platform/exynos4-is/fimc-isp-video.h |    2 +-
 drivers/media/platform/exynos4-is/fimc-isp.h       |    2 +-
 drivers/media/platform/exynos4-is/fimc-lite.c      |    2 +-
 drivers/media/platform/exynos4-is/fimc-lite.h      |    2 +-
 drivers/media/platform/exynos4-is/fimc-m2m.c       |    2 +-
 drivers/media/platform/marvell-ccic/mcam-core.h    |    2 +-
 drivers/media/platform/omap3isp/ispvideo.h         |    2 +-
 drivers/media/platform/rcar_jpu.c                  |    2 +-
 drivers/media/platform/s3c-camif/camif-capture.c   |    2 +-
 drivers/media/platform/s3c-camif/camif-core.c      |    2 +-
 drivers/media/platform/s3c-camif/camif-core.h      |    2 +-
 drivers/media/platform/s5p-g2d/g2d.c               |    2 +-
 drivers/media/platform/s5p-jpeg/jpeg-core.c        |    2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc.c           |    2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_common.h    |    2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c       |    2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c       |    2 +-
 drivers/media/platform/s5p-tv/mixer.h              |    2 +-
 drivers/media/platform/soc_camera/mx2_camera.c     |    2 +-
 drivers/media/platform/soc_camera/soc_camera.c     |    2 +-
 drivers/media/platform/ti-vpe/vpe.c                |    2 +-
 drivers/media/platform/vivid/vivid-core.h          |    2 +-
 drivers/media/platform/vsp1/vsp1_video.c           |    2 +-
 drivers/media/platform/vsp1/vsp1_video.h           |    2 +-
 drivers/media/platform/xilinx/xilinx-dma.c         |    2 +-
 drivers/media/platform/xilinx/xilinx-dma.h         |    2 +-
 drivers/media/usb/go7007/go7007-priv.h             |    2 +-
 drivers/media/usb/stk1160/stk1160.h                |    2 +-
 drivers/media/usb/usbtv/usbtv-video.c              |    2 +-
 drivers/media/usb/uvc/uvcvideo.h                   |    2 +-
 drivers/media/v4l2-core/Makefile                   |    2 +-
 drivers/media/v4l2-core/v4l2-ioctl.c               |    2 +-
 drivers/media/v4l2-core/v4l2-mem2mem.c             |    2 +-
 drivers/media/v4l2-core/v4l2-trace.c               |    2 +-
 drivers/media/v4l2-core/videobuf2-core.c           |   10 +++----
 drivers/media/v4l2-core/videobuf2-v4l2.c           |   31 ++++++++++++++++++++
 drivers/usb/gadget/function/uvc_queue.h            |    2 +-
 include/media/soc_camera.h                         |    2 +-
 include/media/v4l2-mem2mem.h                       |    2 +-
 include/media/videobuf2-core.h                     |    3 +-
 include/media/videobuf2-dvb.h                      |    2 +-
 include/media/videobuf2-v4l2.h                     |   17 +++++++++++
 53 files changed, 103 insertions(+), 56 deletions(-)
 create mode 100644 drivers/media/v4l2-core/videobuf2-v4l2.c
 create mode 100644 include/media/videobuf2-v4l2.h

diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index 27423d7..5cc9e9d 100644
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -35,7 +35,7 @@
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 #include "solo6x10-regs.h"
 
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index fd7819d..cd41d49 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -25,7 +25,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 #include <media/videobuf2-vmalloc.h>
 
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 04310cd..6e0c9be 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -36,7 +36,7 @@
 #include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 #include <media/videobuf2-vmalloc.h>
 
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 59b2af9..feb9671 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -24,7 +24,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 #include "coda_regs.h"
 
diff --git a/drivers/media/platform/coda/trace.h b/drivers/media/platform/coda/trace.h
index d9099a0..9db6a66 100644
--- a/drivers/media/platform/coda/trace.h
+++ b/drivers/media/platform/coda/trace.h
@@ -5,7 +5,7 @@
 #define __CODA_TRACE_H__
 
 #include <linux/tracepoint.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 #include "coda.h"
 
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index fa572aa..769ff50 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -19,7 +19,7 @@
 #include <linux/videodev2.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mem2mem.h>
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index cfebf29..d0ceae3 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -24,7 +24,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "common.h"
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
index 1101c41..cef2a7f 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -27,7 +27,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "fimc-core.h"
diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h
index 7328f08..ccb5d91 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.h
+++ b/drivers/media/platform/exynos4-is/fimc-core.h
@@ -22,7 +22,7 @@
 #include <linux/sizes.h>
 
 #include <media/media-entity.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mem2mem.h>
diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h
index e0be691..386eb49 100644
--- a/drivers/media/platform/exynos4-is/fimc-is.h
+++ b/drivers/media/platform/exynos4-is/fimc-is.h
@@ -22,7 +22,7 @@
 #include <linux/sizes.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/v4l2-ctrls.h>
 
 #include "fimc-isp.h"
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
index 76b6b4d..195f9b5 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
@@ -28,7 +28,7 @@
 
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 #include <media/exynos-fimc.h>
 
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.h b/drivers/media/platform/exynos4-is/fimc-isp-video.h
index 98c6626..f79a1b3 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp-video.h
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.h
@@ -11,7 +11,7 @@
 #ifndef FIMC_ISP_VIDEO__
 #define FIMC_ISP_VIDEO__
 
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include "fimc-isp.h"
 
 #ifdef CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h
index b99be09..ad9908b 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp.h
+++ b/drivers/media/platform/exynos4-is/fimc-isp.h
@@ -21,7 +21,7 @@
 #include <linux/videodev2.h>
 
 #include <media/media-entity.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mediabus.h>
 #include <media/exynos-fimc.h>
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index ca6261a..7e37c9a 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -28,7 +28,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 #include <media/exynos-fimc.h>
 
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h
index ea19dc7..7e4c708 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.h
+++ b/drivers/media/platform/exynos4-is/fimc-lite.h
@@ -19,7 +19,7 @@
 #include <linux/videodev2.h>
 
 #include <media/media-entity.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mediabus.h>
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
index 0ad1b6f..9c27335 100644
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "common.h"
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 97167f6..35cd9e5 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -10,7 +10,7 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-dev.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 /*
  * Create our own symbols for the supported buffer modes, but, for now,
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 4071dd7..31c2445 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -20,7 +20,7 @@
 #include <media/media-entity.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 #define ISP_VIDEO_DRIVER_NAME		"ispvideo"
 #define ISP_VIDEO_DRIVER_VERSION	"0.0.2"
diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c
index 2973f07..18e62d0 100644
--- a/drivers/media/platform/rcar_jpu.c
+++ b/drivers/media/platform/rcar_jpu.c
@@ -37,7 +37,7 @@
 #include <media/v4l2-fh.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index 76e6289..bb01eaa 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -34,7 +34,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "camif-core.h"
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
index f47b332..1ba9bb0 100644
--- a/drivers/media/platform/s3c-camif/camif-core.c
+++ b/drivers/media/platform/s3c-camif/camif-core.c
@@ -32,7 +32,7 @@
 #include <media/media-device.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "camif-core.h"
diff --git a/drivers/media/platform/s3c-camif/camif-core.h b/drivers/media/platform/s3c-camif/camif-core.h
index 35d2fcd..8ef6f26 100644
--- a/drivers/media/platform/s3c-camif/camif-core.h
+++ b/drivers/media/platform/s3c-camif/camif-core.h
@@ -25,7 +25,7 @@
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mediabus.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/s3c_camif.h>
 
 #define S3C_CAMIF_DRIVER_NAME	"s3c-camif"
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index 421a7c3..81483da 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -23,7 +23,7 @@
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "g2d.h"
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 9690f9d..5b1861b 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -26,7 +26,7 @@
 #include <linux/string.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "jpeg-core.h"
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 8de61dc..b3758b8 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -22,7 +22,7 @@
 #include <media/v4l2-event.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_ctrl.h"
 #include "s5p_mfc_debug.h"
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 24262bb..10884a7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -21,7 +21,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include "regs-mfc.h"
 #include "regs-mfc-v8.h"
 
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index aebe4fd..2fd59e7 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -22,7 +22,7 @@
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-event.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_ctrl.h"
 #include "s5p_mfc_debug.h"
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 2e57e9f..e42014c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -23,7 +23,7 @@
 #include <media/v4l2-event.h>
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_ctrl.h"
 #include "s5p_mfc_debug.h"
diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h
index fb2acc5..855b723 100644
--- a/drivers/media/platform/s5p-tv/mixer.h
+++ b/drivers/media/platform/s5p-tv/mixer.h
@@ -24,7 +24,7 @@
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <media/v4l2-device.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 #include "regs-mixer.h"
 
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index ea4c423..6e41335 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -32,7 +32,7 @@
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 #include <media/soc_camera.h>
 #include <media/soc_mediabus.h>
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 9087fed..3a18df7 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -38,7 +38,7 @@
 #include <media/v4l2-dev.h>
 #include <media/v4l2-of.h>
 #include <media/videobuf-core.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 /* Default to VGA resolution */
 #define DEFAULT_WIDTH	640
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index c44760b..d82c2f2 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -40,7 +40,7 @@
 #include <media/v4l2-event.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "vpdma.h"
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index c72349c..5f1b1da 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -21,7 +21,7 @@
 #define _VIVID_CORE_H_
 
 #include <linux/fb.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ctrls.h>
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 3c124c1..dfd45c7 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -24,7 +24,7 @@
 #include <media/v4l2-fh.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-subdev.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "vsp1.h"
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index 0887a4d..d808301 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -18,7 +18,7 @@
 #include <linux/wait.h>
 
 #include <media/media-entity.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 struct vsp1_video;
 
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
index e779c93..d9dcd4b 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -22,7 +22,7 @@
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-contig.h>
 
 #include "xilinx-dma.h"
diff --git a/drivers/media/platform/xilinx/xilinx-dma.h b/drivers/media/platform/xilinx/xilinx-dma.h
index a540111..7a1621a 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.h
+++ b/drivers/media/platform/xilinx/xilinx-dma.h
@@ -22,7 +22,7 @@
 
 #include <media/media-entity.h>
 #include <media/v4l2-dev.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 struct dma_chan;
 struct xvip_composite_device;
diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h
index 2251c3f..9e83bbf 100644
--- a/drivers/media/usb/go7007/go7007-priv.h
+++ b/drivers/media/usb/go7007/go7007-priv.h
@@ -20,7 +20,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 struct go7007;
 
diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h
index 72cc8e8..047131b 100644
--- a/drivers/media/usb/stk1160/stk1160.h
+++ b/drivers/media/usb/stk1160/stk1160.h
@@ -23,7 +23,7 @@
 #include <linux/i2c.h>
 #include <sound/core.h>
 #include <sound/ac97_codec.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
 
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index 08fb0f2..a46766c 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -29,7 +29,7 @@
  */
 
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 #include "usbtv.h"
 
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 816dd1a..53e6484 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -15,7 +15,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 /* --------------------------------------------------------------------------
  * UVC constants
diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
index d1dd440..ad07401 100644
--- a/drivers/media/v4l2-core/Makefile
+++ b/drivers/media/v4l2-core/Makefile
@@ -33,7 +33,7 @@ obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
 obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
 obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
 
-obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o
+obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o videobuf2-v4l2.o
 obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
 obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o
 obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 4a384fc..5dc6908 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -26,7 +26,7 @@
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-device.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 #include <trace/events/v4l2.h>
 
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index ec3ad4e..38703bd 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -17,7 +17,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
diff --git a/drivers/media/v4l2-core/v4l2-trace.c b/drivers/media/v4l2-core/v4l2-trace.c
index ae10b02..4004814 100644
--- a/drivers/media/v4l2-core/v4l2-trace.c
+++ b/drivers/media/v4l2-core/v4l2-trace.c
@@ -1,6 +1,6 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/v4l2.h>
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index b866a6b..ab00ea0 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1,5 +1,5 @@
 /*
- * videobuf2-core.c - V4L2 driver helper framework
+ * videobuf2-core.c - video buffer 2 core framework
  *
  * Copyright (C) 2010 Samsung Electronics
  *
@@ -28,7 +28,7 @@
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
 #include <media/v4l2-common.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 #include <trace/events/v4l2.h>
 
@@ -1810,7 +1810,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
 	/*
 	 * If you see this warning, then the driver isn't cleaning up properly
 	 * after a failed start_streaming(). See the start_streaming()
-	 * documentation in videobuf2-core.h for more information how buffers
+	 * documentation in videobuf2-v4l2.h for more information how buffers
 	 * should be returned to vb2 in start_streaming().
 	 */
 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
@@ -2197,7 +2197,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	/*
 	 * If you see this warning, then the driver isn't cleaning up properly
 	 * in stop_streaming(). See the stop_streaming() documentation in
-	 * videobuf2-core.h for more information how buffers should be returned
+	 * videobuf2-v4l2.h for more information how buffers should be returned
 	 * to vb2 in stop_streaming().
 	 */
 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
@@ -2731,7 +2731,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
  * responsible of clearing it's content and setting initial values for some
  * required entries before calling this function.
  * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
- * to the struct vb2_queue description in include/media/videobuf2-core.h
+ * to the struct vb2_queue description in include/media/videobuf2-v4l2.h
  * for more information.
  */
 int vb2_queue_init(struct vb2_queue *q)
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
new file mode 100644
index 0000000..2f2b738
--- /dev/null
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -0,0 +1,31 @@
+/*
+ * videobuf2-v4l2.c - V4L2 driver helper framework
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Pawel Osciak <pawel@osciak.com>
+ *	   Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * The vb2_thread implementation was based on code from videobuf-dvb.c:
+ *	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+
+#include <media/videobuf2-v4l2.h>
+
+MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
+MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h
index 01ca9ea..0ffe498 100644
--- a/drivers/usb/gadget/function/uvc_queue.h
+++ b/drivers/usb/gadget/function/uvc_queue.h
@@ -6,7 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/poll.h>
 #include <linux/videodev2.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 /* Maximum frame size in bytes, for sanity checking. */
 #define UVC_MAX_FRAME_SIZE	(16*1024*1024)
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 2f6261f..97aa133 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -18,7 +18,7 @@
 #include <linux/pm.h>
 #include <linux/videodev2.h>
 #include <media/videobuf-core.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/v4l2-async.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 8849aab..5c60da9 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -17,7 +17,7 @@
 #ifndef _MEDIA_V4L2_MEM2MEM_H
 #define _MEDIA_V4L2_MEM2MEM_H
 
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 /**
  * struct v4l2_m2m_ops - mem-to-mem device driver callbacks
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4f7f7ae..155991e 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -1,5 +1,5 @@
 /*
- * videobuf2-core.h - V4L2 driver helper framework
+ * videobuf2-core.h - Video Buffer 2 Core Framework
  *
  * Copyright (C) 2010 Samsung Electronics
  *
@@ -661,5 +661,4 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
 
 void vb2_ops_wait_prepare(struct vb2_queue *vq);
 void vb2_ops_wait_finish(struct vb2_queue *vq);
-
 #endif /* _MEDIA_VIDEOBUF2_CORE_H */
diff --git a/include/media/videobuf2-dvb.h b/include/media/videobuf2-dvb.h
index 8f61456..bef9127 100644
--- a/include/media/videobuf2-dvb.h
+++ b/include/media/videobuf2-dvb.h
@@ -6,7 +6,7 @@
 #include <dvb_demux.h>
 #include <dvb_net.h>
 #include <dvb_frontend.h>
-#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
 
 struct vb2_dvb {
 	/* filling that the job of the driver */
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
new file mode 100644
index 0000000..d4a4d9a
--- /dev/null
+++ b/include/media/videobuf2-v4l2.h
@@ -0,0 +1,17 @@
+/*
+ * videobuf2-v4l2.h - V4L2 driver helper framework
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Pawel Osciak <pawel@osciak.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+#ifndef _MEDIA_VIDEOBUF2_V4L2_H
+#define _MEDIA_VIDEOBUF2_V4L2_H
+
+#include <media/videobuf2-core.h>
+
+#endif /* _MEDIA_VIDEOBUF2_V4L2_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer
  2015-08-26 11:59 [RFC PATCH v3 0/5] Refactoring Videobuf2 for common use Junghak Sung
  2015-08-26 11:59 ` [RFC PATCH v3 1/5] media: videobuf2: Replace videobuf2-core with videobuf2-v4l2 Junghak Sung
@ 2015-08-26 11:59 ` Junghak Sung
  2015-08-27 10:28   ` Mauro Carvalho Chehab
  2015-08-28 13:31   ` Hans Verkuil
  2015-08-26 11:59 ` [RFC PATCH v3 3/5] media: videobuf2: Modify all device drivers Junghak Sung
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 23+ messages in thread
From: Junghak Sung @ 2015-08-26 11:59 UTC (permalink / raw)
  To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, jh1009.sung, rany.kwon

Remove v4l2-specific stuff from struct vb2_buffer and add member variables
related with buffer management.

struct vb2_plane {
        <snip>
        /* plane information */
        unsigned int            bytesused;
        unsigned int            length;
        union {
                unsigned int    offset;
                unsigned long   userptr;
                int             fd;
        } m;
        unsigned int            data_offset;
}

struct vb2_buffer {
        <snip>
        /* buffer information */
        unsigned int            num_planes;
        unsigned int            index;
        unsigned int            type;
        unsigned int            memory;

        struct vb2_plane        planes[VIDEO_MAX_PLANES];
        <snip>
};

And create struct vb2_v4l2_buffer as container buffer for v4l2 use.

struct vb2_v4l2_buffer {
        struct vb2_buffer       vb2_buf;

        __u32                   flags;
        __u32                   field;
        struct timeval          timestamp;
        struct v4l2_timecode    timecode;
        __u32                   sequence;
};

This patch includes only changes inside of videobuf2. So, it is required to
modify all device drivers which use videobuf2.

Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
 drivers/media/v4l2-core/videobuf2-core.c |  324 +++++++++++++++++-------------
 include/media/videobuf2-core.h           |   50 ++---
 include/media/videobuf2-v4l2.h           |   26 +++
 3 files changed, 236 insertions(+), 164 deletions(-)

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index ab00ea0..9266d50 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -35,10 +35,10 @@
 static int debug;
 module_param(debug, int, 0644);
 
-#define dprintk(level, fmt, arg...)					      \
-	do {								      \
-		if (debug >= level)					      \
-			pr_info("vb2: %s: " fmt, __func__, ## arg); \
+#define dprintk(level, fmt, arg...)					\
+	do {								\
+		if (debug >= level)					\
+			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
 	} while (0)
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -53,7 +53,7 @@ module_param(debug, int, 0644);
 
 #define log_memop(vb, op)						\
 	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
-		(vb)->vb2_queue, (vb)->v4l2_buf.index, #op,		\
+		(vb)->vb2_queue, (vb)->index, #op,			\
 		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
 
 #define call_memop(vb, op, args...)					\
@@ -115,7 +115,7 @@ module_param(debug, int, 0644);
 
 #define log_vb_qop(vb, op, args...)					\
 	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
-		(vb)->vb2_queue, (vb)->v4l2_buf.index, #op,		\
+		(vb)->vb2_queue, (vb)->index, #op,			\
 		(vb)->vb2_queue->ops->op ? "" : " (nop)")
 
 #define call_vb_qop(vb, op, args...)					\
@@ -205,13 +205,13 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 		unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]);
 
 		mem_priv = call_ptr_memop(vb, alloc, q->alloc_ctx[plane],
-				      size, dma_dir, q->gfp_flags);
+					size, dma_dir, q->gfp_flags);
 		if (IS_ERR_OR_NULL(mem_priv))
 			goto free;
 
 		/* Associate allocator private data with this plane */
 		vb->planes[plane].mem_priv = mem_priv;
-		vb->v4l2_planes[plane].length = q->plane_sizes[plane];
+		vb->planes[plane].length = q->plane_sizes[plane];
 	}
 
 	return 0;
@@ -235,8 +235,7 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb)
 	for (plane = 0; plane < vb->num_planes; ++plane) {
 		call_void_memop(vb, put, vb->planes[plane].mem_priv);
 		vb->planes[plane].mem_priv = NULL;
-		dprintk(3, "freed plane %d of buffer %d\n", plane,
-			vb->v4l2_buf.index);
+		dprintk(3, "freed plane %d of buffer %d\n", plane, vb->index);
 	}
 }
 
@@ -269,7 +268,9 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p)
 
 	call_void_memop(vb, detach_dmabuf, p->mem_priv);
 	dma_buf_put(p->dbuf);
-	memset(p, 0, sizeof(*p));
+	p->mem_priv = NULL;
+	p->dbuf = NULL;
+	p->dbuf_mapped = 0;
 }
 
 /**
@@ -299,7 +300,7 @@ static void __setup_lengths(struct vb2_queue *q, unsigned int n)
 			continue;
 
 		for (plane = 0; plane < vb->num_planes; ++plane)
-			vb->v4l2_planes[plane].length = q->plane_sizes[plane];
+			vb->planes[plane].length = q->plane_sizes[plane];
 	}
 }
 
@@ -314,10 +315,10 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
 	unsigned long off;
 
 	if (q->num_buffers) {
-		struct v4l2_plane *p;
+		struct vb2_plane *p;
 		vb = q->bufs[q->num_buffers - 1];
-		p = &vb->v4l2_planes[vb->num_planes - 1];
-		off = PAGE_ALIGN(p->m.mem_offset + p->length);
+		p = &vb->planes[vb->num_planes - 1];
+		off = PAGE_ALIGN(p->m.offset + p->length);
 	} else {
 		off = 0;
 	}
@@ -328,12 +329,12 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
 			continue;
 
 		for (plane = 0; plane < vb->num_planes; ++plane) {
-			vb->v4l2_planes[plane].m.mem_offset = off;
+			vb->planes[plane].m.offset = off;
 
 			dprintk(3, "buffer %d, plane %d offset 0x%08lx\n",
 					buffer, plane, off);
 
-			off += vb->v4l2_planes[plane].length;
+			off += vb->planes[plane].length;
 			off = PAGE_ALIGN(off);
 		}
 	}
@@ -347,7 +348,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
  * Returns the number of buffers successfully allocated.
  */
 static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
-			     unsigned int num_buffers, unsigned int num_planes)
+			unsigned int num_buffers, unsigned int num_planes)
 {
 	unsigned int buffer;
 	struct vb2_buffer *vb;
@@ -361,16 +362,12 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
 			break;
 		}
 
-		/* Length stores number of planes for multiplanar buffers */
-		if (V4L2_TYPE_IS_MULTIPLANAR(q->type))
-			vb->v4l2_buf.length = num_planes;
-
 		vb->state = VB2_BUF_STATE_DEQUEUED;
 		vb->vb2_queue = q;
 		vb->num_planes = num_planes;
-		vb->v4l2_buf.index = q->num_buffers + buffer;
-		vb->v4l2_buf.type = q->type;
-		vb->v4l2_buf.memory = memory;
+		vb->index = q->num_buffers + buffer;
+		vb->type = q->type;
+		vb->memory = memory;
 
 		/* Allocate video buffer memory for the MMAP type */
 		if (memory == V4L2_MEMORY_MMAP) {
@@ -418,7 +415,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
 	struct vb2_buffer *vb;
 
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
-	     ++buffer) {
+			++buffer) {
 		vb = q->bufs[buffer];
 		if (!vb)
 			continue;
@@ -451,7 +448,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 	 * just return -EAGAIN.
 	 */
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
-	     ++buffer) {
+			++buffer) {
 		if (q->bufs[buffer] == NULL)
 			continue;
 		if (q->bufs[buffer]->state == VB2_BUF_STATE_PREPARING) {
@@ -462,7 +459,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 
 	/* Call driver-provided cleanup function for each buffer, if provided */
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
-	     ++buffer) {
+			++buffer) {
 		struct vb2_buffer *vb = q->bufs[buffer];
 
 		if (vb && vb->planes[0].mem_priv)
@@ -536,7 +533,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 
 	/* Free videobuf buffers */
 	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
-	     ++buffer) {
+			++buffer) {
 		kfree(q->bufs[buffer]);
 		q->bufs[buffer] = NULL;
 	}
@@ -590,23 +587,22 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
 		for (plane = 0; plane < vb->num_planes; ++plane) {
 			length = (b->memory == V4L2_MEMORY_USERPTR ||
-				  b->memory == V4L2_MEMORY_DMABUF)
-			       ? b->m.planes[plane].length
-			       : vb->v4l2_planes[plane].length;
+				b->memory == V4L2_MEMORY_DMABUF)
+				? b->m.planes[plane].length
+				: vb->planes[plane].length;
 			bytesused = b->m.planes[plane].bytesused
-				  ? b->m.planes[plane].bytesused : length;
+				? b->m.planes[plane].bytesused : length;
 
 			if (b->m.planes[plane].bytesused > length)
 				return -EINVAL;
 
 			if (b->m.planes[plane].data_offset > 0 &&
-			    b->m.planes[plane].data_offset >= bytesused)
+				b->m.planes[plane].data_offset >= bytesused)
 				return -EINVAL;
 		}
 	} else {
 		length = (b->memory == V4L2_MEMORY_USERPTR)
-		       ? b->length : vb->v4l2_planes[0].length;
-		bytesused = b->bytesused ? b->bytesused : length;
+			? b->length : vb->planes[0].length;
 
 		if (b->bytesused > length)
 			return -EINVAL;
@@ -656,12 +652,21 @@ static bool __buffers_in_use(struct vb2_queue *q)
  */
 static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int plane;
 
 	/* Copy back data such as timestamp, flags, etc. */
-	memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
-	b->reserved2 = vb->v4l2_buf.reserved2;
-	b->reserved = vb->v4l2_buf.reserved;
+	b->index = vb->index;
+	b->type = vb->type;
+	b->memory = vb->memory;
+	b->bytesused = 0;
+
+	b->flags = vbuf->flags;
+	b->field = vbuf->field;
+	b->timestamp = vbuf->timestamp;
+	b->timecode = vbuf->timecode;
+	b->sequence = vbuf->sequence;
 
 	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
 		/*
@@ -669,21 +674,33 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 		 * for it. The caller has already verified memory and size.
 		 */
 		b->length = vb->num_planes;
-		memcpy(b->m.planes, vb->v4l2_planes,
-			b->length * sizeof(struct v4l2_plane));
+		for (plane = 0; plane < vb->num_planes; ++plane) {
+			struct v4l2_plane *pdst = &b->m.planes[plane];
+			struct vb2_plane *psrc = &vb->planes[plane];
+
+			pdst->bytesused = psrc->bytesused;
+			pdst->length = psrc->length;
+			if (q->memory == V4L2_MEMORY_MMAP)
+				pdst->m.mem_offset = psrc->m.offset;
+			else if (q->memory == V4L2_MEMORY_USERPTR)
+				pdst->m.userptr = psrc->m.userptr;
+			else if (q->memory == V4L2_MEMORY_DMABUF)
+				pdst->m.fd = psrc->m.fd;
+			pdst->data_offset = psrc->data_offset;
+		}
 	} else {
 		/*
 		 * We use length and offset in v4l2_planes array even for
 		 * single-planar buffers, but userspace does not.
 		 */
-		b->length = vb->v4l2_planes[0].length;
-		b->bytesused = vb->v4l2_planes[0].bytesused;
+		b->length = vb->planes[0].length;
+		b->bytesused = vb->planes[0].bytesused;
 		if (q->memory == V4L2_MEMORY_MMAP)
-			b->m.offset = vb->v4l2_planes[0].m.mem_offset;
+			b->m.offset = vb->planes[0].m.offset;
 		else if (q->memory == V4L2_MEMORY_USERPTR)
-			b->m.userptr = vb->v4l2_planes[0].m.userptr;
+			b->m.userptr = vb->planes[0].m.userptr;
 		else if (q->memory == V4L2_MEMORY_DMABUF)
-			b->m.fd = vb->v4l2_planes[0].m.fd;
+			b->m.fd = vb->planes[0].m.fd;
 	}
 
 	/*
@@ -692,7 +709,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
 	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
 	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
-	    V4L2_BUF_FLAG_TIMESTAMP_COPY) {
+			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
 		/*
 		 * For non-COPY timestamps, drop timestamp source bits
 		 * and obtain the timestamp source from the queue.
@@ -767,7 +784,7 @@ EXPORT_SYMBOL(vb2_querybuf);
 static int __verify_userptr_ops(struct vb2_queue *q)
 {
 	if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
-	    !q->mem_ops->put_userptr)
+			!q->mem_ops->put_userptr)
 		return -EINVAL;
 
 	return 0;
@@ -780,7 +797,7 @@ static int __verify_userptr_ops(struct vb2_queue *q)
 static int __verify_mmap_ops(struct vb2_queue *q)
 {
 	if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
-	    !q->mem_ops->put || !q->mem_ops->mmap)
+			!q->mem_ops->put || !q->mem_ops->mmap)
 		return -EINVAL;
 
 	return 0;
@@ -793,8 +810,8 @@ static int __verify_mmap_ops(struct vb2_queue *q)
 static int __verify_dmabuf_ops(struct vb2_queue *q)
 {
 	if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
-	    !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
-	    !q->mem_ops->unmap_dmabuf)
+		!q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
+		!q->mem_ops->unmap_dmabuf)
 		return -EINVAL;
 
 	return 0;
@@ -808,7 +825,7 @@ static int __verify_memory_type(struct vb2_queue *q,
 		enum v4l2_memory memory, enum v4l2_buf_type type)
 {
 	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
-	    memory != V4L2_MEMORY_DMABUF) {
+			memory != V4L2_MEMORY_DMABUF) {
 		dprintk(1, "unsupported memory type\n");
 		return -EINVAL;
 	}
@@ -927,7 +944,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
 	 * Driver also sets the size and allocator context for each plane.
 	 */
 	ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
-		       q->plane_sizes, q->alloc_ctx);
+			q->plane_sizes, q->alloc_ctx);
 	if (ret)
 		return ret;
 
@@ -952,7 +969,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
 		num_buffers = allocated_buffers;
 
 		ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
-			       &num_planes, q->plane_sizes, q->alloc_ctx);
+				&num_planes, q->plane_sizes, q->alloc_ctx);
 
 		if (!ret && allocated_buffers < num_buffers)
 			ret = -ENOMEM;
@@ -1040,7 +1057,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
 	 * buffer and their sizes are acceptable
 	 */
 	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
-		       &num_planes, q->plane_sizes, q->alloc_ctx);
+			&num_planes, q->plane_sizes, q->alloc_ctx);
 	if (ret)
 		return ret;
 
@@ -1063,7 +1080,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
 		 * queue driver has set up
 		 */
 		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
-			       &num_planes, q->plane_sizes, q->alloc_ctx);
+				&num_planes, q->plane_sizes, q->alloc_ctx);
 
 		if (!ret && allocated_buffers < num_buffers)
 			ret = -ENOMEM;
@@ -1183,8 +1200,8 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 		return;
 
 	if (WARN_ON(state != VB2_BUF_STATE_DONE &&
-		    state != VB2_BUF_STATE_ERROR &&
-		    state != VB2_BUF_STATE_QUEUED))
+		state != VB2_BUF_STATE_ERROR &&
+		state != VB2_BUF_STATE_QUEUED))
 		state = VB2_BUF_STATE_ERROR;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -1195,7 +1212,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 	vb->cnt_buf_done++;
 #endif
 	dprintk(4, "done processing on buffer %d, state: %d\n",
-			vb->v4l2_buf.index, state);
+			vb->index, state);
 
 	/* sync buffers */
 	for (plane = 0; plane < vb->num_planes; ++plane)
@@ -1268,25 +1285,26 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
  * v4l2_buffer by the userspace. The caller has already verified that struct
  * v4l2_buffer has a valid number of planes.
  */
-static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
-				struct v4l2_plane *v4l2_planes)
+static void __fill_vb2_buffer(struct vb2_buffer *vb,
+		const struct v4l2_buffer *b, struct vb2_plane *planes)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	unsigned int plane;
 
 	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
 		if (b->memory == V4L2_MEMORY_USERPTR) {
 			for (plane = 0; plane < vb->num_planes; ++plane) {
-				v4l2_planes[plane].m.userptr =
+				planes[plane].m.userptr =
 					b->m.planes[plane].m.userptr;
-				v4l2_planes[plane].length =
+				planes[plane].length =
 					b->m.planes[plane].length;
 			}
 		}
 		if (b->memory == V4L2_MEMORY_DMABUF) {
 			for (plane = 0; plane < vb->num_planes; ++plane) {
-				v4l2_planes[plane].m.fd =
+				planes[plane].m.fd =
 					b->m.planes[plane].m.fd;
-				v4l2_planes[plane].length =
+				planes[plane].length =
 					b->m.planes[plane].length;
 			}
 		}
@@ -1310,7 +1328,7 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
 			 * applications working.
 			 */
 			for (plane = 0; plane < vb->num_planes; ++plane) {
-				struct v4l2_plane *pdst = &v4l2_planes[plane];
+				struct vb2_plane *pdst = &planes[plane];
 				struct v4l2_plane *psrc = &b->m.planes[plane];
 
 				if (psrc->bytesused == 0)
@@ -1340,13 +1358,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
 		 * old userspace applications working.
 		 */
 		if (b->memory == V4L2_MEMORY_USERPTR) {
-			v4l2_planes[0].m.userptr = b->m.userptr;
-			v4l2_planes[0].length = b->length;
+			planes[0].m.userptr = b->m.userptr;
+			planes[0].length = b->length;
 		}
 
 		if (b->memory == V4L2_MEMORY_DMABUF) {
-			v4l2_planes[0].m.fd = b->m.fd;
-			v4l2_planes[0].length = b->length;
+			planes[0].m.fd = b->m.fd;
+			planes[0].length = b->length;
 		}
 
 		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
@@ -1354,25 +1372,26 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
 				vb2_warn_zero_bytesused(vb);
 
 			if (vb->vb2_queue->allow_zero_bytesused)
-				v4l2_planes[0].bytesused = b->bytesused;
+				planes[0].bytesused = b->bytesused;
 			else
-				v4l2_planes[0].bytesused = b->bytesused ?
-					b->bytesused : v4l2_planes[0].length;
+				planes[0].bytesused = b->bytesused ?
+					b->bytesused : planes[0].length;
 		} else
-			v4l2_planes[0].bytesused = 0;
+			planes[0].bytesused = 0;
 
 	}
 
 	/* Zero flags that the vb2 core handles */
-	vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
+	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
 	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
-	    V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
+			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
+			!V4L2_TYPE_IS_OUTPUT(b->type)) {
 		/*
 		 * Non-COPY timestamps and non-OUTPUT queues will get
 		 * their timestamp and timestamp source flags from the
 		 * queue.
 		 */
-		vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
 	}
 
 	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
@@ -1382,11 +1401,11 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
 		 * The 'field' is valid metadata for this output buffer
 		 * and so that needs to be copied here.
 		 */
-		vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TIMECODE;
-		vb->v4l2_buf.field = b->field;
+		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
+		vbuf->field = b->field;
 	} else {
 		/* Zero any output buffer flags as this is a capture buffer */
-		vb->v4l2_buf.flags &= ~V4L2_BUFFER_OUT_FLAGS;
+		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
 	}
 }
 
@@ -1395,7 +1414,7 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
  */
 static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
-	__fill_vb2_buffer(vb, b, vb->v4l2_planes);
+	__fill_vb2_buffer(vb, b, vb->planes);
 	return call_vb_qop(vb, buf_prepare, vb);
 }
 
@@ -1404,7 +1423,7 @@ static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
  */
 static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
-	struct v4l2_plane planes[VIDEO_MAX_PLANES];
+	struct vb2_plane planes[VIDEO_MAX_PLANES];
 	struct vb2_queue *q = vb->vb2_queue;
 	void *mem_priv;
 	unsigned int plane;
@@ -1419,9 +1438,9 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 
 	for (plane = 0; plane < vb->num_planes; ++plane) {
 		/* Skip the plane if already verified */
-		if (vb->v4l2_planes[plane].m.userptr &&
-		    vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
-		    && vb->v4l2_planes[plane].length == planes[plane].length)
+		if (vb->planes[plane].m.userptr &&
+			vb->planes[plane].m.userptr == planes[plane].m.userptr
+			&& vb->planes[plane].length == planes[plane].length)
 			continue;
 
 		dprintk(3, "userspace address for plane %d changed, "
@@ -1447,12 +1466,15 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 		}
 
 		vb->planes[plane].mem_priv = NULL;
-		memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
+		vb->planes[plane].bytesused = 0;
+		vb->planes[plane].length = 0;
+		vb->planes[plane].m.userptr = 0;
+		vb->planes[plane].data_offset = 0;
 
 		/* Acquire each plane's memory */
 		mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane],
-				      planes[plane].m.userptr,
-				      planes[plane].length, dma_dir);
+					planes[plane].m.userptr,
+					planes[plane].length, dma_dir);
 		if (IS_ERR_OR_NULL(mem_priv)) {
 			dprintk(1, "failed acquiring userspace "
 						"memory for plane %d\n", plane);
@@ -1466,8 +1488,12 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	 * Now that everything is in order, copy relevant information
 	 * provided by userspace.
 	 */
-	for (plane = 0; plane < vb->num_planes; ++plane)
-		vb->v4l2_planes[plane] = planes[plane];
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		vb->planes[plane].bytesused = planes[plane].bytesused;
+		vb->planes[plane].length = planes[plane].length;
+		vb->planes[plane].m.userptr = planes[plane].m.userptr;
+		vb->planes[plane].data_offset = planes[plane].data_offset;
+	}
 
 	if (reacquired) {
 		/*
@@ -1494,10 +1520,11 @@ err:
 	/* In case of errors, release planes that were already acquired */
 	for (plane = 0; plane < vb->num_planes; ++plane) {
 		if (vb->planes[plane].mem_priv)
-			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
+			call_void_memop(vb, put_userptr,
+				vb->planes[plane].mem_priv);
 		vb->planes[plane].mem_priv = NULL;
-		vb->v4l2_planes[plane].m.userptr = 0;
-		vb->v4l2_planes[plane].length = 0;
+		vb->planes[plane].m.userptr = 0;
+		vb->planes[plane].length = 0;
 	}
 
 	return ret;
@@ -1508,7 +1535,7 @@ err:
  */
 static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
-	struct v4l2_plane planes[VIDEO_MAX_PLANES];
+	struct vb2_plane planes[VIDEO_MAX_PLANES];
 	struct vb2_queue *q = vb->vb2_queue;
 	void *mem_priv;
 	unsigned int plane;
@@ -1544,7 +1571,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 
 		/* Skip the plane if already verified */
 		if (dbuf == vb->planes[plane].dbuf &&
-		    vb->v4l2_planes[plane].length == planes[plane].length) {
+			vb->planes[plane].length == planes[plane].length) {
 			dma_buf_put(dbuf);
 			continue;
 		}
@@ -1558,11 +1585,15 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 
 		/* Release previously acquired memory if present */
 		__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
-		memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
+		vb->planes[plane].bytesused = 0;
+		vb->planes[plane].length = 0;
+		vb->planes[plane].m.fd = 0;
+		vb->planes[plane].data_offset = 0;
 
 		/* Acquire each plane's memory */
-		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
-			dbuf, planes[plane].length, dma_dir);
+		mem_priv = call_ptr_memop(vb, attach_dmabuf,
+			q->alloc_ctx[plane], dbuf, planes[plane].length,
+			dma_dir);
 		if (IS_ERR(mem_priv)) {
 			dprintk(1, "failed to attach dmabuf\n");
 			ret = PTR_ERR(mem_priv);
@@ -1592,8 +1623,12 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	 * Now that everything is in order, copy relevant information
 	 * provided by userspace.
 	 */
-	for (plane = 0; plane < vb->num_planes; ++plane)
-		vb->v4l2_planes[plane] = planes[plane];
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		vb->planes[plane].bytesused = planes[plane].bytesused;
+		vb->planes[plane].length = planes[plane].length;
+		vb->planes[plane].m.fd = planes[plane].m.userptr;
+		vb->planes[plane].data_offset = planes[plane].data_offset;
+	}
 
 	if (reacquired) {
 		/*
@@ -1644,6 +1679,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
 
 static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct vb2_queue *q = vb->vb2_queue;
 	int ret;
 
@@ -1672,9 +1708,9 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	}
 
 	vb->state = VB2_BUF_STATE_PREPARING;
-	vb->v4l2_buf.timestamp.tv_sec = 0;
-	vb->v4l2_buf.timestamp.tv_usec = 0;
-	vb->v4l2_buf.sequence = 0;
+	vbuf->timestamp.tv_sec = 0;
+	vbuf->timestamp.tv_usec = 0;
+	vbuf->sequence = 0;
 
 	switch (q->memory) {
 	case V4L2_MEMORY_MMAP:
@@ -1701,7 +1737,7 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 }
 
 static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
-				    const char *opname)
+					const char *opname)
 {
 	if (b->type != q->type) {
 		dprintk(1, "%s: invalid buffer type\n", opname);
@@ -1768,7 +1804,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
 		/* Fill buffer information for the userspace */
 		__fill_v4l2_buffer(vb, b);
 
-		dprintk(1, "prepare of buffer %d succeeded\n", vb->v4l2_buf.index);
+		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
 	}
 	return ret;
 }
@@ -1800,7 +1836,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
 	/* Tell the driver to start streaming */
 	q->start_streaming_called = 1;
 	ret = call_qop(q, start_streaming, q,
-		       atomic_read(&q->owned_by_drv_count));
+			atomic_read(&q->owned_by_drv_count));
 	if (!ret)
 		return 0;
 
@@ -1810,7 +1846,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
 	/*
 	 * If you see this warning, then the driver isn't cleaning up properly
 	 * after a failed start_streaming(). See the start_streaming()
-	 * documentation in videobuf2-v4l2.h for more information how buffers
+	 * documentation in videobuf2-core.h for more information how buffers
 	 * should be returned to vb2 in start_streaming().
 	 */
 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
@@ -1841,11 +1877,13 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 {
 	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
 	struct vb2_buffer *vb;
+	struct vb2_v4l2_buffer *vbuf;
 
 	if (ret)
 		return ret;
 
 	vb = q->bufs[b->index];
+	vbuf = to_vb2_v4l2_buffer(vb);
 
 	switch (vb->state) {
 	case VB2_BUF_STATE_DEQUEUED:
@@ -1877,11 +1915,11 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 		 * and the timecode field and flag if needed.
 		 */
 		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
-		    V4L2_BUF_FLAG_TIMESTAMP_COPY)
-			vb->v4l2_buf.timestamp = b->timestamp;
-		vb->v4l2_buf.flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
+				V4L2_BUF_FLAG_TIMESTAMP_COPY)
+			vbuf->timestamp = b->timestamp;
+		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
 		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
-			vb->v4l2_buf.timecode = b->timecode;
+			vbuf->timecode = b->timecode;
 	}
 
 	trace_vb2_qbuf(q, vb);
@@ -1903,13 +1941,13 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 	 * then we can finally call start_streaming().
 	 */
 	if (q->streaming && !q->start_streaming_called &&
-	    q->queued_count >= q->min_buffers_needed) {
+			q->queued_count >= q->min_buffers_needed) {
 		ret = vb2_start_streaming(q);
 		if (ret)
 			return ret;
 	}
 
-	dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
+	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
 	return 0;
 }
 
@@ -2099,9 +2137,11 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
 		}
 }
 
-static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
+static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
+		bool nonblocking)
 {
 	struct vb2_buffer *vb = NULL;
+	struct vb2_v4l2_buffer *vbuf = NULL;
 	int ret;
 
 	if (b->type != q->type) {
@@ -2134,14 +2174,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool n
 
 	trace_vb2_dqbuf(q, vb);
 
+	vbuf = to_vb2_v4l2_buffer(vb);
 	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
-	    vb->v4l2_buf.flags & V4L2_BUF_FLAG_LAST)
+			vbuf->flags & V4L2_BUF_FLAG_LAST)
 		q->last_buffer_dequeued = true;
 	/* go back to dequeued state */
 	__vb2_dqbuf(vb);
 
 	dprintk(1, "dqbuf of buffer %d, with state %d\n",
-			vb->v4l2_buf.index, vb->state);
+			vb->index, vb->state);
 
 	return 0;
 }
@@ -2197,7 +2238,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	/*
 	 * If you see this warning, then the driver isn't cleaning up properly
 	 * in stop_streaming(). See the stop_streaming() documentation in
-	 * videobuf2-v4l2.h for more information how buffers should be returned
+	 * videobuf2-core.h for more information how buffers should be returned
 	 * to vb2 in stop_streaming().
 	 */
 	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
@@ -2399,7 +2440,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 		vb = q->bufs[buffer];
 
 		for (plane = 0; plane < vb->num_planes; ++plane) {
-			if (vb->v4l2_planes[plane].m.mem_offset == off) {
+			if (vb->planes[plane].m.offset == off) {
 				*_buffer = buffer;
 				*_plane = plane;
 				return 0;
@@ -2557,7 +2598,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 	 * The buffer length was page_aligned at __vb2_buf_mem_alloc(),
 	 * so, we need to do the same here.
 	 */
-	length = PAGE_ALIGN(vb->v4l2_planes[plane].length);
+	length = PAGE_ALIGN(vb->planes[plane].length);
 	if (length < (vma->vm_end - vma->vm_start)) {
 		dprintk(1,
 			"MMAP invalid, as it would overflow buffer length\n");
@@ -2577,10 +2618,10 @@ EXPORT_SYMBOL_GPL(vb2_mmap);
 
 #ifndef CONFIG_MMU
 unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
-				    unsigned long addr,
-				    unsigned long len,
-				    unsigned long pgoff,
-				    unsigned long flags)
+					unsigned long addr,
+					unsigned long len,
+					unsigned long pgoff,
+					unsigned long flags)
 {
 	unsigned long off = pgoff << PAGE_SHIFT;
 	struct vb2_buffer *vb;
@@ -2731,7 +2772,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
  * responsible of clearing it's content and setting initial values for some
  * required entries before calling this function.
  * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
- * to the struct vb2_queue description in include/media/videobuf2-v4l2.h
+ * to the struct vb2_queue description in include/media/videobuf2-core.h
  * for more information.
  */
 int vb2_queue_init(struct vb2_queue *q)
@@ -2739,16 +2780,16 @@ int vb2_queue_init(struct vb2_queue *q)
 	/*
 	 * Sanity check
 	 */
-	if (WARN_ON(!q)			  ||
-	    WARN_ON(!q->ops)		  ||
-	    WARN_ON(!q->mem_ops)	  ||
-	    WARN_ON(!q->type)		  ||
-	    WARN_ON(!q->io_modes)	  ||
-	    WARN_ON(!q->ops->queue_setup) ||
-	    WARN_ON(!q->ops->buf_queue)   ||
-	    WARN_ON(q->timestamp_flags &
-		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
-		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
+	if (WARN_ON(!q)				||
+		WARN_ON(!q->ops)		||
+		WARN_ON(!q->mem_ops)		||
+		WARN_ON(!q->type)		||
+		WARN_ON(!q->io_modes)		||
+		WARN_ON(!q->ops->queue_setup)	||
+		WARN_ON(!q->ops->buf_queue)	||
+		WARN_ON(q->timestamp_flags &
+			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
+			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
 		return -EINVAL;
 
 	/* Warn that the driver should choose an appropriate timestamp type */
@@ -2852,7 +2893,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
 	 * Sanity check
 	 */
 	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
-		    (!read && !(q->io_modes & VB2_WRITE))))
+			(!read && !(q->io_modes & VB2_WRITE))))
 		return -EINVAL;
 
 	/*
@@ -3063,9 +3104,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
 		buf->queued = 0;
 		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
 				 : vb2_plane_size(q->bufs[index], 0);
-		/* Compensate for data_offset on read in the multiplanar case. */
+		/*
+		 * Compensate for data_offset on read
+		 * in the multiplanar case
+		 */
 		if (is_multiplanar && read &&
-		    fileio->b.m.planes[0].data_offset < buf->size) {
+			fileio->b.m.planes[0].data_offset < buf->size) {
 			buf->pos = fileio->b.m.planes[0].data_offset;
 			buf->size -= buf->pos;
 		}
@@ -3257,7 +3301,7 @@ static int vb2_thread(void *data)
  * contact the linux-media mailinglist first.
  */
 int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
-		     const char *thread_name)
+			const char *thread_name)
 {
 	struct vb2_threadio_data *threadio;
 	int ret = 0;
@@ -3491,7 +3535,7 @@ ssize_t vb2_fop_write(struct file *file, const char __user *buf,
 	if (vb2_queue_is_busy(vdev, file))
 		goto exit;
 	err = vb2_write(vdev->queue, buf, count, ppos,
-		       file->f_flags & O_NONBLOCK);
+			file->f_flags & O_NONBLOCK);
 	if (vdev->queue->fileio)
 		vdev->queue->owner = file->private_data;
 exit:
@@ -3515,7 +3559,7 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf,
 	if (vb2_queue_is_busy(vdev, file))
 		goto exit;
 	err = vb2_read(vdev->queue, buf, count, ppos,
-		       file->f_flags & O_NONBLOCK);
+			file->f_flags & O_NONBLOCK);
 	if (vdev->queue->fileio)
 		vdev->queue->owner = file->private_data;
 exit:
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 155991e..8787a6c 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -115,6 +115,16 @@ struct vb2_plane {
 	void			*mem_priv;
 	struct dma_buf		*dbuf;
 	unsigned int		dbuf_mapped;
+
+	/* plane information */
+	unsigned int		bytesused;
+	unsigned int		length;
+	union {
+		unsigned int	offset;
+		unsigned long	userptr;
+		int		fd;
+	} m;
+	unsigned int		data_offset;
 };
 
 /**
@@ -161,41 +171,33 @@ struct vb2_queue;
 
 /**
  * struct vb2_buffer - represents a video buffer
- * @v4l2_buf:		struct v4l2_buffer associated with this buffer; can
- *			be read by the driver and relevant entries can be
- *			changed by the driver in case of CAPTURE types
- *			(such as timestamp)
- * @v4l2_planes:	struct v4l2_planes associated with this buffer; can
- *			be read by the driver and relevant entries can be
- *			changed by the driver in case of CAPTURE types
- *			(such as bytesused); NOTE that even for single-planar
- *			types, the v4l2_planes[0] struct should be used
- *			instead of v4l2_buf for filling bytesused - drivers
- *			should use the vb2_set_plane_payload() function for that
  * @vb2_queue:		the queue to which this driver belongs
- * @num_planes:		number of planes in the buffer
- *			on an internal driver queue
  * @state:		current buffer state; do not change
  * @queued_entry:	entry on the queued buffers list, which holds all
  *			buffers queued from userspace
  * @done_entry:		entry on the list that stores all buffers ready to
  *			be dequeued to userspace
+ * @index:		id number of the buffer
+ * @type:		buffer type
+ * @memory:		the method, in which the actual data is passed
+ * @num_planes:		number of planes in the buffer
+ *			on an internal driver queue
  * @planes:		private per-plane information; do not change
  */
 struct vb2_buffer {
-	struct v4l2_buffer	v4l2_buf;
-	struct v4l2_plane	v4l2_planes[VIDEO_MAX_PLANES];
-
 	struct vb2_queue	*vb2_queue;
 
-	unsigned int		num_planes;
-
-/* Private: internal use only */
+	/* Private: internal use only */
 	enum vb2_buffer_state	state;
 
 	struct list_head	queued_entry;
 	struct list_head	done_entry;
 
+	/* buffer information */
+	unsigned int		index;
+	unsigned int		type;
+	unsigned int		memory;
+	unsigned int		num_planes;
 	struct vb2_plane	planes[VIDEO_MAX_PLANES];
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -390,7 +392,7 @@ struct v4l2_fh;
  * @threadio:	thread io internal data, used only if thread is active
  */
 struct vb2_queue {
-	enum v4l2_buf_type		type;
+	unsigned int			type;
 	unsigned int			io_modes;
 	unsigned			fileio_read_once:1;
 	unsigned			fileio_write_immediately:1;
@@ -409,7 +411,7 @@ struct vb2_queue {
 
 	/* private: internal use only */
 	struct mutex			mmap_lock;
-	enum v4l2_memory		memory;
+	unsigned int			memory;
 	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
 	unsigned int			num_buffers;
 
@@ -571,7 +573,7 @@ static inline void vb2_set_plane_payload(struct vb2_buffer *vb,
 				 unsigned int plane_no, unsigned long size)
 {
 	if (plane_no < vb->num_planes)
-		vb->v4l2_planes[plane_no].bytesused = size;
+		vb->planes[plane_no].bytesused = size;
 }
 
 /**
@@ -583,7 +585,7 @@ static inline unsigned long vb2_get_plane_payload(struct vb2_buffer *vb,
 				 unsigned int plane_no)
 {
 	if (plane_no < vb->num_planes)
-		return vb->v4l2_planes[plane_no].bytesused;
+		return vb->planes[plane_no].bytesused;
 	return 0;
 }
 
@@ -596,7 +598,7 @@ static inline unsigned long
 vb2_plane_size(struct vb2_buffer *vb, unsigned int plane_no)
 {
 	if (plane_no < vb->num_planes)
-		return vb->v4l2_planes[plane_no].length;
+		return vb->planes[plane_no].length;
 	return 0;
 }
 
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index d4a4d9a..fc2dbe9 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -12,6 +12,32 @@
 #ifndef _MEDIA_VIDEOBUF2_V4L2_H
 #define _MEDIA_VIDEOBUF2_V4L2_H
 
+#include <linux/videodev2.h>
 #include <media/videobuf2-core.h>
 
+/**
+ * struct vb2_v4l2_buffer - video buffer information for v4l2
+ * @vb2_buf:	video buffer 2
+ * @flags:	buffer informational flags
+ * @field:	enum v4l2_field; field order of the image in the buffer
+ * @timestamp:	frame timestamp
+ * @timecode:	frame timecode
+ * @sequence:	sequence count of this frame
+ */
+struct vb2_v4l2_buffer {
+	struct vb2_buffer	vb2_buf;
+
+	__u32			flags;
+	__u32			field;
+	struct timeval		timestamp;
+	struct v4l2_timecode	timecode;
+	__u32			sequence;
+};
+
+/**
+ * to_vb2_v4l2_buffer() - cast struct vb2_buffer * to struct vb2_v4l2_buffer *
+ */
+#define to_vb2_v4l2_buffer(vb) \
+	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
+
 #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH v3 3/5] media: videobuf2: Modify all device drivers
  2015-08-26 11:59 [RFC PATCH v3 0/5] Refactoring Videobuf2 for common use Junghak Sung
  2015-08-26 11:59 ` [RFC PATCH v3 1/5] media: videobuf2: Replace videobuf2-core with videobuf2-v4l2 Junghak Sung
  2015-08-26 11:59 ` [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer Junghak Sung
@ 2015-08-26 11:59 ` Junghak Sung
  2015-08-27 10:33   ` Mauro Carvalho Chehab
  2015-08-26 11:59 ` [RFC PATCH v3 4/5] media: videobuf2: Change queue_setup argument Junghak Sung
  2015-08-26 11:59 ` [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts Junghak Sung
  4 siblings, 1 reply; 23+ messages in thread
From: Junghak Sung @ 2015-08-26 11:59 UTC (permalink / raw)
  To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, jh1009.sung, rany.kwon

Modify all device drivers related with previous change that restructures
vb2_buffer for common use.
Actually, not all device drivers, yet. So, it required to modifiy more file
to complete this patch.

Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
 drivers/input/touchscreen/sur40.c                  |   17 +++---
 drivers/media/dvb-frontends/rtl2832_sdr.c          |   14 ++---
 drivers/media/pci/cobalt/cobalt-driver.h           |    2 +-
 drivers/media/pci/cobalt/cobalt-irq.c              |    8 +--
 drivers/media/pci/cobalt/cobalt-v4l2.c             |    8 +--
 drivers/media/pci/cx23885/cx23885-417.c            |   11 ++--
 drivers/media/pci/cx23885/cx23885-core.c           |   24 +++++----
 drivers/media/pci/cx23885/cx23885-dvb.c            |    9 ++--
 drivers/media/pci/cx23885/cx23885-vbi.c            |   16 +++---
 drivers/media/pci/cx23885/cx23885-video.c          |   27 +++++-----
 drivers/media/pci/cx23885/cx23885.h                |    2 +-
 drivers/media/pci/cx25821/cx25821-video.c          |   21 ++++----
 drivers/media/pci/cx25821/cx25821.h                |    3 +-
 drivers/media/pci/cx88/cx88-blackbird.c            |   13 +++--
 drivers/media/pci/cx88/cx88-core.c                 |    8 +--
 drivers/media/pci/cx88/cx88-dvb.c                  |   11 ++--
 drivers/media/pci/cx88/cx88-mpeg.c                 |   14 ++---
 drivers/media/pci/cx88/cx88-vbi.c                  |   17 +++---
 drivers/media/pci/cx88/cx88-video.c                |   19 ++++---
 drivers/media/pci/cx88/cx88.h                      |    2 +-
 drivers/media/pci/dt3155/dt3155.c                  |   17 +++---
 drivers/media/pci/dt3155/dt3155.h                  |    3 +-
 drivers/media/pci/netup_unidvb/netup_unidvb_core.c |   19 ++++---
 drivers/media/pci/saa7134/saa7134-core.c           |   14 ++---
 drivers/media/pci/saa7134/saa7134-ts.c             |   14 +++--
 drivers/media/pci/saa7134/saa7134-vbi.c            |   10 ++--
 drivers/media/pci/saa7134/saa7134-video.c          |   21 +++++---
 drivers/media/pci/saa7134/saa7134.h                |    2 +-
 drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c     |    2 +-
 drivers/media/pci/solo6x10/solo6x10.h              |    2 +-
 drivers/media/pci/sta2x11/sta2x11_vip.c            |   12 ++---
 drivers/media/pci/tw68/tw68-video.c                |   10 ++--
 drivers/media/pci/tw68/tw68.h                      |    2 +-
 drivers/media/platform/am437x/am437x-vpfe.c        |   20 ++++----
 drivers/media/platform/am437x/am437x-vpfe.h        |    2 +-
 drivers/media/platform/blackfin/bfin_capture.c     |   10 ++--
 drivers/media/platform/davinci/vpif_capture.c      |   17 +++---
 drivers/media/platform/davinci/vpif_capture.h      |    2 +-
 drivers/media/platform/davinci/vpif_display.c      |   27 +++++-----
 drivers/media/platform/davinci/vpif_display.h      |    2 +-
 drivers/media/platform/exynos-gsc/gsc-core.h       |    2 +-
 drivers/media/platform/exynos4-is/fimc-capture.c   |   13 ++---
 drivers/media/platform/exynos4-is/fimc-core.h      |    2 +-
 drivers/media/platform/exynos4-is/fimc-isp.h       |    2 +-
 drivers/media/platform/exynos4-is/fimc-lite.c      |   10 ++--
 drivers/media/platform/exynos4-is/fimc-lite.h      |    2 +-
 drivers/media/platform/m2m-deinterlace.c           |   23 +++++----
 drivers/media/platform/marvell-ccic/mcam-core.c    |   43 +++++++++-------
 drivers/media/platform/omap3isp/ispvideo.c         |   19 +++----
 drivers/media/platform/omap3isp/ispvideo.h         |    2 +-
 drivers/media/platform/s3c-camif/camif-capture.c   |   10 ++--
 drivers/media/platform/s3c-camif/camif-core.h      |    2 +-
 drivers/media/platform/s5p-tv/mixer.h              |    2 +-
 drivers/media/platform/s5p-tv/mixer_reg.c          |    2 +-
 drivers/media/platform/s5p-tv/mixer_video.c        |    8 +--
 drivers/media/platform/sh_veu.c                    |   19 +++----
 drivers/media/platform/sh_vou.c                    |   15 +++---
 drivers/media/platform/soc_camera/atmel-isi.c      |    6 +--
 drivers/media/platform/soc_camera/mx2_camera.c     |    2 +-
 drivers/media/platform/soc_camera/mx3_camera.c     |    4 +-
 drivers/media/platform/soc_camera/rcar_vin.c       |    2 +-
 .../platform/soc_camera/sh_mobile_ceu_camera.c     |    2 +-
 drivers/media/platform/vivid/vivid-core.h          |    2 +-
 drivers/media/platform/vivid/vivid-kthread-cap.c   |   54 ++++++++++----------
 drivers/media/platform/vivid/vivid-kthread-out.c   |   34 ++++++------
 drivers/media/platform/vivid/vivid-sdr-cap.c       |   15 +++---
 drivers/media/platform/vivid/vivid-vbi-cap.c       |   23 +++++----
 drivers/media/platform/vivid/vivid-vbi-out.c       |    3 +-
 drivers/media/platform/vivid/vivid-vid-cap.c       |    3 +-
 drivers/media/platform/vivid/vivid-vid-out.c       |    3 +-
 drivers/media/platform/vsp1/vsp1_video.c           |   10 ++--
 drivers/media/platform/vsp1/vsp1_video.h           |    2 +-
 drivers/media/platform/xilinx/xilinx-dma.c         |   18 +++----
 drivers/media/usb/airspy/airspy.c                  |   17 +++---
 drivers/media/usb/au0828/au0828-vbi.c              |    6 +--
 drivers/media/usb/au0828/au0828-video.c            |   45 ++++++++--------
 drivers/media/usb/au0828/au0828.h                  |    3 +-
 drivers/media/usb/em28xx/em28xx-vbi.c              |    2 +-
 drivers/media/usb/em28xx/em28xx-video.c            |   22 ++++----
 drivers/media/usb/em28xx/em28xx.h                  |    3 +-
 drivers/media/usb/go7007/go7007-driver.c           |   24 ++++-----
 drivers/media/usb/go7007/go7007-priv.h             |    2 +-
 drivers/media/usb/go7007/go7007-v4l2.c             |   20 ++++----
 drivers/media/usb/hackrf/hackrf.c                  |   15 +++---
 drivers/media/usb/msi2500/msi2500.c                |   10 ++--
 drivers/media/usb/pwc/pwc-if.c                     |   29 ++++++-----
 drivers/media/usb/pwc/pwc-uncompress.c             |    8 +--
 drivers/media/usb/pwc/pwc.h                        |    3 +-
 drivers/media/usb/s2255/s2255drv.c                 |   27 +++++-----
 drivers/media/usb/stk1160/stk1160-v4l.c            |   15 +++---
 drivers/media/usb/stk1160/stk1160-video.c          |   12 ++---
 drivers/media/usb/stk1160/stk1160.h                |    2 +-
 drivers/media/usb/usbtv/usbtv-video.c              |   19 +++----
 drivers/media/usb/usbtv/usbtv.h                    |    3 +-
 drivers/media/usb/uvc/uvc_queue.c                  |   26 ++++++----
 drivers/media/usb/uvc/uvc_video.c                  |   20 ++++----
 drivers/media/usb/uvc/uvcvideo.h                   |    4 +-
 drivers/media/v4l2-core/v4l2-mem2mem.c             |    8 +--
 drivers/usb/gadget/function/uvc_queue.c            |   26 +++++-----
 drivers/usb/gadget/function/uvc_queue.h            |    2 +-
 include/media/v4l2-mem2mem.h                       |    9 ++--
 include/trace/events/v4l2.h                        |   35 +++++++------
 102 files changed, 670 insertions(+), 560 deletions(-)

diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index 8be7b9b..8d0b6f0 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -38,6 +38,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-sg.h>
 
 /* read 512 bytes from endpoint 0x86 -> get header + blobs */
@@ -163,7 +164,7 @@ struct sur40_state {
 };
 
 struct sur40_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
@@ -420,7 +421,7 @@ static void sur40_process_video(struct sur40_state *sur40)
 
 	dev_dbg(sur40->dev, "header acquired\n");
 
-	sgt = vb2_dma_sg_plane_desc(&new_buf->vb, 0);
+	sgt = vb2_dma_sg_plane_desc(&new_buf->vb.vb2_buf, 0);
 
 	result = usb_sg_init(&sgr, sur40->usbdev,
 		usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT), 0,
@@ -443,15 +444,15 @@ static void sur40_process_video(struct sur40_state *sur40)
 		goto err_poll;
 
 	/* mark as finished */
-	v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp);
-	new_buf->vb.v4l2_buf.sequence = sur40->sequence++;
-	new_buf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
-	vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE);
+	v4l2_get_timestamp(&new_buf->vb.timestamp);
+	new_buf->vb.sequence = sur40->sequence++;
+	new_buf->vb.field = V4L2_FIELD_NONE;
+	vb2_buffer_done(&new_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	dev_dbg(sur40->dev, "buffer marked done\n");
 	return;
 
 err_poll:
-	vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_ERROR);
+	vb2_buffer_done(&new_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 }
 
 /* Initialize input device parameters. */
@@ -700,7 +701,7 @@ static void return_all_buffers(struct sur40_state *sur40,
 
 	spin_lock(&sur40->qlock);
 	list_for_each_entry_safe(buf, node, &sur40->buf_list, list) {
-		vb2_buffer_done(&buf->vb, state);
+		vb2_buffer_done(&buf->vb.vb2_buf, state);
 		list_del(&buf->list);
 	}
 	spin_unlock(&sur40->qlock);
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index d5b994f..3501215 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -107,7 +107,7 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 
 /* intermediate buffers with raw data from the USB device */
 struct rtl2832_sdr_frame_buf {
-	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+	struct vb2_v4l2_buffer vb;   /* common v4l buffer stuff -- must be first */
 	struct list_head list;
 };
 
@@ -307,10 +307,10 @@ static void rtl2832_sdr_urb_complete(struct urb *urb)
 		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
 		len = rtl2832_sdr_convert_stream(dev, ptr, urb->transfer_buffer,
 				urb->actual_length);
-		vb2_set_plane_payload(&fbuf->vb, 0, len);
-		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
-		fbuf->vb.v4l2_buf.sequence = dev->sequence++;
-		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+		vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len);
+		v4l2_get_timestamp(&fbuf->vb.timestamp);
+		fbuf->vb.sequence = dev->sequence++;
+		vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	}
 skip:
 	usb_submit_urb(urb, GFP_ATOMIC);
@@ -464,7 +464,7 @@ static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev)
 		buf = list_entry(dev->queued_bufs.next,
 				struct rtl2832_sdr_frame_buf, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
 }
@@ -525,7 +525,7 @@ static void rtl2832_sdr_buf_queue(struct vb2_buffer *vb)
 
 	/* Check the device has not disconnected between prep and queuing */
 	if (!dev->udev) {
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		return;
 	}
 
diff --git a/drivers/media/pci/cobalt/cobalt-driver.h b/drivers/media/pci/cobalt/cobalt-driver.h
index c206df9..b184be0 100644
--- a/drivers/media/pci/cobalt/cobalt-driver.h
+++ b/drivers/media/pci/cobalt/cobalt-driver.h
@@ -206,7 +206,7 @@ struct sg_dma_desc_info {
 #define COBALT_STREAM_FL_ADV_IRQ		1
 
 struct cobalt_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
diff --git a/drivers/media/pci/cobalt/cobalt-irq.c b/drivers/media/pci/cobalt/cobalt-irq.c
index dd4bff9..cecadd0 100644
--- a/drivers/media/pci/cobalt/cobalt-irq.c
+++ b/drivers/media/pci/cobalt/cobalt-irq.c
@@ -134,12 +134,12 @@ done:
 		skip = true;
 		s->skip_first_frames--;
 	}
-	v4l2_get_timestamp(&cb->vb.v4l2_buf.timestamp);
+	v4l2_get_timestamp(&cb->vb.timestamp);
 	/* TODO: the sequence number should be read from the FPGA so we
 	   also know about dropped frames. */
-	cb->vb.v4l2_buf.sequence = s->sequence++;
-	vb2_buffer_done(&cb->vb, (skip || s->unstable_frame) ?
-			VB2_BUF_STATE_QUEUED : VB2_BUF_STATE_DONE);
+	cb->vb.sequence = s->sequence++;
+	vb2_buffer_done(&cb->vb.vb2_buf,
+			(skip || s->unstable_frame) ? VB2_BUF_STATE_QUEUED : VB2_BUF_STATE_DONE);
 }
 
 irqreturn_t cobalt_irq_handler(int irq, void *dev_id)
diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c
index 9756fd3..e72480a 100644
--- a/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -128,7 +128,7 @@ static void chain_all_buffers(struct cobalt_stream *s)
 
 	list_for_each(p, &s->bufs) {
 		cb = list_entry(p, struct cobalt_buffer, list);
-		desc[i] = &s->dma_desc_info[cb->vb.v4l2_buf.index];
+		desc[i] = &s->dma_desc_info[cb->vb.vb2_buf.index];
 		if (i > 0)
 			descriptor_list_chain(desc[i-1], desc[i]);
 		i++;
@@ -284,7 +284,7 @@ static void cobalt_dma_start_streaming(struct cobalt_stream *s)
 			  &vo->control);
 	}
 	cb = list_first_entry(&s->bufs, struct cobalt_buffer, list);
-	omni_sg_dma_start(s, &s->dma_desc_info[cb->vb.v4l2_buf.index]);
+	omni_sg_dma_start(s, &s->dma_desc_info[cb->vb.vb2_buf.index]);
 	spin_unlock_irqrestore(&s->irqlock, flags);
 }
 
@@ -381,7 +381,7 @@ static void cobalt_dma_stop_streaming(struct cobalt_stream *s)
 	spin_lock_irqsave(&s->irqlock, flags);
 	list_for_each(p, &s->bufs) {
 		cb = list_entry(p, struct cobalt_buffer, list);
-		desc = &s->dma_desc_info[cb->vb.v4l2_buf.index];
+		desc = &s->dma_desc_info[cb->vb.vb2_buf.index];
 		/* Stop DMA after this descriptor chain */
 		descriptor_list_end_of_chain(desc);
 	}
@@ -416,7 +416,7 @@ static void cobalt_stop_streaming(struct vb2_queue *q)
 	list_for_each_safe(p, safe, &s->bufs) {
 		cb = list_entry(p, struct cobalt_buffer, list);
 		list_del(&cb->list);
-		vb2_buffer_done(&cb->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&cb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&s->irqlock, flags);
 
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index 63c0ee5..316a322 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1155,17 +1155,19 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx23885_buffer *buf =
-		container_of(vb, struct cx23885_buffer, vb);
+		container_of(vbuf, struct cx23885_buffer, vb);
 
 	return cx23885_buf_prepare(buf, &dev->ts1);
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx23885_buffer *buf = container_of(vb,
+	struct cx23885_buffer *buf = container_of(vbuf,
 		struct cx23885_buffer, vb);
 
 	cx23885_free_buffer(dev, buf);
@@ -1173,8 +1175,9 @@ static void buffer_finish(struct vb2_buffer *vb)
 
 static void buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx23885_buffer   *buf = container_of(vb,
+	struct cx23885_buffer   *buf = container_of(vbuf,
 		struct cx23885_buffer, vb);
 
 	cx23885_buf_queue(&dev->ts1, buf);
@@ -1201,7 +1204,7 @@ static int cx23885_start_streaming(struct vb2_queue *q, unsigned int count)
 			struct cx23885_buffer, queue);
 
 		list_del(&buf->queue);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 	return ret;
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index 7aee76a..bc1c960 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -427,12 +427,13 @@ static void cx23885_wakeup(struct cx23885_tsport *port,
 	buf = list_entry(q->active.next,
 			 struct cx23885_buffer, queue);
 
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-	buf->vb.v4l2_buf.sequence = q->count++;
-	dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.v4l2_buf.index,
+	v4l2_get_timestamp(&buf->vb.timestamp);
+	buf->vb.sequence = q->count++;
+	dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf,
+		buf->vb.vb2_buf.index,
 		count, q->count);
 	list_del(&buf->queue);
-	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 int cx23885_sram_channel_setup(struct cx23885_dev *dev,
@@ -1453,12 +1454,12 @@ int cx23885_buf_prepare(struct cx23885_buffer *buf, struct cx23885_tsport *port)
 {
 	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);
+	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
 
 	dprintk(1, "%s: %p\n", __func__, buf);
-	if (vb2_plane_size(&buf->vb, 0) < size)
+	if (vb2_plane_size(&buf->vb.vb2_buf, 0) < size)
 		return -EINVAL;
-	vb2_set_plane_payload(&buf->vb, 0, size);
+	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
 
 	cx23885_risc_databuffer(dev->pci, &buf->risc,
 				sgt->sgl,
@@ -1503,7 +1504,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
 	if (list_empty(&cx88q->active)) {
 		list_add_tail(&buf->queue, &cx88q->active);
 		dprintk(1, "[%p/%d] %s - first active\n",
-			buf, buf->vb.v4l2_buf.index, __func__);
+			buf, buf->vb.vb2_buf.index, __func__);
 	} else {
 		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
 		prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
@@ -1511,7 +1512,7 @@ void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
 		list_add_tail(&buf->queue, &cx88q->active);
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 		dprintk(1, "[%p/%d] %s - append to active\n",
-			 buf, buf->vb.v4l2_buf.index, __func__);
+			 buf, buf->vb.vb2_buf.index, __func__);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
@@ -1530,9 +1531,10 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason)
 		buf = list_entry(q->active.next, struct cx23885_buffer,
 				 queue);
 		list_del(&buf->queue);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		dprintk(1, "[%p/%d] %s - dma=0x%08lx\n",
-			buf, buf->vb.v4l2_buf.index, reason, (unsigned long)buf->risc.dma);
+			buf, buf->vb.vb2_buf.index, reason,
+			(unsigned long)buf->risc.dma);
 	}
 	spin_unlock_irqrestore(&port->slock, flags);
 }
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 6e8c24c..09ad512 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -110,18 +110,20 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_tsport *port = vb->vb2_queue->drv_priv;
 	struct cx23885_buffer *buf =
-		container_of(vb, struct cx23885_buffer, vb);
+		container_of(vbuf, struct cx23885_buffer, vb);
 
 	return cx23885_buf_prepare(buf, port);
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_tsport *port = vb->vb2_queue->drv_priv;
 	struct cx23885_dev *dev = port->dev;
-	struct cx23885_buffer *buf = container_of(vb,
+	struct cx23885_buffer *buf = container_of(vbuf,
 		struct cx23885_buffer, vb);
 
 	cx23885_free_buffer(dev, buf);
@@ -129,8 +131,9 @@ static void buffer_finish(struct vb2_buffer *vb)
 
 static void buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_tsport *port = vb->vb2_queue->drv_priv;
-	struct cx23885_buffer   *buf = container_of(vb,
+	struct cx23885_buffer   *buf = container_of(vbuf,
 		struct cx23885_buffer, vb);
 
 	cx23885_buf_queue(port, buf);
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
index d362d38..6c9bb03 100644
--- a/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -138,8 +138,9 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx23885_buffer *buf = container_of(vb,
+	struct cx23885_buffer *buf = container_of(vbuf,
 		struct cx23885_buffer, vb);
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 	unsigned lines = VBI_PAL_LINE_COUNT;
@@ -161,7 +162,8 @@ static int buffer_prepare(struct vb2_buffer *vb)
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
-	struct cx23885_buffer *buf = container_of(vb,
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct cx23885_buffer *buf = container_of(vbuf,
 		struct cx23885_buffer, vb);
 
 	cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
@@ -190,8 +192,10 @@ static void buffer_finish(struct vb2_buffer *vb)
  */
 static void buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx23885_buffer *buf = container_of(vb, struct cx23885_buffer, vb);
+	struct cx23885_buffer *buf = container_of(vbuf,
+			struct cx23885_buffer, vb);
 	struct cx23885_buffer *prev;
 	struct cx23885_dmaqueue *q = &dev->vbiq;
 	unsigned long flags;
@@ -206,7 +210,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 		list_add_tail(&buf->queue, &q->active);
 		spin_unlock_irqrestore(&dev->slock, flags);
 		dprintk(2, "[%p/%d] vbi_queue - first active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.vb2_buf.index);
 
 	} else {
 		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
@@ -217,7 +221,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 		spin_unlock_irqrestore(&dev->slock, flags);
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 		dprintk(2, "[%p/%d] buffer_queue - append to active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.vb2_buf.index);
 	}
 }
 
@@ -245,7 +249,7 @@ static void cx23885_stop_streaming(struct vb2_queue *q)
 			struct cx23885_buffer, queue);
 
 		list_del(&buf->queue);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index ec76470..b6a193d 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -104,12 +104,12 @@ void cx23885_video_wakeup(struct cx23885_dev *dev,
 	buf = list_entry(q->active.next,
 			struct cx23885_buffer, queue);
 
-	buf->vb.v4l2_buf.sequence = q->count++;
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-	dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.v4l2_buf.index,
-			count, q->count);
+	buf->vb.sequence = q->count++;
+	v4l2_get_timestamp(&buf->vb.timestamp);
+	dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf,
+			buf->vb.vb2_buf.index, count, q->count);
 	list_del(&buf->queue);
-	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
@@ -329,9 +329,10 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx23885_buffer *buf =
-		container_of(vb, struct cx23885_buffer, vb);
+		container_of(vbuf, struct cx23885_buffer, vb);
 	u32 line0_offset, line1_offset;
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 	int field_tff;
@@ -401,7 +402,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
 		BUG();
 	}
 	dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
-		buf, buf->vb.v4l2_buf.index,
+		buf, buf->vb.vb2_buf.index,
 		dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
 		(unsigned long)buf->risc.dma);
 	return 0;
@@ -409,7 +410,8 @@ static int buffer_prepare(struct vb2_buffer *vb)
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
-	struct cx23885_buffer *buf = container_of(vb,
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct cx23885_buffer *buf = container_of(vbuf,
 		struct cx23885_buffer, vb);
 
 	cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
@@ -438,8 +440,9 @@ static void buffer_finish(struct vb2_buffer *vb)
  */
 static void buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx23885_buffer   *buf = container_of(vb,
+	struct cx23885_buffer   *buf = container_of(vbuf,
 		struct cx23885_buffer, vb);
 	struct cx23885_buffer   *prev;
 	struct cx23885_dmaqueue *q    = &dev->vidq;
@@ -455,7 +458,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 	if (list_empty(&q->active)) {
 		list_add_tail(&buf->queue, &q->active);
 		dprintk(2, "[%p/%d] buffer_queue - first active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.vb2_buf.index);
 	} else {
 		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
 		prev = list_entry(q->active.prev, struct cx23885_buffer,
@@ -463,7 +466,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 		list_add_tail(&buf->queue, &q->active);
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 		dprintk(2, "[%p/%d] buffer_queue - append to active\n",
-				buf, buf->vb.v4l2_buf.index);
+				buf, buf->vb.vb2_buf.index);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
@@ -492,7 +495,7 @@ static void cx23885_stop_streaming(struct vb2_queue *q)
 			struct cx23885_buffer, queue);
 
 		list_del(&buf->queue);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index 027ead4..c5ba083 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -170,7 +170,7 @@ struct cx23885_riscmem {
 /* buffer for one video frame */
 struct cx23885_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head queue;
 
 	/* cx23885 specific */
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index 7bc495e..f1deb8f 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -130,10 +130,10 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
 			buf = list_entry(dmaq->active.next,
 					 struct cx25821_buffer, queue);
 
-			v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-			buf->vb.v4l2_buf.sequence = dmaq->count++;
+			v4l2_get_timestamp(&buf->vb.timestamp);
+			buf->vb.sequence = dmaq->count++;
 			list_del(&buf->queue);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 		}
 		spin_unlock(&dev->slock);
 		handled++;
@@ -159,10 +159,11 @@ static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fm
 
 static int cx25821_buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
 	struct cx25821_dev *dev = chan->dev;
 	struct cx25821_buffer *buf =
-		container_of(vb, struct cx25821_buffer, vb);
+		container_of(vbuf, struct cx25821_buffer, vb);
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 	u32 line0_offset;
 	int bpl_local = LINE_SIZE_D1;
@@ -176,7 +177,7 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb)
 	if (vb2_plane_size(vb, 0) < chan->height * buf->bpl)
 		return -EINVAL;
 	vb2_set_plane_payload(vb, 0, chan->height * buf->bpl);
-	buf->vb.v4l2_buf.field = chan->field;
+	buf->vb.field = chan->field;
 
 	if (chan->pixel_formats == PIXEL_FRMT_411) {
 		bpl_local = buf->bpl;
@@ -231,7 +232,7 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb)
 	}
 
 	dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
-		buf, buf->vb.v4l2_buf.index, chan->width, chan->height,
+		buf, buf->vb.vb2_buf.index, chan->width, chan->height,
 		chan->fmt->depth, chan->fmt->name,
 		(unsigned long)buf->risc.dma);
 
@@ -240,8 +241,9 @@ static int cx25821_buffer_prepare(struct vb2_buffer *vb)
 
 static void cx25821_buffer_finish(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx25821_buffer *buf =
-		container_of(vb, struct cx25821_buffer, vb);
+		container_of(vbuf, struct cx25821_buffer, vb);
 	struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
 	struct cx25821_dev *dev = chan->dev;
 
@@ -250,8 +252,9 @@ static void cx25821_buffer_finish(struct vb2_buffer *vb)
 
 static void cx25821_buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx25821_buffer *buf =
-		container_of(vb, struct cx25821_buffer, vb);
+		container_of(vbuf, struct cx25821_buffer, vb);
 	struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
 	struct cx25821_dev *dev = chan->dev;
 	struct cx25821_buffer *prev;
@@ -300,7 +303,7 @@ static void cx25821_stop_streaming(struct vb2_queue *q)
 			struct cx25821_buffer, queue);
 
 		list_del(&buf->queue);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h
index d81a08a..a513b68 100644
--- a/drivers/media/pci/cx25821/cx25821.h
+++ b/drivers/media/pci/cx25821/cx25821.h
@@ -34,6 +34,7 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-dma-sg.h>
 
 #include "cx25821-reg.h"
@@ -127,7 +128,7 @@ struct cx25821_riscmem {
 /* buffer for one video frame */
 struct cx25821_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head queue;
 
 	/* cx25821 specific */
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 24216ef..49d0b7c 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -653,16 +653,18 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
 
 	return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
 	struct cx88_riscmem *risc = &buf->risc;
 
 	if (risc->cpu)
@@ -672,8 +674,9 @@ static void buffer_finish(struct vb2_buffer *vb)
 
 static void buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer    *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer    *buf = container_of(vbuf, struct cx88_buffer, vb);
 
 	cx8802_buf_queue(dev, buf);
 }
@@ -721,7 +724,7 @@ fail:
 			struct cx88_buffer, list);
 
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 	return err;
@@ -749,7 +752,7 @@ static void stop_streaming(struct vb2_queue *q)
 			struct cx88_buffer, list);
 
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index aab7cf4..9a43c78 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -518,11 +518,11 @@ void cx88_wakeup(struct cx88_core *core,
 
 	buf = list_entry(q->active.next,
 			 struct cx88_buffer, list);
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-	buf->vb.v4l2_buf.field = core->field;
-	buf->vb.v4l2_buf.sequence = q->count++;
+	v4l2_get_timestamp(&buf->vb.timestamp);
+	buf->vb.field = core->field;
+	buf->vb.sequence = q->count++;
 	list_del(&buf->list);
-	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 void cx88_shutdown(struct cx88_core *core)
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index 9dfa5ee..f0923fb 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -99,16 +99,18 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
 
 	return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
 	struct cx88_riscmem *risc = &buf->risc;
 
 	if (risc->cpu)
@@ -118,8 +120,9 @@ static void buffer_finish(struct vb2_buffer *vb)
 
 static void buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer    *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer    *buf = container_of(vbuf, struct cx88_buffer, vb);
 
 	cx8802_buf_queue(dev, buf);
 }
@@ -149,7 +152,7 @@ static void stop_streaming(struct vb2_queue *q)
 			struct cx88_buffer, list);
 
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 34f5057..9961b22 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -214,7 +214,7 @@ static int cx8802_restart_queue(struct cx8802_dev    *dev,
 
 	buf = list_entry(q->active.next, struct cx88_buffer, list);
 	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
-		buf, buf->vb.v4l2_buf.index);
+		buf, buf->vb.vb2_buf.index);
 	cx8802_start_dma(dev, q, buf);
 	return 0;
 }
@@ -225,13 +225,13 @@ int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
 			struct cx88_buffer *buf)
 {
 	int size = dev->ts_packet_size * dev->ts_packet_count;
-	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
+	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
 	struct cx88_riscmem *risc = &buf->risc;
 	int rc;
 
-	if (vb2_plane_size(&buf->vb, 0) < size)
+	if (vb2_plane_size(&buf->vb.vb2_buf, 0) < size)
 		return -EINVAL;
-	vb2_set_plane_payload(&buf->vb, 0, size);
+	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
 
 	rc = cx88_risc_databuffer(dev->pci, risc, sgt->sgl,
 			     dev->ts_packet_size, dev->ts_packet_count, 0);
@@ -259,7 +259,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
 		dprintk( 1, "queue is empty - first active\n" );
 		list_add_tail(&buf->list, &cx88q->active);
 		dprintk(1,"[%p/%d] %s - first active\n",
-			buf, buf->vb.v4l2_buf.index, __func__);
+			buf, buf->vb.vb2_buf.index, __func__);
 
 	} else {
 		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
@@ -268,7 +268,7 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
 		list_add_tail(&buf->list, &cx88q->active);
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 		dprintk( 1, "[%p/%d] %s - append to active\n",
-			buf, buf->vb.v4l2_buf.index, __func__);
+			buf, buf->vb.vb2_buf.index, __func__);
 	}
 }
 
@@ -284,7 +284,7 @@ static void do_cancel_buffers(struct cx8802_dev *dev)
 	while (!list_empty(&q->active)) {
 		buf = list_entry(q->active.next, struct cx88_buffer, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock,flags);
 }
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 7510e80..1d65543 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -100,7 +100,7 @@ int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
 
 	buf = list_entry(q->active.next, struct cx88_buffer, list);
 	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
-		buf, buf->vb.v4l2_buf.index);
+		buf, buf->vb.vb2_buf.index);
 	cx8800_start_vbi_dma(dev, q, buf);
 	return 0;
 }
@@ -125,8 +125,9 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 	unsigned int lines;
 	unsigned int size;
@@ -149,8 +150,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
 	struct cx88_riscmem *risc = &buf->risc;
 
 	if (risc->cpu)
@@ -160,8 +162,9 @@ static void buffer_finish(struct vb2_buffer *vb)
 
 static void buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer    *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer    *buf = container_of(vbuf, struct cx88_buffer, vb);
 	struct cx88_buffer    *prev;
 	struct cx88_dmaqueue  *q    = &dev->vbiq;
 
@@ -174,7 +177,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 		list_add_tail(&buf->list, &q->active);
 		cx8800_start_vbi_dma(dev, q, buf);
 		dprintk(2,"[%p/%d] vbi_queue - first active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.vb2_buf.index);
 
 	} else {
 		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
@@ -182,7 +185,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 		list_add_tail(&buf->list, &q->active);
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 		dprintk(2,"[%p/%d] buffer_queue - append to active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.vb2_buf.index);
 	}
 }
 
@@ -213,7 +216,7 @@ static void stop_streaming(struct vb2_queue *q)
 			struct cx88_buffer, list);
 
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 400e5ca..c6a337a 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -420,7 +420,7 @@ static int restart_video_queue(struct cx8800_dev    *dev,
 	if (!list_empty(&q->active)) {
 		buf = list_entry(q->active.next, struct cx88_buffer, list);
 		dprintk(2,"restart_queue [%p/%d]: restart dma\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.vb2_buf.index);
 		start_video_dma(dev, q, buf);
 	}
 	return 0;
@@ -444,9 +444,10 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx88_core *core = dev->core;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
 
 	buf->bpl = core->width * dev->fmt->depth >> 3;
@@ -489,7 +490,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
 		break;
 	}
 	dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
-		buf, buf->vb.v4l2_buf.index,
+		buf, buf->vb.vb2_buf.index,
 		core->width, core->height, dev->fmt->depth, dev->fmt->name,
 		(unsigned long)buf->risc.dma);
 	return 0;
@@ -497,8 +498,9 @@ static int buffer_prepare(struct vb2_buffer *vb)
 
 static void buffer_finish(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb);
 	struct cx88_riscmem *risc = &buf->risc;
 
 	if (risc->cpu)
@@ -508,8 +510,9 @@ static void buffer_finish(struct vb2_buffer *vb)
 
 static void buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
-	struct cx88_buffer    *buf = container_of(vb, struct cx88_buffer, vb);
+	struct cx88_buffer    *buf = container_of(vbuf, struct cx88_buffer, vb);
 	struct cx88_buffer    *prev;
 	struct cx88_core      *core = dev->core;
 	struct cx88_dmaqueue  *q    = &dev->vidq;
@@ -522,7 +525,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 	if (list_empty(&q->active)) {
 		list_add_tail(&buf->list, &q->active);
 		dprintk(2,"[%p/%d] buffer_queue - first active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.vb2_buf.index);
 
 	} else {
 		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
@@ -530,7 +533,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 		list_add_tail(&buf->list, &q->active);
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 		dprintk(2, "[%p/%d] buffer_queue - append to active\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.vb2_buf.index);
 	}
 }
 
@@ -560,7 +563,7 @@ static void stop_streaming(struct vb2_queue *q)
 			struct cx88_buffer, list);
 
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index 785fe2e..2996eb3 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -321,7 +321,7 @@ struct cx88_riscmem {
 /* buffer for one video frame */
 struct cx88_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head       list;
 
 	/* cx88 specific */
diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c
index 8df6345..f27a858 100644
--- a/drivers/media/pci/dt3155/dt3155.c
+++ b/drivers/media/pci/dt3155/dt3155.c
@@ -160,7 +160,7 @@ static int dt3155_buf_prepare(struct vb2_buffer *vb)
 static int dt3155_start_streaming(struct vb2_queue *q, unsigned count)
 {
 	struct dt3155_priv *pd = vb2_get_drv_priv(q);
-	struct vb2_buffer *vb = pd->curr_buf;
+	struct vb2_buffer *vb = &pd->curr_buf->vb2_buf;
 	dma_addr_t dma_addr;
 
 	pd->sequence = 0;
@@ -208,7 +208,7 @@ static void dt3155_stop_streaming(struct vb2_queue *q)
 
 	spin_lock_irq(&pd->lock);
 	if (pd->curr_buf) {
-		vb2_buffer_done(pd->curr_buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&pd->curr_buf->vb2_buf, VB2_BUF_STATE_ERROR);
 		pd->curr_buf = NULL;
 	}
 
@@ -222,6 +222,7 @@ static void dt3155_stop_streaming(struct vb2_queue *q)
 
 static void dt3155_buf_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
 
 	/*  pd->vidq.streaming = 1 when dt3155_buf_queue() is invoked  */
@@ -229,7 +230,7 @@ static void dt3155_buf_queue(struct vb2_buffer *vb)
 	if (pd->curr_buf)
 		list_add_tail(&vb->done_entry, &pd->dmaq);
 	else
-		pd->curr_buf = vb;
+		pd->curr_buf = vbuf;
 	spin_unlock_irq(&pd->lock);
 }
 
@@ -269,14 +270,14 @@ static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id)
 
 	spin_lock(&ipd->lock);
 	if (ipd->curr_buf && !list_empty(&ipd->dmaq)) {
-		v4l2_get_timestamp(&ipd->curr_buf->v4l2_buf.timestamp);
-		ipd->curr_buf->v4l2_buf.sequence = ipd->sequence++;
-		ipd->curr_buf->v4l2_buf.field = V4L2_FIELD_NONE;
-		vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE);
+		v4l2_get_timestamp(&ipd->curr_buf->timestamp);
+		ipd->curr_buf->sequence = ipd->sequence++;
+		ipd->curr_buf->field = V4L2_FIELD_NONE;
+		vb2_buffer_done(&ipd->curr_buf->vb2_buf, VB2_BUF_STATE_DONE);
 
 		ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
 		list_del(&ivb->done_entry);
-		ipd->curr_buf = ivb;
+		ipd->curr_buf = to_vb2_v4l2_buffer(ivb);
 		dma_addr = vb2_dma_contig_plane_dma_addr(ivb, 0);
 		iowrite32(dma_addr, ipd->regs + EVEN_DMA_START);
 		iowrite32(dma_addr + ipd->width, ipd->regs + ODD_DMA_START);
diff --git a/drivers/media/pci/dt3155/dt3155.h b/drivers/media/pci/dt3155/dt3155.h
index 4e1f4d5..b3531e0 100644
--- a/drivers/media/pci/dt3155/dt3155.h
+++ b/drivers/media/pci/dt3155/dt3155.h
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-dev.h>
+#include <media/videobuf2-v4l2.h>
 
 #define DT3155_NAME "dt3155"
 #define DT3155_VER_MAJ 2
@@ -181,7 +182,7 @@ struct dt3155_priv {
 	struct pci_dev *pdev;
 	struct vb2_queue vidq;
 	struct vb2_alloc_ctx *alloc_ctx;
-	struct vb2_buffer *curr_buf;
+	struct vb2_v4l2_buffer *curr_buf;
 	struct mutex mux;
 	struct list_head dmaq;
 	spinlock_t lock;
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
index 6d8bf627..b012aa65 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/list.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 
 #include "netup_unidvb.h"
@@ -110,7 +111,7 @@ struct netup_dma_regs {
 } __packed __aligned(1);
 
 struct netup_unidvb_buffer {
-	struct vb2_buffer	vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head	list;
 	u32			size;
 };
@@ -300,7 +301,8 @@ static int netup_unidvb_queue_setup(struct vb2_queue *vq,
 static int netup_unidvb_buf_prepare(struct vb2_buffer *vb)
 {
 	struct netup_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
-	struct netup_unidvb_buffer *buf = container_of(vb,
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct netup_unidvb_buffer *buf = container_of(vbuf,
 				struct netup_unidvb_buffer, vb);
 
 	dev_dbg(&dma->ndev->pci_dev->dev, "%s(): buf 0x%p\n", __func__, buf);
@@ -312,7 +314,8 @@ static void netup_unidvb_buf_queue(struct vb2_buffer *vb)
 {
 	unsigned long flags;
 	struct netup_dma *dma = vb2_get_drv_priv(vb->vb2_queue);
-	struct netup_unidvb_buffer *buf = container_of(vb,
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct netup_unidvb_buffer *buf = container_of(vbuf,
 				struct netup_unidvb_buffer, vb);
 
 	dev_dbg(&dma->ndev->pci_dev->dev, "%s(): %p\n", __func__, buf);
@@ -509,7 +512,7 @@ static int netup_unidvb_ring_copy(struct netup_dma *dma,
 {
 	u32 copy_bytes, ring_bytes;
 	u32 buff_bytes = NETUP_DMA_PACKETS_COUNT * 188 - buf->size;
-	u8 *p = vb2_plane_vaddr(&buf->vb, 0);
+	u8 *p = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 	struct netup_unidvb_dev *ndev = dma->ndev;
 
 	if (p == NULL) {
@@ -579,9 +582,9 @@ static void netup_unidvb_dma_worker(struct work_struct *work)
 			dev_dbg(&ndev->pci_dev->dev,
 				"%s(): buffer %p done, size %d\n",
 				__func__, buf, buf->size);
-			v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-			vb2_set_plane_payload(&buf->vb, 0, buf->size);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+			v4l2_get_timestamp(&buf->vb.timestamp);
+			vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->size);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 		}
 	}
 work_done:
@@ -599,7 +602,7 @@ static void netup_unidvb_queue_cleanup(struct netup_dma *dma)
 		buf = list_first_entry(&dma->free_buffers,
 			struct netup_unidvb_buffer, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dma->lock, flags);
 }
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index 72d7f99..87f39f9 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -216,13 +216,14 @@ int saa7134_buffer_count(unsigned int size, unsigned int count)
 
 int saa7134_buffer_startpage(struct saa7134_buf *buf)
 {
-	return saa7134_buffer_pages(vb2_plane_size(&buf->vb2, 0)) * buf->vb2.v4l2_buf.index;
+	return saa7134_buffer_pages(vb2_plane_size(&buf->vb2.vb2_buf, 0))
+			* buf->vb2.vb2_buf.index;
 }
 
 unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
 {
 	unsigned long base;
-	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+	struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2.vb2_buf, 0);
 
 	base  = saa7134_buffer_startpage(buf) * 4096;
 	base += dma->sgl[0].offset;
@@ -308,9 +309,9 @@ void saa7134_buffer_finish(struct saa7134_dev *dev,
 	core_dbg("buffer_finish %p\n", q->curr);
 
 	/* finish current buffer */
-	v4l2_get_timestamp(&q->curr->vb2.v4l2_buf.timestamp);
-	q->curr->vb2.v4l2_buf.sequence = q->seq_nr++;
-	vb2_buffer_done(&q->curr->vb2, state);
+	v4l2_get_timestamp(&q->curr->vb2.timestamp);
+	q->curr->vb2.sequence = q->seq_nr++;
+	vb2_buffer_done(&q->curr->vb2.vb2_buf, state);
 	q->curr = NULL;
 }
 
@@ -375,7 +376,8 @@ void saa7134_stop_streaming(struct saa7134_dev *dev, struct saa7134_dmaqueue *q)
 	if (!list_empty(&q->queue)) {
 		list_for_each_safe(pos, n, &q->queue) {
 			 tmp = list_entry(pos, struct saa7134_buf, entry);
-			 vb2_buffer_done(&tmp->vb2, VB2_BUF_STATE_ERROR);
+			 vb2_buffer_done(&tmp->vb2.vb2_buf,
+					 VB2_BUF_STATE_ERROR);
 			 list_del(pos);
 			 tmp = NULL;
 		}
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index 4b202fa..b0ef37d 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -79,8 +79,9 @@ static int buffer_activate(struct saa7134_dev *dev,
 
 int saa7134_ts_buffer_init(struct vb2_buffer *vb2)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
 	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
-	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
 
 	dmaq->curr = NULL;
 	buf->activate = buffer_activate;
@@ -91,9 +92,10 @@ EXPORT_SYMBOL_GPL(saa7134_ts_buffer_init);
 
 int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_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 saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
 	struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
 	unsigned int lines, llength, size;
 
@@ -107,7 +109,7 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
 		return -EINVAL;
 
 	vb2_set_plane_payload(vb2, 0, size);
-	vb2->v4l2_buf.field = dev->field;
+	vbuf->field = dev->field;
 
 	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
 				    saa7134_buffer_startpage(buf));
@@ -148,10 +150,12 @@ int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 		list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
 			list_del(&buf->entry);
-			vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb2.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 		}
 		if (dmaq->curr) {
-			vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&dmaq->curr->vb2.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 			dmaq->curr = NULL;
 		}
 		return -EBUSY;
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index 4d36586..fb1605e 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -83,7 +83,7 @@ static int buffer_activate(struct saa7134_dev *dev,
 			   struct saa7134_buf *buf,
 			   struct saa7134_buf *next)
 {
-	struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
+	struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv;
 	unsigned long control, base;
 
 	vbi_dbg("buffer_activate [%p]\n", buf);
@@ -119,8 +119,9 @@ static int buffer_prepare(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);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
+	struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
 	unsigned int size;
 
 	if (dma->sgl->offset) {
@@ -161,7 +162,8 @@ static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
 static int buffer_init(struct vb2_buffer *vb2)
 {
 	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
-	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
 
 	dmaq->curr = NULL;
 	buf->activate = buffer_activate;
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 035039c..602d53d 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -791,7 +791,7 @@ static int buffer_activate(struct saa7134_dev *dev,
 			   struct saa7134_buf *buf,
 			   struct saa7134_buf *next)
 {
-	struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_queue->drv_priv;
+	struct saa7134_dmaqueue *dmaq = buf->vb2.vb2_buf.vb2_queue->drv_priv;
 	unsigned long base,control,bpl;
 	unsigned long bpl_uv,lines_uv,base2,base3,tmp; /* planar */
 
@@ -872,7 +872,8 @@ static int buffer_activate(struct saa7134_dev *dev,
 static int buffer_init(struct vb2_buffer *vb2)
 {
 	struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
-	struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
 
 	dmaq->curr = NULL;
 	buf->activate = buffer_activate;
@@ -883,8 +884,9 @@ static int buffer_prepare(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);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb2);
+	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
+	struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
 	unsigned int size;
 
 	if (dma->sgl->offset) {
@@ -896,7 +898,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
 		return -EINVAL;
 
 	vb2_set_plane_payload(vb2, 0, size);
-	vb2->v4l2_buf.field = dev->field;
+	vbuf->field = dev->field;
 
 	return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
 				    saa7134_buffer_startpage(buf));
@@ -932,7 +934,8 @@ void saa7134_vb2_buffer_queue(struct vb2_buffer *vb)
 {
 	struct saa7134_dmaqueue *dmaq = vb->vb2_queue->drv_priv;
 	struct saa7134_dev *dev = dmaq->dev;
-	struct saa7134_buf *buf = container_of(vb, struct saa7134_buf, vb2);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct saa7134_buf *buf = container_of(vbuf, struct saa7134_buf, vb2);
 
 	saa7134_buffer_queue(dev, dmaq, buf);
 }
@@ -953,10 +956,12 @@ int saa7134_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
 
 		list_for_each_entry_safe(buf, tmp, &dmaq->queue, entry) {
 			list_del(&buf->entry);
-			vb2_buffer_done(&buf->vb2, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb2.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 		}
 		if (dmaq->curr) {
-			vb2_buffer_done(&dmaq->curr->vb2, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&dmaq->curr->vb2.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 			dmaq->curr = NULL;
 		}
 		return -EBUSY;
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 6b5f6f4..002ba1d8 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -459,7 +459,7 @@ struct saa7134_thread {
 /* buffer for one video/vbi/ts frame */
 struct saa7134_buf {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer vb2;
+	struct vb2_v4l2_buffer vb2;
 
 	/* saa7134 specific */
 	unsigned int            top_seen;
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 53fff54..fb71f2f 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -734,7 +734,7 @@ static void solo_enc_stop_streaming(struct vb2_queue *q)
 				struct solo_vb2_buf, list);
 
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&solo_enc->av_lock, flags);
 }
diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index 5cc9e9d..4ab6586 100644
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -135,7 +135,7 @@ struct solo_p2m_dev {
 #define OSD_TEXT_MAX		44
 
 struct solo_vb2_buf {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 59b3a36..8fe6ea6 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -88,7 +88,7 @@
 
 
 struct vip_buffer {
-	struct vb2_buffer	vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head	list;
 	dma_addr_t		dma;
 };
@@ -307,7 +307,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
 		return -EINVAL;
 	}
 
-	vb2_set_plane_payload(&vip_buf->vb, 0, size);
+	vb2_set_plane_payload(&vip_buf->vb.vb2_buf, 0, size);
 
 	return 0;
 }
@@ -370,7 +370,7 @@ static void stop_streaming(struct vb2_queue *vq)
 	/* Release all active buffers */
 	spin_lock(&vip->lock);
 	list_for_each_entry_safe(vip_buf, node, &vip->buffer_list, list) {
-		vb2_buffer_done(&vip_buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&vip_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		list_del(&vip_buf->list);
 	}
 	spin_unlock(&vip->lock);
@@ -813,9 +813,9 @@ static irqreturn_t vip_irq(int irq, struct sta2x11_vip *vip)
 		/* Disable acquisition */
 		reg_write(vip, DVP_CTL, reg_read(vip, DVP_CTL) & ~DVP_CTL_ENA);
 		/* Remove the active buffer from the list */
-		v4l2_get_timestamp(&vip->active->vb.v4l2_buf.timestamp);
-		vip->active->vb.v4l2_buf.sequence = vip->sequence++;
-		vb2_buffer_done(&vip->active->vb, VB2_BUF_STATE_DONE);
+		v4l2_get_timestamp(&vip->active->vb.timestamp);
+		vip->active->vb.sequence = vip->sequence++;
+		vb2_buffer_done(&vip->active->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	}
 
 	return IRQ_HANDLED;
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index 8355e55..ae06535 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -528,7 +528,7 @@ static void tw68_stop_streaming(struct vb2_queue *q)
 			container_of(dev->active.next, struct tw68_buf, list);
 
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 }
 
@@ -1012,10 +1012,10 @@ void tw68_irq_video_done(struct tw68_dev *dev, unsigned long status)
 		buf = list_entry(dev->active.next, struct tw68_buf, list);
 		list_del(&buf->list);
 		spin_unlock(&dev->slock);
-		v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-		buf->vb.v4l2_buf.field = dev->field;
-		buf->vb.v4l2_buf.sequence = dev->seqnr++;
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+		v4l2_get_timestamp(&buf->vb.timestamp);
+		buf->vb.field = dev->field;
+		buf->vb.sequence = dev->seqnr++;
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 		status &= ~(TW68_DMAPI);
 		if (0 == status)
 			return;
diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h
index ef51e4d..9e713ef 100644
--- a/drivers/media/pci/tw68/tw68.h
+++ b/drivers/media/pci/tw68/tw68.h
@@ -118,7 +118,7 @@ struct tw68_dev;	/* forward delclaration */
 
 /* buffer for one video/vbi/ts frame */
 struct tw68_buf {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 
 	unsigned int   size;
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index c8447fa..85649ca 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -1280,10 +1280,10 @@ static inline void vpfe_schedule_bottom_field(struct vpfe_device *vpfe)
  */
 static inline void vpfe_process_buffer_complete(struct vpfe_device *vpfe)
 {
-	v4l2_get_timestamp(&vpfe->cur_frm->vb.v4l2_buf.timestamp);
-	vpfe->cur_frm->vb.v4l2_buf.field = vpfe->fmt.fmt.pix.field;
-	vpfe->cur_frm->vb.v4l2_buf.sequence = vpfe->sequence++;
-	vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_DONE);
+	v4l2_get_timestamp(&vpfe->cur_frm->vb.timestamp);
+	vpfe->cur_frm->vb.field = vpfe->fmt.fmt.pix.field;
+	vpfe->cur_frm->vb.sequence = vpfe->sequence++;
+	vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	vpfe->cur_frm = vpfe->next_frm;
 }
 
@@ -2023,7 +2023,7 @@ static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
 err:
 	list_for_each_entry_safe(buf, tmp, &vpfe->dma_queue, list) {
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 	}
 
 	return ret;
@@ -2055,13 +2055,14 @@ static void vpfe_stop_streaming(struct vb2_queue *vq)
 	/* release all active buffers */
 	spin_lock_irqsave(&vpfe->dma_queue_lock, flags);
 	if (vpfe->cur_frm == vpfe->next_frm) {
-		vb2_buffer_done(&vpfe->cur_frm->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 	} else {
 		if (vpfe->cur_frm != NULL)
-			vb2_buffer_done(&vpfe->cur_frm->vb,
+			vb2_buffer_done(&vpfe->cur_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
 		if (vpfe->next_frm != NULL)
-			vb2_buffer_done(&vpfe->next_frm->vb,
+			vb2_buffer_done(&vpfe->next_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
 	}
 
@@ -2069,7 +2070,8 @@ static void vpfe_stop_streaming(struct vb2_queue *vq)
 		vpfe->next_frm = list_entry(vpfe->dma_queue.next,
 						struct vpfe_cap_buffer, list);
 		list_del(&vpfe->next_frm->list);
-		vb2_buffer_done(&vpfe->next_frm->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&vpfe->next_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&vpfe->dma_queue_lock, flags);
 }
diff --git a/drivers/media/platform/am437x/am437x-vpfe.h b/drivers/media/platform/am437x/am437x-vpfe.h
index 5bfb356..587a09f 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.h
+++ b/drivers/media/platform/am437x/am437x-vpfe.h
@@ -104,7 +104,7 @@ struct vpfe_config {
 };
 
 struct vpfe_cap_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index b7e70fb..4bb3208 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -54,7 +54,7 @@ struct bcap_format {
 };
 
 struct bcap_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
@@ -344,7 +344,7 @@ static int bcap_start_streaming(struct vb2_queue *vq, unsigned int count)
 err:
 	list_for_each_entry_safe(buf, tmp, &bcap_dev->dma_queue, list) {
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 	}
 
 	return ret;
@@ -367,13 +367,15 @@ static void bcap_stop_streaming(struct vb2_queue *vq)
 
 	/* release all active buffers */
 	if (bcap_dev->cur_frm)
-		vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&bcap_dev->cur_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 
 	while (!list_empty(&bcap_dev->dma_queue)) {
 		bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
 						struct bcap_buffer, list);
 		list_del_init(&bcap_dev->cur_frm->list);
-		vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&bcap_dev->cur_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 	}
 }
 
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index a5f5481..d7ddc7d 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -243,7 +243,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
 err:
 	list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) {
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 	}
 	spin_unlock_irqrestore(&common->irqlock, flags);
 
@@ -286,13 +286,14 @@ static void vpif_stop_streaming(struct vb2_queue *vq)
 	/* release all active buffers */
 	spin_lock_irqsave(&common->irqlock, flags);
 	if (common->cur_frm == common->next_frm) {
-		vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 	} else {
 		if (common->cur_frm != NULL)
-			vb2_buffer_done(&common->cur_frm->vb,
+			vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
 		if (common->next_frm != NULL)
-			vb2_buffer_done(&common->next_frm->vb,
+			vb2_buffer_done(&common->next_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
 	}
 
@@ -300,7 +301,8 @@ static void vpif_stop_streaming(struct vb2_queue *vq)
 		common->next_frm = list_entry(common->dma_queue.next,
 						struct vpif_cap_buffer, list);
 		list_del(&common->next_frm->list);
-		vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&common->next_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&common->irqlock, flags);
 }
@@ -325,9 +327,8 @@ static struct vb2_ops video_qops = {
  */
 static void vpif_process_buffer_complete(struct common_obj *common)
 {
-	v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp);
-	vb2_buffer_done(&common->cur_frm->vb,
-					    VB2_BUF_STATE_DONE);
+	v4l2_get_timestamp(&common->cur_frm->vb.timestamp);
+	vb2_buffer_done(&common->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	/* Make curFrm pointing to nextFrm */
 	common->cur_frm = common->next_frm;
 }
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h
index 8b8a663..4a76009 100644
--- a/drivers/media/platform/davinci/vpif_capture.h
+++ b/drivers/media/platform/davinci/vpif_capture.h
@@ -52,7 +52,7 @@ struct video_obj {
 };
 
 struct vpif_cap_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 682e5d5..f641bc0 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -77,7 +77,7 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
 	if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
 		return -EINVAL;
 
-	vb->v4l2_buf.field = common->fmt.fmt.pix.field;
+	vb->field = common->fmt.fmt.pix.field;
 
 	if (vb->vb2_queue->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
 		unsigned long addr = vb2_dma_contig_plane_dma_addr(vb, 0);
@@ -229,7 +229,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
 err:
 	list_for_each_entry_safe(buf, tmp, &common->dma_queue, list) {
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 	}
 	spin_unlock_irqrestore(&common->irqlock, flags);
 
@@ -264,13 +264,14 @@ static void vpif_stop_streaming(struct vb2_queue *vq)
 	/* release all active buffers */
 	spin_lock_irqsave(&common->irqlock, flags);
 	if (common->cur_frm == common->next_frm) {
-		vb2_buffer_done(&common->cur_frm->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 	} else {
 		if (common->cur_frm != NULL)
-			vb2_buffer_done(&common->cur_frm->vb,
+			vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
 		if (common->next_frm != NULL)
-			vb2_buffer_done(&common->next_frm->vb,
+			vb2_buffer_done(&common->next_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
 	}
 
@@ -278,7 +279,8 @@ static void vpif_stop_streaming(struct vb2_queue *vq)
 		common->next_frm = list_entry(common->dma_queue.next,
 						struct vpif_disp_buffer, list);
 		list_del(&common->next_frm->list);
-		vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&common->next_frm->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&common->irqlock, flags);
 }
@@ -324,10 +326,10 @@ static void process_interlaced_mode(int fid, struct common_obj *common)
 		/* one frame is displayed If next frame is
 		 *  available, release cur_frm and move on */
 		/* Copy frame display time */
-		v4l2_get_timestamp(&common->cur_frm->vb.v4l2_buf.timestamp);
+		v4l2_get_timestamp(&common->cur_frm->vb.timestamp);
 		/* Change status of the cur_frm */
-		vb2_buffer_done(&common->cur_frm->vb,
-					    VB2_BUF_STATE_DONE);
+		vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
+					VB2_BUF_STATE_DONE);
 		/* Make cur_frm pointing to next_frm */
 		common->cur_frm = common->next_frm;
 
@@ -380,10 +382,9 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
 			if (!channel_first_int[i][channel_id]) {
 				/* Mark status of the cur_frm to
 				 * done and unlock semaphore on it */
-				v4l2_get_timestamp(&common->cur_frm->vb.
-						   v4l2_buf.timestamp);
-				vb2_buffer_done(&common->cur_frm->vb,
-					    VB2_BUF_STATE_DONE);
+				v4l2_get_timestamp(&common->cur_frm->vb.timestamp);
+				vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
+						VB2_BUF_STATE_DONE);
 				/* Make cur_frm pointing to next_frm */
 				common->cur_frm = common->next_frm;
 			}
diff --git a/drivers/media/platform/davinci/vpif_display.h b/drivers/media/platform/davinci/vpif_display.h
index 849e0e3..e7a1723 100644
--- a/drivers/media/platform/davinci/vpif_display.h
+++ b/drivers/media/platform/davinci/vpif_display.h
@@ -62,7 +62,7 @@ struct video_obj {
 };
 
 struct vpif_disp_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index 769ff50..e93a233 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -136,7 +136,7 @@ struct gsc_fmt {
  * @idx : index of G-Scaler input buffer
  */
 struct gsc_input_buf {
-	struct vb2_buffer	vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head	list;
 	int			idx;
 };
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index d0ceae3..3844d6c 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -103,7 +103,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
 	/* Release unused buffers */
 	while (!suspend && !list_empty(&cap->pending_buf_q)) {
 		buf = fimc_pending_queue_pop(cap);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	/* If suspending put unused buffers onto pending queue */
 	while (!list_empty(&cap->active_buf_q)) {
@@ -111,7 +111,7 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
 		if (suspend)
 			fimc_pending_queue_add(cap, buf);
 		else
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 
 	fimc_hw_reset(fimc);
@@ -197,12 +197,12 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
 
 		v_buf = fimc_active_queue_pop(cap);
 
-		tv = &v_buf->vb.v4l2_buf.timestamp;
+		tv = &v_buf->vb.timestamp;
 		tv->tv_sec = ts.tv_sec;
 		tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
-		v_buf->vb.v4l2_buf.sequence = cap->frame_count++;
+		v_buf->vb.sequence = cap->frame_count++;
 
-		vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
+		vb2_buffer_done(&v_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	}
 
 	if (!list_empty(&cap->pending_buf_q)) {
@@ -1472,7 +1472,8 @@ void fimc_sensor_notify(struct v4l2_subdev *sd, unsigned int notification,
 		if (!list_empty(&fimc->vid_cap.active_buf_q)) {
 			buf = list_entry(fimc->vid_cap.active_buf_q.next,
 					 struct fimc_vid_buffer, list);
-			vb2_set_plane_payload(&buf->vb, 0, *((u32 *)arg));
+			vb2_set_plane_payload(&buf->vb.vb2_buf, 0,
+					      *((u32 *)arg));
 		}
 		fimc_capture_irq_handler(fimc, 1);
 		fimc_deactivate_capture(fimc);
diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h
index ccb5d91..d336fa2 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.h
+++ b/drivers/media/platform/exynos4-is/fimc-core.h
@@ -224,7 +224,7 @@ struct fimc_addr {
  * @index: buffer index for the output DMA engine
  */
 struct fimc_vid_buffer {
-	struct vb2_buffer	vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head	list;
 	struct fimc_addr	paddr;
 	int			index;
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h
index ad9908b..c2d25df 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp.h
+++ b/drivers/media/platform/exynos4-is/fimc-isp.h
@@ -102,7 +102,7 @@ struct fimc_isp_ctrls {
 };
 
 struct isp_video_buf {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	dma_addr_t dma_addr[FIMC_ISP_MAX_PLANES];
 	unsigned int index;
 };
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index 7e37c9a..21527cf 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -200,7 +200,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
 	/* Release unused buffers */
 	while (!suspend && !list_empty(&fimc->pending_buf_q)) {
 		buf = fimc_lite_pending_queue_pop(fimc);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	/* If suspending put unused buffers onto pending queue */
 	while (!list_empty(&fimc->active_buf_q)) {
@@ -208,7 +208,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
 		if (suspend)
 			fimc_lite_pending_queue_add(fimc, buf);
 		else
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 
 	spin_unlock_irqrestore(&fimc->slock, flags);
@@ -295,12 +295,12 @@ static irqreturn_t flite_irq_handler(int irq, void *priv)
 	    !list_empty(&fimc->active_buf_q)) {
 		vbuf = fimc_lite_active_queue_pop(fimc);
 		ktime_get_ts(&ts);
-		tv = &vbuf->vb.v4l2_buf.timestamp;
+		tv = &vbuf->vb.timestamp;
 		tv->tv_sec = ts.tv_sec;
 		tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
-		vbuf->vb.v4l2_buf.sequence = fimc->frame_count++;
+		vbuf->vb.sequence = fimc->frame_count++;
 		flite_hw_mask_dma_buffer(fimc, vbuf->index);
-		vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE);
+		vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	}
 
 	if (test_bit(ST_FLITE_CONFIG, &fimc->state))
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h
index 7e4c708..b302305 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.h
+++ b/drivers/media/platform/exynos4-is/fimc-lite.h
@@ -100,7 +100,7 @@ struct flite_frame {
  * @index: DMA start address register's index
  */
 struct flite_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 	dma_addr_t paddr;
 	unsigned short index;
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index c07f367..bdd8f11 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -200,18 +200,18 @@ static void dma_callback(void *data)
 {
 	struct deinterlace_ctx *curr_ctx = data;
 	struct deinterlace_dev *pcdev = curr_ctx->dev;
-	struct vb2_buffer *src_vb, *dst_vb;
+	struct vb2_v4l2_buffer *src_vb, *dst_vb;
 
 	atomic_set(&pcdev->busy, 0);
 
 	src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
 	dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
 
-	dst_vb->v4l2_buf.timestamp = src_vb->v4l2_buf.timestamp;
-	dst_vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-	dst_vb->v4l2_buf.flags |=
-		src_vb->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-	dst_vb->v4l2_buf.timecode = src_vb->v4l2_buf.timecode;
+	dst_vb->timestamp = src_vb->timestamp;
+	dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+	dst_vb->flags |=
+		src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+	dst_vb->timecode = src_vb->timecode;
 
 	v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
 	v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
@@ -225,7 +225,7 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
 				  int do_callback)
 {
 	struct deinterlace_q_data *s_q_data;
-	struct vb2_buffer *src_buf, *dst_buf;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
 	struct deinterlace_dev *pcdev = ctx->dev;
 	struct dma_chan *chan = pcdev->dma_chan;
 	struct dma_device *dmadev = chan->device;
@@ -243,8 +243,9 @@ static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
 	s_height = s_q_data->height;
 	s_size = s_width * s_height;
 
-	p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0);
-	p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+	p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf,
+							  0);
 	if (!p_in || !p_out) {
 		v4l2_err(&pcdev->v4l2_dev,
 			 "Acquiring kernel pointers to buffers failed\n");
@@ -849,8 +850,10 @@ static int deinterlace_buf_prepare(struct vb2_buffer *vb)
 
 static void deinterlace_buf_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+
+	v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf);
 }
 
 static struct vb2_ops deinterlace_qops = {
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 5e2b4df..1d95842 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -201,18 +201,18 @@ struct mcam_dma_desc {
 
 /*
  * Our buffer type for working with videobuf2.  Note that the vb2
- * developers have decreed that struct vb2_buffer must be at the
+ * developers have decreed that struct vb2_v4l2_buffer must be at the
  * beginning of this structure.
  */
 struct mcam_vb_buffer {
-	struct vb2_buffer vb_buf;
+	struct vb2_v4l2_buffer vb_buf;
 	struct list_head queue;
 	struct mcam_dma_desc *dma_desc;	/* Descriptor virtual address */
 	dma_addr_t dma_desc_pa;		/* Descriptor physical address */
 	int dma_desc_nent;		/* Number of mapped descriptors */
 };
 
-static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
+static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_v4l2_buffer *vb)
 {
 	return container_of(vb, struct mcam_vb_buffer, vb_buf);
 }
@@ -221,14 +221,14 @@ static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
  * Hand a completed buffer back to user space.
  */
 static void mcam_buffer_done(struct mcam_camera *cam, int frame,
-		struct vb2_buffer *vbuf)
+		struct vb2_v4l2_buffer *vbuf)
 {
-	vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage;
-	vbuf->v4l2_buf.sequence = cam->buf_seq[frame];
-	vbuf->v4l2_buf.field = V4L2_FIELD_NONE;
-	v4l2_get_timestamp(&vbuf->v4l2_buf.timestamp);
-	vb2_set_plane_payload(vbuf, 0, cam->pix_format.sizeimage);
-	vb2_buffer_done(vbuf, VB2_BUF_STATE_DONE);
+	vbuf->vb2_buf.planes[0].bytesused = cam->pix_format.sizeimage;
+	vbuf->sequence = cam->buf_seq[frame];
+	vbuf->field = V4L2_FIELD_NONE;
+	v4l2_get_timestamp(&vbuf->timestamp);
+	vb2_set_plane_payload(&vbuf->vb2_buf, 0, cam->pix_format.sizeimage);
+	vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 
@@ -482,7 +482,8 @@ static void mcam_frame_tasklet(unsigned long data)
 		 * Drop the lock during the big copy.  This *should* be safe...
 		 */
 		spin_unlock_irqrestore(&cam->dev_lock, flags);
-		memcpy(vb2_plane_vaddr(&buf->vb_buf, 0), cam->dma_bufs[bufno],
+		memcpy(vb2_plane_vaddr(&buf->vb_buf.vb2_buf, 0),
+				cam->dma_bufs[bufno],
 				cam->pix_format.sizeimage);
 		mcam_buffer_done(cam, bufno, &buf->vb_buf);
 		spin_lock_irqsave(&cam->dev_lock, flags);
@@ -548,7 +549,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
 {
 	struct mcam_vb_buffer *buf;
 	dma_addr_t dma_handle;
-	struct vb2_buffer *vb;
+	struct vb2_v4l2_buffer *vb;
 
 	/*
 	 * If there are no available buffers, go into single mode
@@ -570,7 +571,7 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
 	cam->vb_bufs[frame] = buf;
 	vb = &buf->vb_buf;
 
-	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
+	dma_handle = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
 	mcam_write_yuv_bases(cam, frame, dma_handle);
 }
 
@@ -1071,7 +1072,8 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
 
 static void mcam_vb_buf_queue(struct vb2_buffer *vb)
 {
-	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf);
 	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
 	unsigned long flags;
 	int start;
@@ -1096,14 +1098,14 @@ static void mcam_vb_requeue_bufs(struct vb2_queue *vq,
 
 	spin_lock_irqsave(&cam->dev_lock, flags);
 	list_for_each_entry_safe(buf, node, &cam->buffers, queue) {
-		vb2_buffer_done(&buf->vb_buf, state);
+		vb2_buffer_done(&buf->vb_buf.vb2_buf, state);
 		list_del(&buf->queue);
 	}
 	for (i = 0; i < MAX_DMA_BUFS; i++) {
 		buf = cam->vb_bufs[i];
 
 		if (buf) {
-			vb2_buffer_done(&buf->vb_buf, state);
+			vb2_buffer_done(&buf->vb_buf.vb2_buf, state);
 			cam->vb_bufs[i] = NULL;
 		}
 	}
@@ -1198,7 +1200,8 @@ static const struct vb2_ops mcam_vb2_ops = {
  */
 static int mcam_vb_sg_buf_init(struct vb2_buffer *vb)
 {
-	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf);
 	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
 	int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1;
 
@@ -1214,7 +1217,8 @@ static int mcam_vb_sg_buf_init(struct vb2_buffer *vb)
 
 static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
 {
-	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf);
 	struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
 	struct mcam_dma_desc *desc = mvb->dma_desc;
 	struct scatterlist *sg;
@@ -1230,8 +1234,9 @@ static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
 
 static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
-	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+	struct mcam_vb_buffer *mvb = vb_to_mvb(vbuf);
 	int ndesc = cam->pix_format.sizeimage/PAGE_SIZE + 1;
 
 	dma_free_coherent(cam->dev, ndesc * sizeof(struct mcam_dma_desc),
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index 41bb8df..08c9f62 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -363,7 +363,8 @@ static int isp_video_buffer_prepare(struct vb2_buffer *buf)
 		return -EINVAL;
 	}
 
-	vb2_set_plane_payload(&buffer->vb, 0, vfh->format.fmt.pix.sizeimage);
+	vb2_set_plane_payload(&buffer->vb.vb2_buf, 0,
+			      vfh->format.fmt.pix.sizeimage);
 	buffer->dma = addr;
 
 	return 0;
@@ -392,7 +393,7 @@ static void isp_video_buffer_queue(struct vb2_buffer *buf)
 	spin_lock_irqsave(&video->irqlock, flags);
 
 	if (unlikely(video->error)) {
-		vb2_buffer_done(&buffer->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		spin_unlock_irqrestore(&video->irqlock, flags);
 		return;
 	}
@@ -464,7 +465,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 	list_del(&buf->irqlist);
 	spin_unlock_irqrestore(&video->irqlock, flags);
 
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+	v4l2_get_timestamp(&buf->vb.timestamp);
 
 	/* Do frame number propagation only if this is the output video node.
 	 * Frame number either comes from the CSI receivers or it gets
@@ -473,15 +474,15 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 	 * first, so the input number might lag behind by 1 in some cases.
 	 */
 	if (video == pipe->output && !pipe->do_propagation)
-		buf->vb.v4l2_buf.sequence =
+		buf->vb.sequence =
 			atomic_inc_return(&pipe->frame_number);
 	else
-		buf->vb.v4l2_buf.sequence = atomic_read(&pipe->frame_number);
+		buf->vb.sequence = atomic_read(&pipe->frame_number);
 
 	if (pipe->field != V4L2_FIELD_NONE)
-		buf->vb.v4l2_buf.sequence /= 2;
+		buf->vb.sequence /= 2;
 
-	buf->vb.v4l2_buf.field = pipe->field;
+	buf->vb.field = pipe->field;
 
 	/* Report pipeline errors to userspace on the capture device side. */
 	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) {
@@ -491,7 +492,7 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video)
 		state = VB2_BUF_STATE_DONE;
 	}
 
-	vb2_buffer_done(&buf->vb, state);
+	vb2_buffer_done(&buf->vb.vb2_buf, state);
 
 	spin_lock_irqsave(&video->irqlock, flags);
 
@@ -546,7 +547,7 @@ void omap3isp_video_cancel_stream(struct isp_video *video)
 		buf = list_first_entry(&video->dmaqueue,
 				       struct isp_buffer, irqlist);
 		list_del(&buf->irqlist);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 
 	video->error = true;
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 31c2445..bcf0e0a 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -122,7 +122,7 @@ static inline int isp_pipeline_ready(struct isp_pipeline *pipe)
  * @dma: DMA address
  */
 struct isp_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head irqlist;
 	dma_addr_t dma;
 };
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index bb01eaa..dc67c4ec 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -164,12 +164,12 @@ static int camif_reinitialize(struct camif_vp *vp)
 	/* Release unused buffers */
 	while (!list_empty(&vp->pending_buf_q)) {
 		buf = camif_pending_queue_pop(vp);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 
 	while (!list_empty(&vp->active_buf_q)) {
 		buf = camif_active_queue_pop(vp);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 
 	spin_unlock_irqrestore(&camif->slock, flags);
@@ -342,11 +342,11 @@ irqreturn_t s3c_camif_irq_handler(int irq, void *priv)
 
 		if (!WARN_ON(vbuf == NULL)) {
 			/* Dequeue a filled buffer */
-			tv = &vbuf->vb.v4l2_buf.timestamp;
+			tv = &vbuf->vb.timestamp;
 			tv->tv_sec = ts.tv_sec;
 			tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
-			vbuf->vb.v4l2_buf.sequence = vp->frame_sequence++;
-			vb2_buffer_done(&vbuf->vb, VB2_BUF_STATE_DONE);
+			vbuf->vb.sequence = vp->frame_sequence++;
+			vb2_buffer_done(&vbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 
 			/* Set up an empty buffer at the DMA engine */
 			vbuf = camif_pending_queue_pop(vp);
diff --git a/drivers/media/platform/s3c-camif/camif-core.h b/drivers/media/platform/s3c-camif/camif-core.h
index 8ef6f26..adaf196 100644
--- a/drivers/media/platform/s3c-camif/camif-core.h
+++ b/drivers/media/platform/s3c-camif/camif-core.h
@@ -322,7 +322,7 @@ struct camif_addr {
  * @index: an identifier of this buffer at the DMA engine
  */
 struct camif_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 	struct camif_addr paddr;
 	unsigned int index;
diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h
index 855b723..42cd270 100644
--- a/drivers/media/platform/s5p-tv/mixer.h
+++ b/drivers/media/platform/s5p-tv/mixer.h
@@ -113,7 +113,7 @@ struct mxr_geometry {
 /** instance of a buffer */
 struct mxr_buffer {
 	/** common v4l buffer stuff -- must be first */
-	struct vb2_buffer	vb;
+	struct vb2_v4l2_buffer vb;
 	/** node for layer's lists */
 	struct list_head	list;
 };
diff --git a/drivers/media/platform/s5p-tv/mixer_reg.c b/drivers/media/platform/s5p-tv/mixer_reg.c
index 5127acb..a0ec14a 100644
--- a/drivers/media/platform/s5p-tv/mixer_reg.c
+++ b/drivers/media/platform/s5p-tv/mixer_reg.c
@@ -279,7 +279,7 @@ static void mxr_irq_layer_handle(struct mxr_layer *layer)
 	layer->ops.buffer_set(layer, layer->update_buf);
 
 	if (done && done != layer->shadow_buf)
-		vb2_buffer_done(&done->vb, VB2_BUF_STATE_DONE);
+		vb2_buffer_done(&done->vb.vb2_buf, VB2_BUF_STATE_DONE);
 
 done:
 	spin_unlock(&layer->enq_slock);
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index 751f3b6..5347a6c 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -963,11 +963,13 @@ static void mxr_watchdog(unsigned long arg)
 	if (layer->update_buf == layer->shadow_buf)
 		layer->update_buf = NULL;
 	if (layer->update_buf) {
-		vb2_buffer_done(&layer->update_buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&layer->update_buf->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 		layer->update_buf = NULL;
 	}
 	if (layer->shadow_buf) {
-		vb2_buffer_done(&layer->shadow_buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&layer->shadow_buf->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 		layer->shadow_buf = NULL;
 	}
 	spin_unlock_irqrestore(&layer->enq_slock, flags);
@@ -991,7 +993,7 @@ static void stop_streaming(struct vb2_queue *vq)
 	/* set all buffer to be done */
 	list_for_each_entry_safe(buf, buf_tmp, &layer->enq_list, list) {
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 
 	spin_unlock_irqrestore(&layer->enq_slock, flags);
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index f5e3eb3a..6455cb9 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -931,9 +931,10 @@ static int sh_veu_buf_prepare(struct vb2_buffer *vb)
 
 static void sh_veu_buf_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct sh_veu_dev *veu = vb2_get_drv_priv(vb->vb2_queue);
-	dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->v4l2_buf.type);
-	v4l2_m2m_buf_queue(veu->m2m_ctx, vb);
+	dev_dbg(veu->dev, "%s(%d)\n", __func__, vb->type);
+	v4l2_m2m_buf_queue(veu->m2m_ctx, vbuf);
 }
 
 static const struct vb2_ops sh_veu_qops = {
@@ -1084,8 +1085,8 @@ static irqreturn_t sh_veu_bh(int irq, void *dev_id)
 static irqreturn_t sh_veu_isr(int irq, void *dev_id)
 {
 	struct sh_veu_dev *veu = dev_id;
-	struct vb2_buffer *dst;
-	struct vb2_buffer *src;
+	struct vb2_v4l2_buffer *dst;
+	struct vb2_v4l2_buffer *src;
 	u32 status = sh_veu_reg_read(veu, VEU_EVTR);
 
 	/* bundle read mode not used */
@@ -1105,11 +1106,11 @@ static irqreturn_t sh_veu_isr(int irq, void *dev_id)
 	if (!src || !dst)
 		return IRQ_NONE;
 
-	dst->v4l2_buf.timestamp = src->v4l2_buf.timestamp;
-	dst->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-	dst->v4l2_buf.flags |=
-		src->v4l2_buf.flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-	dst->v4l2_buf.timecode = src->v4l2_buf.timecode;
+	dst->timestamp = src->timestamp;
+	dst->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+	dst->flags |=
+		src->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+	dst->timecode = src->timecode;
 
 	spin_lock(&veu->lock);
 	v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index fe5c8ab..7014f2e 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -62,7 +62,7 @@ enum sh_vou_status {
 #define VOU_MIN_IMAGE_HEIGHT	16
 
 struct sh_vou_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
@@ -302,7 +302,8 @@ static int sh_vou_start_streaming(struct vb2_queue *vq, unsigned int count)
 					 video, s_stream, 1);
 	if (ret < 0 && ret != -ENOIOCTLCMD) {
 		list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) {
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 			list_del(&buf->list);
 		}
 		vou_dev->active = NULL;
@@ -353,7 +354,7 @@ static void sh_vou_stop_streaming(struct vb2_queue *vq)
 	msleep(50);
 	spin_lock_irqsave(&vou_dev->lock, flags);
 	list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) {
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		list_del(&buf->list);
 	}
 	vou_dev->active = NULL;
@@ -1066,10 +1067,10 @@ static irqreturn_t sh_vou_isr(int irq, void *dev_id)
 
 	list_del(&vb->list);
 
-	v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
-	vb->vb.v4l2_buf.sequence = vou_dev->sequence++;
-	vb->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
-	vb2_buffer_done(&vb->vb, VB2_BUF_STATE_DONE);
+	v4l2_get_timestamp(&vb->vb.timestamp);
+	vb->vb.sequence = vou_dev->sequence++;
+	vb->vb.field = V4L2_FIELD_INTERLACED;
+	vb2_buffer_done(&vb->vb.vb2_buf, VB2_BUF_STATE_DONE);
 
 	vou_dev->active = list_entry(vou_dev->buf_list.next,
 				     struct sh_vou_buffer, list);
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 9070172..6b312a4 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -59,7 +59,7 @@ struct isi_dma_desc {
 
 /* Frame buffer data */
 struct frame_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct isi_dma_desc *p_dma_desc;
 	struct list_head list;
 };
@@ -292,7 +292,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
 		return -EINVAL;
 	}
 
-	vb2_set_plane_payload(&buf->vb, 0, size);
+	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
 
 	if (!buf->p_dma_desc) {
 		if (list_empty(&isi->dma_desc_head)) {
@@ -422,7 +422,7 @@ static void stop_streaming(struct vb2_queue *vq)
 	/* Release all active buffers */
 	list_for_each_entry_safe(buf, node, &isi->video_buffer_list, list) {
 		list_del_init(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irq(&isi->lock);
 
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index 6e41335..f4398bb 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -225,7 +225,7 @@ struct mx2_buf_internal {
 /* buffer for one video frame */
 struct mx2_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer		vb;
+	struct vb2_v4l2_buffer vb;
 	struct mx2_buf_internal		internal;
 };
 
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index ace41f5..dcd7dc1 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -63,7 +63,7 @@
 
 struct mx3_camera_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer			vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head			queue;
 
 	/* One descriptot per scatterlist (per frame) */
@@ -424,7 +424,7 @@ static void mx3_stop_streaming(struct vb2_queue *q)
 
 	list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) {
 		list_del_init(&buf->queue);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 
 	spin_unlock_irqrestore(&mx3_cam->lock, flags);
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 71dd71c..cd45fa9 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -492,7 +492,7 @@ struct rcar_vin_priv {
 #define is_continuous_transfer(priv)	(priv->vb_count > MAX_BUFFER_NUM)
 
 struct rcar_vin_buffer {
-	struct vb2_buffer		vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head		list;
 };
 
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index efdeea4..161b614 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -93,7 +93,7 @@
 
 /* per video frame buffer */
 struct sh_mobile_ceu_buffer {
-	struct vb2_buffer vb; /* v4l buffer must be first */
+	struct vb2_v4l2_buffer vb; /* v4l buffer must be first */
 	struct list_head queue;
 };
 
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 5f1b1da..b039103 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -93,7 +93,7 @@ extern struct vivid_fmt vivid_formats[];
 /* buffer for one video frame */
 struct vivid_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer	vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head	list;
 };
 
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 1727f54..d9e7df2 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -246,7 +246,7 @@ static void *plane_vaddr(struct tpg_data *tpg, struct vivid_buffer *buf,
 static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 		struct vivid_buffer *vid_cap_buf)
 {
-	bool blank = dev->must_blank[vid_cap_buf->vb.v4l2_buf.index];
+	bool blank = dev->must_blank[vid_cap_buf->vb.vb2_buf.index];
 	struct tpg_data *tpg = &dev->tpg;
 	struct vivid_buffer *vid_out_buf = NULL;
 	unsigned vdiv = dev->fmt_out->vdownsampling[p];
@@ -283,7 +283,7 @@ static int vivid_copy_buffer(struct vivid_dev *dev, unsigned p, u8 *vcapbuf,
 	if (vid_out_buf == NULL)
 		return -ENODATA;
 
-	vid_cap_buf->vb.v4l2_buf.field = vid_out_buf->vb.v4l2_buf.field;
+	vid_cap_buf->vb.field = vid_out_buf->vb.field;
 
 	voutbuf = plane_vaddr(tpg, vid_out_buf, p,
 			      dev->bytesperline_out, dev->fmt_out_rect.height);
@@ -433,13 +433,13 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 	     (vivid_is_hdmi_cap(dev) && !VIVID_INVALID_SIGNAL(dev->dv_timings_signal_mode))))
 		is_loop = true;
 
-	buf->vb.v4l2_buf.sequence = dev->vid_cap_seq_count;
+	buf->vb.sequence = dev->vid_cap_seq_count;
 	/*
 	 * Take the timestamp now if the timestamp source is set to
 	 * "Start of Exposure".
 	 */
 	if (dev->tstamp_src_is_soe)
-		v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+		v4l2_get_timestamp(&buf->vb.timestamp);
 	if (dev->field_cap == V4L2_FIELD_ALTERNATE) {
 		/*
 		 * 60 Hz standards start with the bottom field, 50 Hz standards
@@ -447,19 +447,19 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 		 * then the field is TOP for 50 Hz and BOTTOM for 60 Hz
 		 * standards.
 		 */
-		buf->vb.v4l2_buf.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ?
+		buf->vb.field = ((dev->vid_cap_seq_count & 1) ^ is_60hz) ?
 			V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP;
 		/*
 		 * The sequence counter counts frames, not fields. So divide
 		 * by two.
 		 */
-		buf->vb.v4l2_buf.sequence /= 2;
+		buf->vb.sequence /= 2;
 	} else {
-		buf->vb.v4l2_buf.field = dev->field_cap;
+		buf->vb.field = dev->field_cap;
 	}
-	tpg_s_field(tpg, buf->vb.v4l2_buf.field,
+	tpg_s_field(tpg, buf->vb.field,
 		    dev->field_cap == V4L2_FIELD_ALTERNATE);
-	tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.v4l2_buf.index]);
+	tpg_s_perc_fill_blank(tpg, dev->must_blank[buf->vb.vb2_buf.index]);
 
 	vivid_precalc_copy_rects(dev);
 
@@ -481,10 +481,10 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 		if (!is_loop || vivid_copy_buffer(dev, p, vbuf, buf))
 			tpg_fill_plane_buffer(tpg, vivid_get_std_cap(dev), p, vbuf);
 	}
-	dev->must_blank[buf->vb.v4l2_buf.index] = false;
+	dev->must_blank[buf->vb.vb2_buf.index] = false;
 
 	/* Updates stream time, only update at the start of a new frame. */
-	if (dev->field_cap != V4L2_FIELD_ALTERNATE || (buf->vb.v4l2_buf.sequence & 1) == 0)
+	if (dev->field_cap != V4L2_FIELD_ALTERNATE || (buf->vb.sequence & 1) == 0)
 		dev->ms_vid_cap = jiffies_to_msecs(jiffies - dev->jiffies_vid_cap);
 
 	ms = dev->ms_vid_cap;
@@ -494,9 +494,9 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 				(ms / (60 * 1000)) % 60,
 				(ms / 1000) % 60,
 				ms % 1000,
-				buf->vb.v4l2_buf.sequence,
+				buf->vb.sequence,
 				(dev->field_cap == V4L2_FIELD_ALTERNATE) ?
-					(buf->vb.v4l2_buf.field == V4L2_FIELD_TOP ?
+					(buf->vb.field == V4L2_FIELD_TOP ?
 					 " top" : " bottom") : "");
 		tpg_gen_text(tpg, basep, line++ * line_height, 16, str);
 	}
@@ -553,8 +553,8 @@ static void vivid_fillbuff(struct vivid_dev *dev, struct vivid_buffer *buf)
 	 * the timestamp now.
 	 */
 	if (!dev->tstamp_src_is_soe)
-		v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-	buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
+		v4l2_get_timestamp(&buf->vb.timestamp);
+	buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
 }
 
 /*
@@ -616,7 +616,7 @@ static void vivid_overlay(struct vivid_dev *dev, struct vivid_buffer *buf)
 		return;
 	if ((dev->overlay_cap_field == V4L2_FIELD_TOP ||
 	     dev->overlay_cap_field == V4L2_FIELD_BOTTOM) &&
-	    dev->overlay_cap_field != buf->vb.v4l2_buf.field)
+	    dev->overlay_cap_field != buf->vb.field)
 		return;
 
 	vbuf += dev->compose_cap.left * pixsize + dev->compose_cap.top * stride;
@@ -699,17 +699,17 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs)
 		/* Fill buffer */
 		vivid_fillbuff(dev, vid_cap_buf);
 		dprintk(dev, 1, "filled buffer %d\n",
-			vid_cap_buf->vb.v4l2_buf.index);
+			vid_cap_buf->vb.vb2_buf.index);
 
 		/* Handle overlay */
 		if (dev->overlay_cap_owner && dev->fb_cap.base &&
 				dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc)
 			vivid_overlay(dev, vid_cap_buf);
 
-		vb2_buffer_done(&vid_cap_buf->vb, dev->dqbuf_error ?
-				VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+		vb2_buffer_done(&vid_cap_buf->vb.vb2_buf,
+				dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 		dprintk(dev, 2, "vid_cap buffer %d done\n",
-				vid_cap_buf->vb.v4l2_buf.index);
+				vid_cap_buf->vb.vb2_buf.index);
 	}
 
 	if (vbi_cap_buf) {
@@ -717,10 +717,10 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev *dev, int dropped_bufs)
 			vivid_sliced_vbi_cap_process(dev, vbi_cap_buf);
 		else
 			vivid_raw_vbi_cap_process(dev, vbi_cap_buf);
-		vb2_buffer_done(&vbi_cap_buf->vb, dev->dqbuf_error ?
-				VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+		vb2_buffer_done(&vbi_cap_buf->vb.vb2_buf,
+				dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 		dprintk(dev, 2, "vbi_cap %d done\n",
-				vbi_cap_buf->vb.v4l2_buf.index);
+				vbi_cap_buf->vb.vb2_buf.index);
 	}
 	dev->dqbuf_error = false;
 
@@ -884,9 +884,9 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming)
 			buf = list_entry(dev->vid_cap_active.next,
 					 struct vivid_buffer, list);
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 			dprintk(dev, 2, "vid_cap buffer %d done\n",
-				buf->vb.v4l2_buf.index);
+				buf->vb.vb2_buf.index);
 		}
 	}
 
@@ -897,9 +897,9 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, bool *pstreaming)
 			buf = list_entry(dev->vbi_cap_active.next,
 					 struct vivid_buffer, list);
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 			dprintk(dev, 2, "vbi_cap buffer %d done\n",
-				buf->vb.v4l2_buf.index);
+				buf->vb.vb2_buf.index);
 		}
 	}
 
diff --git a/drivers/media/platform/vivid/vivid-kthread-out.c b/drivers/media/platform/vivid/vivid-kthread-out.c
index d9f36cc..e5155d9f 100644
--- a/drivers/media/platform/vivid/vivid-kthread-out.c
+++ b/drivers/media/platform/vivid/vivid-kthread-out.c
@@ -87,33 +87,33 @@ static void vivid_thread_vid_out_tick(struct vivid_dev *dev)
 		return;
 
 	if (vid_out_buf) {
-		vid_out_buf->vb.v4l2_buf.sequence = dev->vid_out_seq_count;
+		vid_out_buf->vb.sequence = dev->vid_out_seq_count;
 		if (dev->field_out == V4L2_FIELD_ALTERNATE) {
 			/*
 			 * The sequence counter counts frames, not fields. So divide
 			 * by two.
 			 */
-			vid_out_buf->vb.v4l2_buf.sequence /= 2;
+			vid_out_buf->vb.sequence /= 2;
 		}
-		v4l2_get_timestamp(&vid_out_buf->vb.v4l2_buf.timestamp);
-		vid_out_buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
-		vb2_buffer_done(&vid_out_buf->vb, dev->dqbuf_error ?
-				VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+		v4l2_get_timestamp(&vid_out_buf->vb.timestamp);
+		vid_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+		vb2_buffer_done(&vid_out_buf->vb.vb2_buf,
+				dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 		dprintk(dev, 2, "vid_out buffer %d done\n",
-			vid_out_buf->vb.v4l2_buf.index);
+			vid_out_buf->vb.vb2_buf.index);
 	}
 
 	if (vbi_out_buf) {
 		if (dev->stream_sliced_vbi_out)
 			vivid_sliced_vbi_out_process(dev, vbi_out_buf);
 
-		vbi_out_buf->vb.v4l2_buf.sequence = dev->vbi_out_seq_count;
-		v4l2_get_timestamp(&vbi_out_buf->vb.v4l2_buf.timestamp);
-		vbi_out_buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
-		vb2_buffer_done(&vbi_out_buf->vb, dev->dqbuf_error ?
-				VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+		vbi_out_buf->vb.sequence = dev->vbi_out_seq_count;
+		v4l2_get_timestamp(&vbi_out_buf->vb.timestamp);
+		vbi_out_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+		vb2_buffer_done(&vbi_out_buf->vb.vb2_buf,
+				dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 		dprintk(dev, 2, "vbi_out buffer %d done\n",
-			vbi_out_buf->vb.v4l2_buf.index);
+			vbi_out_buf->vb.vb2_buf.index);
 	}
 	dev->dqbuf_error = false;
 }
@@ -274,9 +274,9 @@ void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
 			buf = list_entry(dev->vid_out_active.next,
 					 struct vivid_buffer, list);
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 			dprintk(dev, 2, "vid_out buffer %d done\n",
-				buf->vb.v4l2_buf.index);
+				buf->vb.vb2_buf.index);
 		}
 	}
 
@@ -287,9 +287,9 @@ void vivid_stop_generating_vid_out(struct vivid_dev *dev, bool *pstreaming)
 			buf = list_entry(dev->vbi_out_active.next,
 					 struct vivid_buffer, list);
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 			dprintk(dev, 2, "vbi_out buffer %d done\n",
-				buf->vb.v4l2_buf.index);
+				buf->vb.vb2_buf.index);
 		}
 	}
 
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index d2f2188..bae5b8a 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -114,12 +114,12 @@ static void vivid_thread_sdr_cap_tick(struct vivid_dev *dev)
 	spin_unlock(&dev->slock);
 
 	if (sdr_cap_buf) {
-		sdr_cap_buf->vb.v4l2_buf.sequence = dev->sdr_cap_seq_count;
+		sdr_cap_buf->vb.sequence = dev->sdr_cap_seq_count;
 		vivid_sdr_cap_process(dev, sdr_cap_buf);
-		v4l2_get_timestamp(&sdr_cap_buf->vb.v4l2_buf.timestamp);
-		sdr_cap_buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
-		vb2_buffer_done(&sdr_cap_buf->vb, dev->dqbuf_error ?
-				VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+		v4l2_get_timestamp(&sdr_cap_buf->vb.timestamp);
+		sdr_cap_buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
+		vb2_buffer_done(&sdr_cap_buf->vb.vb2_buf,
+				dev->dqbuf_error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 		dev->dqbuf_error = false;
 	}
 }
@@ -282,7 +282,8 @@ static int sdr_cap_start_streaming(struct vb2_queue *vq, unsigned count)
 
 		list_for_each_entry_safe(buf, tmp, &dev->sdr_cap_active, list) {
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 		}
 	}
 	return err;
@@ -301,7 +302,7 @@ static void sdr_cap_stop_streaming(struct vb2_queue *vq)
 
 		buf = list_entry(dev->sdr_cap_active.next, struct vivid_buffer, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 
 	/* shutdown control thread */
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
index ef81b01..73e9c0b 100644
--- a/drivers/media/platform/vivid/vivid-vbi-cap.c
+++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
@@ -97,19 +97,19 @@ void vivid_raw_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *buf)
 	u8 *vbuf = vb2_plane_vaddr(&buf->vb, 0);
 
 	vivid_g_fmt_vbi_cap(dev, &vbi);
-	buf->vb.v4l2_buf.sequence = dev->vbi_cap_seq_count;
+	buf->vb.sequence = dev->vbi_cap_seq_count;
 	if (dev->field_cap == V4L2_FIELD_ALTERNATE)
-		buf->vb.v4l2_buf.sequence /= 2;
+		buf->vb.sequence /= 2;
 
-	vivid_sliced_vbi_cap_fill(dev, buf->vb.v4l2_buf.sequence);
+	vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence);
 
 	memset(vbuf, 0x10, vb2_plane_size(&buf->vb, 0));
 
 	if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode))
 		vivid_vbi_gen_raw(&dev->vbi_gen, &vbi, vbuf);
 
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-	buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
+	v4l2_get_timestamp(&buf->vb.timestamp);
+	buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
 }
 
 
@@ -117,11 +117,11 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *bu
 {
 	struct v4l2_sliced_vbi_data *vbuf = vb2_plane_vaddr(&buf->vb, 0);
 
-	buf->vb.v4l2_buf.sequence = dev->vbi_cap_seq_count;
+	buf->vb.sequence = dev->vbi_cap_seq_count;
 	if (dev->field_cap == V4L2_FIELD_ALTERNATE)
-		buf->vb.v4l2_buf.sequence /= 2;
+		buf->vb.sequence /= 2;
 
-	vivid_sliced_vbi_cap_fill(dev, buf->vb.v4l2_buf.sequence);
+	vivid_sliced_vbi_cap_fill(dev, buf->vb.sequence);
 
 	memset(vbuf, 0, vb2_plane_size(&buf->vb, 0));
 	if (!VIVID_INVALID_SIGNAL(dev->std_signal_mode)) {
@@ -131,8 +131,8 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *bu
 			vbuf[i] = dev->vbi_gen.data[i];
 	}
 
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-	buf->vb.v4l2_buf.timestamp.tv_sec += dev->time_wrap_offset;
+	v4l2_get_timestamp(&buf->vb.timestamp);
+	buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
 }
 
 static int vbi_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
@@ -215,7 +215,8 @@ static int vbi_cap_start_streaming(struct vb2_queue *vq, unsigned count)
 
 		list_for_each_entry_safe(buf, tmp, &dev->vbi_cap_active, list) {
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 		}
 	}
 	return err;
diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c
index 4e4c70e..1333f96 100644
--- a/drivers/media/platform/vivid/vivid-vbi-out.c
+++ b/drivers/media/platform/vivid/vivid-vbi-out.c
@@ -107,7 +107,8 @@ static int vbi_out_start_streaming(struct vb2_queue *vq, unsigned count)
 
 		list_for_each_entry_safe(buf, tmp, &dev->vbi_out_active, list) {
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 		}
 	}
 	return err;
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index ed0b878..4572709 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -268,7 +268,8 @@ static int vid_cap_start_streaming(struct vb2_queue *vq, unsigned count)
 
 		list_for_each_entry_safe(buf, tmp, &dev->vid_cap_active, list) {
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 		}
 	}
 	return err;
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index c404e27..73c8f97 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -186,7 +186,8 @@ static int vid_out_start_streaming(struct vb2_queue *vq, unsigned count)
 
 		list_for_each_entry_safe(buf, tmp, &dev->vid_out_active, list) {
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 		}
 	}
 	return err;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index dfd45c7..5837bc1 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -610,11 +610,11 @@ vsp1_video_complete_buffer(struct vsp1_video *video)
 
 	spin_unlock_irqrestore(&video->irqlock, flags);
 
-	done->buf.v4l2_buf.sequence = video->sequence++;
-	v4l2_get_timestamp(&done->buf.v4l2_buf.timestamp);
+	done->buf.sequence = video->sequence++;
+	v4l2_get_timestamp(&done->buf.timestamp);
 	for (i = 0; i < done->buf.num_planes; ++i)
-		vb2_set_plane_payload(&done->buf, i, done->length[i]);
-	vb2_buffer_done(&done->buf, VB2_BUF_STATE_DONE);
+		vb2_set_plane_payload(&done->buf.vb2_buf, i, done->length[i]);
+	vb2_buffer_done(&done->buf.vb2_buf, VB2_BUF_STATE_DONE);
 
 	return next;
 }
@@ -954,7 +954,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
 	/* Remove all buffers from the IRQ queue. */
 	spin_lock_irqsave(&video->irqlock, flags);
 	list_for_each_entry(buffer, &video->irqqueue, queue)
-		vb2_buffer_done(&buffer->buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buffer->buf.vb2_buf, VB2_BUF_STATE_ERROR);
 	INIT_LIST_HEAD(&video->irqqueue);
 	spin_unlock_irqrestore(&video->irqlock, flags);
 }
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index d808301..ab56f30 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -94,7 +94,7 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
 }
 
 struct vsp1_video_buffer {
-	struct vb2_buffer buf;
+	struct vb2_v4l2_buffer buf;
 	struct list_head queue;
 
 	dma_addr_t addr[3];
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
index d9dcd4b..3b6112e 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -285,7 +285,7 @@ done:
  * @dma: DMA channel that uses the buffer
  */
 struct xvip_dma_buffer {
-	struct vb2_buffer buf;
+	struct vb2_v4l2_buffer buf;
 	struct list_head queue;
 	struct xvip_dma *dma;
 };
@@ -301,11 +301,11 @@ static void xvip_dma_complete(void *param)
 	list_del(&buf->queue);
 	spin_unlock(&dma->queued_lock);
 
-	buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
-	buf->buf.v4l2_buf.sequence = dma->sequence++;
-	v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp);
-	vb2_set_plane_payload(&buf->buf, 0, dma->format.sizeimage);
-	vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+	buf->buf.field = V4L2_FIELD_NONE;
+	buf->buf.sequence = dma->sequence++;
+	v4l2_get_timestamp(&buf->buf.timestamp);
+	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, dma->format.sizeimage);
+	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 static int
@@ -367,7 +367,7 @@ static void xvip_dma_buffer_queue(struct vb2_buffer *vb)
 	desc = dmaengine_prep_interleaved_dma(dma->dma, &dma->xt, flags);
 	if (!desc) {
 		dev_err(dma->xdev->dev, "Failed to prepare DMA transfer\n");
-		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
 		return;
 	}
 	desc->callback = xvip_dma_complete;
@@ -434,7 +434,7 @@ error:
 	/* Give back all queued buffers to videobuf2. */
 	spin_lock_irq(&dma->queued_lock);
 	list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) {
-		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_QUEUED);
+		vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_QUEUED);
 		list_del(&buf->queue);
 	}
 	spin_unlock_irq(&dma->queued_lock);
@@ -461,7 +461,7 @@ static void xvip_dma_stop_streaming(struct vb2_queue *vq)
 	/* Give back all queued buffers to videobuf2. */
 	spin_lock_irq(&dma->queued_lock);
 	list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) {
-		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
 		list_del(&buf->queue);
 	}
 	spin_unlock_irq(&dma->queued_lock);
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index 8f2e1c2..bc45104 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -97,7 +97,7 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 
 /* intermediate buffers with raw data from the USB device */
 struct airspy_frame_buf {
-	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+	struct vb2_v4l2_buffer vb;   /* common v4l buffer stuff -- must be first */
 	struct list_head list;
 };
 
@@ -313,10 +313,10 @@ static void airspy_urb_complete(struct urb *urb)
 		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
 		len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
 				urb->actual_length);
-		vb2_set_plane_payload(&fbuf->vb, 0, len);
-		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
-		fbuf->vb.v4l2_buf.sequence = s->sequence++;
-		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+		vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len);
+		v4l2_get_timestamp(&fbuf->vb.timestamp);
+		fbuf->vb.sequence = s->sequence++;
+		vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	}
 skip:
 	usb_submit_urb(urb, GFP_ATOMIC);
@@ -459,7 +459,7 @@ static void airspy_cleanup_queued_bufs(struct airspy *s)
 		buf = list_entry(s->queued_bufs.next,
 				struct airspy_frame_buf, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
 }
@@ -512,7 +512,7 @@ static void airspy_buf_queue(struct vb2_buffer *vb)
 
 	/* Check the device has not disconnected between prep and queuing */
 	if (unlikely(!s->udev)) {
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		return;
 	}
 
@@ -571,7 +571,8 @@ err_clear_bit:
 
 		list_for_each_entry_safe(buf, tmp, &s->queued_bufs, list) {
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 		}
 	}
 
diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c
index f67247c..44d1d46 100644
--- a/drivers/media/usb/au0828/au0828-vbi.c
+++ b/drivers/media/usb/au0828/au0828-vbi.c
@@ -52,7 +52,6 @@ static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 static int vbi_buffer_prepare(struct vb2_buffer *vb)
 {
 	struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
 	unsigned long size;
 
 	size = dev->vbi_width * dev->vbi_height * 2;
@@ -62,7 +61,7 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb)
 			__func__, vb2_plane_size(vb, 0), size);
 		return -EINVAL;
 	}
-	vb2_set_plane_payload(&buf->vb, 0, size);
+	vb2_set_plane_payload(vb, 0, size);
 
 	return 0;
 }
@@ -71,7 +70,8 @@ static void
 vbi_buffer_queue(struct vb2_buffer *vb)
 {
 	struct au0828_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
-	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct au0828_buffer *buf = container_of(vbuf, struct au0828_buffer, vb);
 	struct au0828_dmaqueue *vbiq = &dev->vbiq;
 	unsigned long flags = 0;
 
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 1a362a0..065b9c8 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -302,20 +302,20 @@ static inline void buffer_filled(struct au0828_dev *dev,
 				 struct au0828_dmaqueue *dma_q,
 				 struct au0828_buffer *buf)
 {
-	struct vb2_buffer *vb = &buf->vb;
-	struct vb2_queue *q = vb->vb2_queue;
+	struct vb2_v4l2_buffer *vb = &buf->vb;
+	struct vb2_queue *q = vb->vb2_buf.vb2_queue;
 
 	/* Advice that buffer was filled */
 	au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
 
 	if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		vb->v4l2_buf.sequence = dev->frame_count++;
+		vb->sequence = dev->frame_count++;
 	else
-		vb->v4l2_buf.sequence = dev->vbi_frame_count++;
+		vb->sequence = dev->vbi_frame_count++;
 
-	vb->v4l2_buf.field = V4L2_FIELD_INTERLACED;
-	v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
-	vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+	vb->field = V4L2_FIELD_INTERLACED;
+	v4l2_get_timestamp(&vb->timestamp);
+	vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 /*
@@ -531,11 +531,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 
 	buf = dev->isoc_ctl.buf;
 	if (buf != NULL)
-		outp = vb2_plane_vaddr(&buf->vb, 0);
+		outp = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 
 	vbi_buf = dev->isoc_ctl.vbi_buf;
 	if (vbi_buf != NULL)
-		vbioutp = vb2_plane_vaddr(&vbi_buf->vb, 0);
+		vbioutp = vb2_plane_vaddr(&vbi_buf->vb.vb2_buf, 0);
 
 	for (i = 0; i < urb->number_of_packets; i++) {
 		int status = urb->iso_frame_desc[i].status;
@@ -574,7 +574,7 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 					vbioutp = NULL;
 				else
 					vbioutp = vb2_plane_vaddr(
-						&vbi_buf->vb, 0);
+						&vbi_buf->vb.vb2_buf, 0);
 
 				/* Video */
 				if (buf != NULL)
@@ -583,7 +583,8 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 				if (buf == NULL)
 					outp = NULL;
 				else
-					outp = vb2_plane_vaddr(&buf->vb, 0);
+					outp = vb2_plane_vaddr(
+						&buf->vb.vb2_buf, 0);
 
 				/* As long as isoc traffic is arriving, keep
 				   resetting the timer */
@@ -658,7 +659,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 static int
 buffer_prepare(struct vb2_buffer *vb)
 {
-	struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct au0828_buffer *buf = container_of(vbuf,
+				struct au0828_buffer, vb);
 	struct au0828_dev    *dev = vb2_get_drv_priv(vb->vb2_queue);
 
 	buf->length = dev->height * dev->bytesperline;
@@ -668,14 +671,15 @@ buffer_prepare(struct vb2_buffer *vb)
 			__func__, vb2_plane_size(vb, 0), buf->length);
 		return -EINVAL;
 	}
-	vb2_set_plane_payload(&buf->vb, 0, buf->length);
+	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->length);
 	return 0;
 }
 
 static void
 buffer_queue(struct vb2_buffer *vb)
 {
-	struct au0828_buffer    *buf     = container_of(vb,
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct au0828_buffer    *buf     = container_of(vbuf,
 							struct au0828_buffer,
 							vb);
 	struct au0828_dev       *dev     = vb2_get_drv_priv(vb->vb2_queue);
@@ -826,14 +830,15 @@ static void au0828_stop_streaming(struct vb2_queue *vq)
 
 	spin_lock_irqsave(&dev->slock, flags);
 	if (dev->isoc_ctl.buf != NULL) {
-		vb2_buffer_done(&dev->isoc_ctl.buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&dev->isoc_ctl.buf->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 		dev->isoc_ctl.buf = NULL;
 	}
 	while (!list_empty(&vidq->active)) {
 		struct au0828_buffer *buf;
 
 		buf = list_entry(vidq->active.next, struct au0828_buffer, list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		list_del(&buf->list);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
@@ -853,7 +858,7 @@ void au0828_stop_vbi_streaming(struct vb2_queue *vq)
 
 	spin_lock_irqsave(&dev->slock, flags);
 	if (dev->isoc_ctl.vbi_buf != NULL) {
-		vb2_buffer_done(&dev->isoc_ctl.vbi_buf->vb,
+		vb2_buffer_done(&dev->isoc_ctl.vbi_buf->vb.vb2_buf,
 				VB2_BUF_STATE_ERROR);
 		dev->isoc_ctl.vbi_buf = NULL;
 	}
@@ -862,7 +867,7 @@ void au0828_stop_vbi_streaming(struct vb2_queue *vq)
 
 		buf = list_entry(vbiq->active.next, struct au0828_buffer, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 
@@ -911,7 +916,7 @@ static void au0828_vid_buffer_timeout(unsigned long data)
 
 	buf = dev->isoc_ctl.buf;
 	if (buf != NULL) {
-		vid_data = vb2_plane_vaddr(&buf->vb, 0);
+		vid_data = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 		memset(vid_data, 0x00, buf->length); /* Blank green frame */
 		buffer_filled(dev, dma_q, buf);
 	}
@@ -935,7 +940,7 @@ static void au0828_vbi_buffer_timeout(unsigned long data)
 
 	buf = dev->isoc_ctl.vbi_buf;
 	if (buf != NULL) {
-		vbi_data = vb2_plane_vaddr(&buf->vb, 0);
+		vbi_data = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 		memset(vbi_data, 0x00, buf->length);
 		buffer_filled(dev, dma_q, buf);
 	}
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index 3b48000..60b5939 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -28,6 +28,7 @@
 
 /* Analog */
 #include <linux/videodev2.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
@@ -167,7 +168,7 @@ struct au0828_usb_isoc_ctl {
 /* buffer for one video frame */
 struct au0828_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 
 	void *mem;
diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
index 744e7ed..a4d7f41 100644
--- a/drivers/media/usb/em28xx/em28xx-vbi.c
+++ b/drivers/media/usb/em28xx/em28xx-vbi.c
@@ -71,7 +71,7 @@ static int vbi_buffer_prepare(struct vb2_buffer *vb)
 		       __func__, vb2_plane_size(vb, 0), size);
 		return -EINVAL;
 	}
-	vb2_set_plane_payload(&buf->vb, 0, size);
+	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
 
 	return 0;
 }
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 4397ce5..5b6fdd2 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -433,14 +433,14 @@ static inline void finish_buffer(struct em28xx *dev,
 {
 	em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->top_field);
 
-	buf->vb.v4l2_buf.sequence = dev->v4l2->field_count++;
+	buf->vb.sequence = dev->v4l2->field_count++;
 	if (dev->v4l2->progressive)
-		buf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
+		buf->vb.field = V4L2_FIELD_NONE;
 	else
-		buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+		buf->vb.field = V4L2_FIELD_INTERLACED;
+	v4l2_get_timestamp(&buf->vb.timestamp);
 
-	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
 /*
@@ -914,7 +914,7 @@ buffer_prepare(struct vb2_buffer *vb)
 				__func__, vb2_plane_size(vb, 0), size);
 		return -EINVAL;
 	}
-	vb2_set_plane_payload(&buf->vb, 0, size);
+	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
 
 	return 0;
 }
@@ -995,7 +995,8 @@ static void em28xx_stop_streaming(struct vb2_queue *vq)
 
 	spin_lock_irqsave(&dev->slock, flags);
 	if (dev->usb_ctl.vid_buf != NULL) {
-		vb2_buffer_done(&dev->usb_ctl.vid_buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&dev->usb_ctl.vid_buf->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 		dev->usb_ctl.vid_buf = NULL;
 	}
 	while (!list_empty(&vidq->active)) {
@@ -1003,7 +1004,7 @@ static void em28xx_stop_streaming(struct vb2_queue *vq)
 
 		buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
@@ -1026,7 +1027,8 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
 
 	spin_lock_irqsave(&dev->slock, flags);
 	if (dev->usb_ctl.vbi_buf != NULL) {
-		vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&dev->usb_ctl.vbi_buf->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 		dev->usb_ctl.vbi_buf = NULL;
 	}
 	while (!list_empty(&vbiq->active)) {
@@ -1034,7 +1036,7 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq)
 
 		buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index e6559c6..76bf8ba 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -35,6 +35,7 @@
 #include <linux/kref.h>
 #include <linux/videodev2.h>
 
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
@@ -264,7 +265,7 @@ struct em28xx_fmt {
 /* buffer for one video frame */
 struct em28xx_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 
 	void *mem;
diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c
index 0ab81ec..f0ee44d 100644
--- a/drivers/media/usb/go7007/go7007-driver.c
+++ b/drivers/media/usb/go7007/go7007-driver.c
@@ -386,10 +386,10 @@ start_error:
  */
 static inline void store_byte(struct go7007_buffer *vb, u8 byte)
 {
-	if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) {
-		u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
+	if (vb && vb->vb.vb2_buf.planes[0].bytesused < GO7007_BUF_SIZE) {
+		u8 *ptr = vb2_plane_vaddr(&vb->vb.vb2_buf, 0);
 
-		ptr[vb->vb.v4l2_planes[0].bytesused++] = byte;
+		ptr[vb->vb.vb2_buf.planes[0].bytesused++] = byte;
 	}
 }
 
@@ -401,7 +401,7 @@ static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *v
 			.type = V4L2_EVENT_MOTION_DET,
 			.u.motion_det = {
 				.flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
-				.frame_sequence = vb->vb.v4l2_buf.sequence,
+				.frame_sequence = vb->vb.sequence,
 				.region_mask = motion_regions,
 			},
 		};
@@ -417,7 +417,7 @@ static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *v
  */
 static void go7007_motion_regions(struct go7007 *go, struct go7007_buffer *vb)
 {
-	u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
+	u32 *bytesused = &vb->vb.vb2_buf.planes[0].bytesused;
 	unsigned motion[4] = { 0, 0, 0, 0 };
 	u32 motion_regions = 0;
 	unsigned stride = (go->width + 7) >> 3;
@@ -458,15 +458,15 @@ static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buf
 		go->next_seq++;
 		return vb;
 	}
-	bytesused = &vb->vb.v4l2_planes[0].bytesused;
+	bytesused = &vb->vb.vb2_buf.planes[0].bytesused;
 
-	vb->vb.v4l2_buf.sequence = go->next_seq++;
+	vb->vb.sequence = go->next_seq++;
 	if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE)
 		go7007_motion_regions(go, vb);
 	else
 		go7007_set_motion_regions(go, vb, 0);
 
-	v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
+	v4l2_get_timestamp(&vb->vb.timestamp);
 	vb_tmp = vb;
 	spin_lock(&go->spinlock);
 	list_del(&vb->list);
@@ -476,7 +476,7 @@ static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buf
 		vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
 	go->active_buf = vb;
 	spin_unlock(&go->spinlock);
-	vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
+	vb2_buffer_done(&vb_tmp->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	return vb;
 }
 
@@ -519,9 +519,9 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 	}
 
 	for (i = 0; i < length; ++i) {
-		if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) {
+		if (vb && vb->vb.vb2_buf.planes[0].bytesused >= GO7007_BUF_SIZE - 3) {
 			v4l2_info(&go->v4l2_dev, "dropping oversized frame\n");
-			vb->vb.v4l2_planes[0].bytesused = 0;
+			vb->vb.vb2_buf.planes[0].bytesused = 0;
 			vb->frame_offset = 0;
 			vb->modet_active = 0;
 			vb = go->active_buf = NULL;
@@ -601,7 +601,7 @@ void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 					vb = frame_boundary(go, vb);
 				go->seen_frame = buf[i] == frame_start_code;
 				if (vb && go->seen_frame)
-					vb->frame_offset = vb->vb.v4l2_planes[0].bytesused;
+					vb->frame_offset = vb->vb.vb2_buf.planes[0].bytesused;
 			}
 			/* Handle any special chunk types, or just write the
 			 * start code to the (potentially new) buffer */
diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h
index 9e83bbf..745185e 100644
--- a/drivers/media/usb/go7007/go7007-priv.h
+++ b/drivers/media/usb/go7007/go7007-priv.h
@@ -136,7 +136,7 @@ struct go7007_hpi_ops {
 #define	GO7007_BUF_SIZE		(GO7007_BUF_PAGES << PAGE_SHIFT)
 
 struct go7007_buffer {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 	unsigned int frame_offset;
 	u32 modet_active;
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index c57207e..63d87a2 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -52,7 +52,7 @@ static bool valid_pixelformat(u32 pixelformat)
 
 static u32 get_frame_type_flag(struct go7007_buffer *vb, int format)
 {
-	u8 *ptr = vb2_plane_vaddr(&vb->vb, 0);
+	u8 *ptr = vb2_plane_vaddr(&vb->vb.vb2_buf, 0);
 
 	switch (format) {
 	case V4L2_PIX_FMT_MJPEG:
@@ -386,8 +386,9 @@ static void go7007_buf_queue(struct vb2_buffer *vb)
 {
 	struct vb2_queue *vq = vb->vb2_queue;
 	struct go7007 *go = vb2_get_drv_priv(vq);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct go7007_buffer *go7007_vb =
-		container_of(vb, struct go7007_buffer, vb);
+		container_of(vbuf, struct go7007_buffer, vb);
 	unsigned long flags;
 
 	spin_lock_irqsave(&go->spinlock, flags);
@@ -397,12 +398,13 @@ static void go7007_buf_queue(struct vb2_buffer *vb)
 
 static int go7007_buf_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct go7007_buffer *go7007_vb =
-		container_of(vb, struct go7007_buffer, vb);
+		container_of(vbuf, struct go7007_buffer, vb);
 
 	go7007_vb->modet_active = 0;
 	go7007_vb->frame_offset = 0;
-	vb->v4l2_planes[0].bytesused = 0;
+	vb->planes[0].bytesused = 0;
 	return 0;
 }
 
@@ -410,15 +412,15 @@ static void go7007_buf_finish(struct vb2_buffer *vb)
 {
 	struct vb2_queue *vq = vb->vb2_queue;
 	struct go7007 *go = vb2_get_drv_priv(vq);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct go7007_buffer *go7007_vb =
-		container_of(vb, struct go7007_buffer, vb);
+		container_of(vbuf, struct go7007_buffer, vb);
 	u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format);
-	struct v4l2_buffer *buf = &vb->v4l2_buf;
 
-	buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
+	vbuf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME |
 			V4L2_BUF_FLAG_PFRAME);
-	buf->flags |= frame_type_flag;
-	buf->field = V4L2_FIELD_NONE;
+	vbuf->flags |= frame_type_flag;
+	vbuf->field = V4L2_FIELD_NONE;
 }
 
 static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index fd1fa41..e932f0b 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -85,7 +85,7 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 
 /* intermediate buffers with raw data from the USB device */
 struct hackrf_frame_buf {
-	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+	struct vb2_v4l2_buffer vb;   /* common v4l buffer stuff -- must be first */
 	struct list_head list;
 };
 
@@ -290,10 +290,10 @@ static void hackrf_urb_complete(struct urb *urb)
 		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
 		len = hackrf_convert_stream(dev, ptr, urb->transfer_buffer,
 				urb->actual_length);
-		vb2_set_plane_payload(&fbuf->vb, 0, len);
-		v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
-		fbuf->vb.v4l2_buf.sequence = dev->sequence++;
-		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+		vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, len);
+		v4l2_get_timestamp(&fbuf->vb.timestamp);
+		fbuf->vb.sequence = dev->sequence++;
+		vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	}
 skip:
 	usb_submit_urb(urb, GFP_ATOMIC);
@@ -437,7 +437,7 @@ static void hackrf_cleanup_queued_bufs(struct hackrf_dev *dev)
 		buf = list_entry(dev->queued_bufs.next,
 				struct hackrf_frame_buf, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
 }
@@ -539,7 +539,8 @@ err:
 
 		list_for_each_entry_safe(buf, tmp, &dev->queued_bufs, list) {
 			list_del(&buf->list);
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
+			vb2_buffer_done(&buf->vb.vb2_buf,
+					VB2_BUF_STATE_QUEUED);
 		}
 	}
 
diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c
index 3f276d9..6ba87d0 100644
--- a/drivers/media/usb/msi2500/msi2500.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -112,7 +112,7 @@ static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
 
 /* intermediate buffers with raw data from the USB device */
 struct msi2500_frame_buf {
-	struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+	struct vb2_v4l2_buffer vb;   /* common v4l buffer stuff -- must be first */
 	struct list_head list;
 };
 
@@ -433,8 +433,8 @@ static void msi2500_isoc_handler(struct urb *urb)
 		/* fill framebuffer */
 		ptr = vb2_plane_vaddr(&fbuf->vb, 0);
 		flen = msi2500_convert_stream(dev, ptr, iso_buf, flen);
-		vb2_set_plane_payload(&fbuf->vb, 0, flen);
-		vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+		vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0, flen);
+		vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	}
 
 handler_end:
@@ -569,7 +569,7 @@ static void msi2500_cleanup_queued_bufs(struct msi2500_dev *dev)
 		buf = list_entry(dev->queued_bufs.next,
 				 struct msi2500_frame_buf, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
 }
@@ -641,7 +641,7 @@ static void msi2500_buf_queue(struct vb2_buffer *vb)
 
 	/* Check the device has not disconnected between prep and queuing */
 	if (unlikely(!dev->udev)) {
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		return;
 	}
 
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index 702267e..a33ce99 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -240,9 +240,9 @@ static void pwc_frame_complete(struct pwc_device *pdev)
 			PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
 				       " discarded.\n", fbuf->filled);
 		} else {
-			fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
-			fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
-			vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+			fbuf->vb.field = V4L2_FIELD_NONE;
+			fbuf->vb.sequence = pdev->vframe_count;
+			vb2_buffer_done(&fbuf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 			pdev->fill_buf = NULL;
 			pdev->vsync = 0;
 		}
@@ -287,7 +287,7 @@ static void pwc_isoc_handler(struct urb *urb)
 		{
 			PWC_ERROR("Too many ISOC errors, bailing out.\n");
 			if (pdev->fill_buf) {
-				vb2_buffer_done(&pdev->fill_buf->vb,
+				vb2_buffer_done(&pdev->fill_buf->vb.vb2_buf,
 						VB2_BUF_STATE_ERROR);
 				pdev->fill_buf = NULL;
 			}
@@ -317,7 +317,7 @@ static void pwc_isoc_handler(struct urb *urb)
 
 			if (pdev->vsync == 1) {
 				v4l2_get_timestamp(
-					&fbuf->vb.v4l2_buf.timestamp);
+					&fbuf->vb.timestamp);
 				pdev->vsync = 2;
 			}
 
@@ -520,7 +520,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev,
 		buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf,
 				 list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, state);
+		vb2_buffer_done(&buf->vb.vb2_buf, state);
 	}
 	spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
 }
@@ -594,7 +594,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 
 static int buffer_init(struct vb2_buffer *vb)
 {
-	struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct pwc_frame_buf *buf = container_of(vbuf, struct pwc_frame_buf, vb);
 
 	/* need vmalloc since frame buffer > 128K */
 	buf->data = vzalloc(PWC_FRAME_SIZE);
@@ -618,7 +619,8 @@ static int buffer_prepare(struct vb2_buffer *vb)
 static void buffer_finish(struct vb2_buffer *vb)
 {
 	struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
-	struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct pwc_frame_buf *buf = container_of(vbuf, struct pwc_frame_buf, vb);
 
 	if (vb->state == VB2_BUF_STATE_DONE) {
 		/*
@@ -633,7 +635,8 @@ static void buffer_finish(struct vb2_buffer *vb)
 
 static void buffer_cleanup(struct vb2_buffer *vb)
 {
-	struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct pwc_frame_buf *buf = container_of(vbuf, struct pwc_frame_buf, vb);
 
 	vfree(buf->data);
 }
@@ -641,12 +644,13 @@ static void buffer_cleanup(struct vb2_buffer *vb)
 static void buffer_queue(struct vb2_buffer *vb)
 {
 	struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
-	struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct pwc_frame_buf *buf = container_of(vbuf, struct pwc_frame_buf, vb);
 	unsigned long flags = 0;
 
 	/* Check the device has not disconnected between prep and queuing */
 	if (!pdev->udev) {
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 		return;
 	}
 
@@ -695,7 +699,8 @@ static void stop_streaming(struct vb2_queue *vq)
 
 	pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_ERROR);
 	if (pdev->fill_buf)
-		vb2_buffer_done(&pdev->fill_buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&pdev->fill_buf->vb.vb2_buf,
+				VB2_BUF_STATE_ERROR);
 	mutex_unlock(&pdev->v4l2_lock);
 }
 
diff --git a/drivers/media/usb/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c
index b65903f..58b5518 100644
--- a/drivers/media/usb/pwc/pwc-uncompress.c
+++ b/drivers/media/usb/pwc/pwc-uncompress.c
@@ -40,7 +40,7 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
 	u16 *src;
 	u16 *dsty, *dstu, *dstv;
 
-	image = vb2_plane_vaddr(&fbuf->vb, 0);
+	image = vb2_plane_vaddr(&fbuf->vb.vb2_buf, 0);
 
 	yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
 
@@ -55,12 +55,12 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
 			 * determine this using the type of the webcam */
 		memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
 		memcpy(raw_frame+1, yuv, pdev->frame_size);
-		vb2_set_plane_payload(&fbuf->vb, 0,
-			pdev->frame_size + sizeof(struct pwc_raw_frame));
+		vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0,
+				      pdev->frame_size + sizeof(struct pwc_raw_frame));
 		return 0;
 	}
 
-	vb2_set_plane_payload(&fbuf->vb, 0,
+	vb2_set_plane_payload(&fbuf->vb.vb2_buf, 0,
 			      pdev->width * pdev->height * 3 / 2);
 
 	if (pdev->vbandlength == 0) {
diff --git a/drivers/media/usb/pwc/pwc.h b/drivers/media/usb/pwc/pwc.h
index 81b017a..e0d9125 100644
--- a/drivers/media/usb/pwc/pwc.h
+++ b/drivers/media/usb/pwc/pwc.h
@@ -40,6 +40,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
 #include <linux/input.h>
@@ -210,7 +211,7 @@ struct pwc_raw_frame {
 /* intermediate buffers with raw data from the USB cam */
 struct pwc_frame_buf
 {
-	struct vb2_buffer vb;	/* common v4l buffer stuff -- must be first */
+	struct vb2_v4l2_buffer vb;	/* common v4l buffer stuff -- must be first */
 	struct list_head list;
 	void *data;
 	int filled;		/* number of bytes filled */
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index 0f3c34d..32b5115 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -45,6 +45,7 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/usb.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
@@ -293,7 +294,7 @@ struct s2255_fmt {
 /* buffer for one video frame */
 struct s2255_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
@@ -573,14 +574,14 @@ static void s2255_got_frame(struct s2255_vc *vc, int jpgsize)
 	buf = list_entry(vc->buf_list.next,
 			 struct s2255_buffer, list);
 	list_del(&buf->list);
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-	buf->vb.v4l2_buf.field = vc->field;
-	buf->vb.v4l2_buf.sequence = vc->frame_count;
+	v4l2_get_timestamp(&buf->vb.timestamp);
+	buf->vb.field = vc->field;
+	buf->vb.sequence = vc->frame_count;
 	spin_unlock_irqrestore(&vc->qlock, flags);
 
 	s2255_fillbuff(vc, buf, jpgsize);
 	/* tell v4l buffer was filled */
-	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 	dprintk(dev, 2, "%s: [buf] [%p]\n", __func__, buf);
 }
 
@@ -612,7 +613,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
 {
 	int pos = 0;
 	const char *tmpbuf;
-	char *vbuf = vb2_plane_vaddr(&buf->vb, 0);
+	char *vbuf = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 	unsigned long last_frame;
 	struct s2255_dev *dev = vc->dev;
 
@@ -635,7 +636,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
 			break;
 		case V4L2_PIX_FMT_JPEG:
 		case V4L2_PIX_FMT_MJPEG:
-			vb2_set_plane_payload(&buf->vb, 0, jpgsize);
+			vb2_set_plane_payload(&buf->vb.vb2_buf, 0, jpgsize);
 			memcpy(vbuf, tmpbuf, jpgsize);
 			break;
 		case V4L2_PIX_FMT_YUV422P:
@@ -674,7 +675,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 static int buffer_prepare(struct vb2_buffer *vb)
 {
 	struct s2255_vc *vc = vb2_get_drv_priv(vb->vb2_queue);
-	struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct s2255_buffer *buf = container_of(vbuf, struct s2255_buffer, vb);
 	int w = vc->width;
 	int h = vc->height;
 	unsigned long size;
@@ -696,13 +698,14 @@ static int buffer_prepare(struct vb2_buffer *vb)
 		return -EINVAL;
 	}
 
-	vb2_set_plane_payload(&buf->vb, 0, size);
+	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
 	return 0;
 }
 
 static void buffer_queue(struct vb2_buffer *vb)
 {
-	struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct s2255_buffer *buf = container_of(vbuf, struct s2255_buffer, vb);
 	struct s2255_vc *vc = vb2_get_drv_priv(vb->vb2_queue);
 	unsigned long flags = 0;
 	dprintk(vc->dev, 1, "%s\n", __func__);
@@ -1116,9 +1119,9 @@ static void stop_streaming(struct vb2_queue *vq)
 	spin_lock_irqsave(&vc->qlock, flags);
 	list_for_each_entry_safe(buf, node, &vc->buf_list, list) {
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		dprintk(vc->dev, 2, "[%p/%d] done\n",
-			buf, buf->vb.v4l2_buf.index);
+			buf, buf->vb.vb2_buf.index);
 	}
 	spin_unlock_irqrestore(&vc->qlock, flags);
 }
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index e12b103..10e35e6 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -695,8 +695,9 @@ static void buffer_queue(struct vb2_buffer *vb)
 {
 	unsigned long flags;
 	struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct stk1160_buffer *buf =
-		container_of(vb, struct stk1160_buffer, vb);
+		container_of(vbuf, struct stk1160_buffer, vb);
 
 	spin_lock_irqsave(&dev->buf_lock, flags);
 	if (!dev->udev) {
@@ -704,7 +705,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 		 * If the device is disconnected return the buffer to userspace
 		 * directly. The next QBUF call will fail with -ENODEV.
 		 */
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	} else {
 
 		buf->mem = vb2_plane_vaddr(vb, 0);
@@ -717,7 +718,7 @@ static void buffer_queue(struct vb2_buffer *vb)
 		 * the buffer to userspace directly.
 		 */
 		if (buf->length < dev->width * dev->height * 2)
-			vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		else
 			list_add_tail(&buf->list, &dev->avail_bufs);
 
@@ -769,9 +770,9 @@ void stk1160_clear_queue(struct stk1160 *dev)
 		buf = list_first_entry(&dev->avail_bufs,
 			struct stk1160_buffer, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		stk1160_dbg("buffer [%p/%d] aborted\n",
-			    buf, buf->vb.v4l2_buf.index);
+			    buf, buf->vb.vb2_buf.index);
 	}
 
 	/* It's important to release the current buffer */
@@ -779,9 +780,9 @@ void stk1160_clear_queue(struct stk1160 *dev)
 		buf = dev->isoc_ctl.buf;
 		dev->isoc_ctl.buf = NULL;
 
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		stk1160_dbg("buffer [%p/%d] aborted\n",
-			    buf, buf->vb.v4l2_buf.index);
+			    buf, buf->vb.vb2_buf.index);
 	}
 	spin_unlock_irqrestore(&dev->buf_lock, flags);
 }
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
index 940c3ea..75654e6 100644
--- a/drivers/media/usb/stk1160/stk1160-video.c
+++ b/drivers/media/usb/stk1160/stk1160-video.c
@@ -96,13 +96,13 @@ void stk1160_buffer_done(struct stk1160 *dev)
 {
 	struct stk1160_buffer *buf = dev->isoc_ctl.buf;
 
-	buf->vb.v4l2_buf.sequence = dev->sequence++;
-	buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
-	buf->vb.v4l2_buf.bytesused = buf->bytesused;
-	v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+	buf->vb.sequence = dev->sequence++;
+	buf->vb.field = V4L2_FIELD_INTERLACED;
+	buf->vb.vb2_buf.planes[0].bytesused = buf->bytesused;
+	v4l2_get_timestamp(&buf->vb.timestamp);
 
-	vb2_set_plane_payload(&buf->vb, 0, buf->bytesused);
-	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused);
+	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 
 	dev->isoc_ctl.buf = NULL;
 }
diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h
index 047131b..1ed1cc4 100644
--- a/drivers/media/usb/stk1160/stk1160.h
+++ b/drivers/media/usb/stk1160/stk1160.h
@@ -77,7 +77,7 @@
 /* Buffer for one video frame */
 struct stk1160_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 
 	void *mem;
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index a46766c..ce5d502 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -306,7 +306,7 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk)
 
 	/* First available buffer. */
 	buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list);
-	frame = vb2_plane_vaddr(&buf->vb, 0);
+	frame = vb2_plane_vaddr(&buf->vb.vb2_buf, 0);
 
 	/* Copy the chunk data. */
 	usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd);
@@ -314,17 +314,17 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk)
 
 	/* Last chunk in a frame, signalling an end */
 	if (odd && chunk_no == usbtv->n_chunks-1) {
-		int size = vb2_plane_size(&buf->vb, 0);
+		int size = vb2_plane_size(&buf->vb.vb2_buf, 0);
 		enum vb2_buffer_state state = usbtv->chunks_done ==
 						usbtv->n_chunks ?
 						VB2_BUF_STATE_DONE :
 						VB2_BUF_STATE_ERROR;
 
-		buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
-		buf->vb.v4l2_buf.sequence = usbtv->sequence++;
-		v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
-		vb2_set_plane_payload(&buf->vb, 0, size);
-		vb2_buffer_done(&buf->vb, state);
+		buf->vb.field = V4L2_FIELD_INTERLACED;
+		buf->vb.sequence = usbtv->sequence++;
+		v4l2_get_timestamp(&buf->vb.timestamp);
+		vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
+		vb2_buffer_done(&buf->vb.vb2_buf, state);
 		list_del(&buf->list);
 	}
 
@@ -422,7 +422,7 @@ static void usbtv_stop(struct usbtv *usbtv)
 	while (!list_empty(&usbtv->bufs)) {
 		struct usbtv_buf *buf = list_first_entry(&usbtv->bufs,
 						struct usbtv_buf, list);
-		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 		list_del(&buf->list);
 	}
 	spin_unlock_irqrestore(&usbtv->buflock, flags);
@@ -617,8 +617,9 @@ static int usbtv_queue_setup(struct vb2_queue *vq,
 
 static void usbtv_buf_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct usbtv *usbtv = vb2_get_drv_priv(vb->vb2_queue);
-	struct usbtv_buf *buf = container_of(vb, struct usbtv_buf, vb);
+	struct usbtv_buf *buf = container_of(vbuf, struct usbtv_buf, vb);
 	unsigned long flags;
 
 	if (usbtv->udev == NULL) {
diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h
index 9681195..19cb8bf 100644
--- a/drivers/media/usb/usbtv/usbtv.h
+++ b/drivers/media/usb/usbtv/usbtv.h
@@ -24,6 +24,7 @@
 #include <linux/usb.h>
 
 #include <media/v4l2-device.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 
 /* Hardware. */
@@ -61,7 +62,7 @@ struct usbtv_norm_params {
 
 /* A single videobuf2 frame buffer. */
 struct usbtv_buf {
-	struct vb2_buffer vb;
+	struct vb2_v4l2_buffer vb;
 	struct list_head list;
 };
 
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index f16b9b4..b49bcab 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -20,6 +20,7 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
+#include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 
 #include "uvcvideo.h"
@@ -60,7 +61,7 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue,
 							  queue);
 		list_del(&buf->queue);
 		buf->state = state;
-		vb2_buffer_done(&buf->buf, vb2_state);
+		vb2_buffer_done(&buf->buf.vb2_buf, vb2_state);
 	}
 }
 
@@ -89,10 +90,11 @@ static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 
 static int uvc_buffer_prepare(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
-	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+	struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
 
-	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
 	    vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
 		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
 		return -EINVAL;
@@ -105,7 +107,7 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
 	buf->error = 0;
 	buf->mem = vb2_plane_vaddr(vb, 0);
 	buf->length = vb2_plane_size(vb, 0);
-	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		buf->bytesused = 0;
 	else
 		buf->bytesused = vb2_get_plane_payload(vb, 0);
@@ -115,8 +117,9 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
 
 static void uvc_buffer_queue(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
-	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+	struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
 	unsigned long flags;
 
 	spin_lock_irqsave(&queue->irqlock, flags);
@@ -127,7 +130,7 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
 		 * directly. The next QBUF call will fail with -ENODEV.
 		 */
 		buf->state = UVC_BUF_STATE_ERROR;
-		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 	}
 
 	spin_unlock_irqrestore(&queue->irqlock, flags);
@@ -135,12 +138,13 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
 
 static void uvc_buffer_finish(struct vb2_buffer *vb)
 {
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
 	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
-	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+	struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
 
 	if (vb->state == VB2_BUF_STATE_DONE)
-		uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
+		uvc_video_clock_update(stream, vbuf, buf);
 }
 
 static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count)
@@ -398,7 +402,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
 		buf->error = 0;
 		buf->state = UVC_BUF_STATE_QUEUED;
 		buf->bytesused = 0;
-		vb2_set_plane_payload(&buf->buf, 0, 0);
+		vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
 		return buf;
 	}
 
@@ -412,8 +416,8 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
 	spin_unlock_irqrestore(&queue->irqlock, flags);
 
 	buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
-	vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
-	vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
+	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
 
 	return nextbuf;
 }
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index f839654..4160212 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -606,7 +606,7 @@ static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
  * timestamp of the sliding window to 1s.
  */
 void uvc_video_clock_update(struct uvc_streaming *stream,
-			    struct v4l2_buffer *v4l2_buf,
+			    struct vb2_v4l2_buffer *vbuf,
 			    struct uvc_buffer *buf)
 {
 	struct uvc_clock *clock = &stream->clock;
@@ -696,14 +696,14 @@ void uvc_video_clock_update(struct uvc_streaming *stream,
 		  stream->dev->name,
 		  sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
 		  y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
-		  v4l2_buf->timestamp.tv_sec,
-		  (unsigned long)v4l2_buf->timestamp.tv_usec,
+		  vbuf->timestamp.tv_sec,
+		  (unsigned long)vbuf->timestamp.tv_usec,
 		  x1, first->host_sof, first->dev_sof,
 		  x2, last->host_sof, last->dev_sof, y1, y2);
 
 	/* Update the V4L2 buffer. */
-	v4l2_buf->timestamp.tv_sec = ts.tv_sec;
-	v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+	vbuf->timestamp.tv_sec = ts.tv_sec;
+	vbuf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 
 done:
 	spin_unlock_irqrestore(&stream->clock.lock, flags);
@@ -1029,10 +1029,10 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
 
 		uvc_video_get_ts(&ts);
 
-		buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
-		buf->buf.v4l2_buf.sequence = stream->sequence;
-		buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
-		buf->buf.v4l2_buf.timestamp.tv_usec =
+		buf->buf.field = V4L2_FIELD_NONE;
+		buf->buf.sequence = stream->sequence;
+		buf->buf.timestamp.tv_sec = ts.tv_sec;
+		buf->buf.timestamp.tv_usec =
 			ts.tv_nsec / NSEC_PER_USEC;
 
 		/* TODO: Handle PTS and SCR. */
@@ -1305,7 +1305,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
 		if (buf->bytesused == stream->queue.buf_used) {
 			stream->queue.buf_used = 0;
 			buf->state = UVC_BUF_STATE_READY;
-			buf->buf.v4l2_buf.sequence = ++stream->sequence;
+			buf->buf.sequence = ++stream->sequence;
 			uvc_queue_next_buffer(&stream->queue, buf);
 			stream->last_fid ^= UVC_STREAM_FID;
 		}
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 53e6484..94bc7a8 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -354,7 +354,7 @@ enum uvc_buffer_state {
 };
 
 struct uvc_buffer {
-	struct vb2_buffer buf;
+	struct vb2_v4l2_buffer buf;
 	struct list_head queue;
 
 	enum uvc_buffer_state state;
@@ -673,7 +673,7 @@ extern int uvc_probe_video(struct uvc_streaming *stream,
 extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
 		__u8 intfnum, __u8 cs, void *data, __u16 size);
 void uvc_video_clock_update(struct uvc_streaming *stream,
-			    struct v4l2_buffer *v4l2_buf,
+			    struct vb2_v4l2_buffer *vbuf,
 			    struct uvc_buffer *buf);
 
 /* Status */
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 38703bd..d3b7192 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -773,13 +773,15 @@ EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_release);
  *
  * Call from buf_queue(), videobuf_queue_ops callback.
  */
-void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb)
+void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,
+		struct vb2_v4l2_buffer *vbuf)
 {
-	struct v4l2_m2m_buffer *b = container_of(vb, struct v4l2_m2m_buffer, vb);
+	struct v4l2_m2m_buffer *b = container_of(vbuf,
+				struct v4l2_m2m_buffer, vb);
 	struct v4l2_m2m_queue_ctx *q_ctx;
 	unsigned long flags;
 
-	q_ctx = get_queue_ctx(m2m_ctx, vb->vb2_queue->type);
+	q_ctx = get_queue_ctx(m2m_ctx, vbuf->vb2_buf.vb2_queue->type);
 	if (!q_ctx)
 		return;
 
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
index d617c39..3628938 100644
--- a/drivers/usb/gadget/function/uvc_queue.c
+++ b/drivers/usb/gadget/function/uvc_queue.c
@@ -61,9 +61,10 @@ static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
 static int uvc_buffer_prepare(struct vb2_buffer *vb)
 {
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
-	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
 
-	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
 	    vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
 		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
 		return -EINVAL;
@@ -75,7 +76,7 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
 	buf->state = UVC_BUF_STATE_QUEUED;
 	buf->mem = vb2_plane_vaddr(vb, 0);
 	buf->length = vb2_plane_size(vb, 0);
-	if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		buf->bytesused = 0;
 	else
 		buf->bytesused = vb2_get_plane_payload(vb, 0);
@@ -86,7 +87,8 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
 static void uvc_buffer_queue(struct vb2_buffer *vb)
 {
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
-	struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
 	unsigned long flags;
 
 	spin_lock_irqsave(&queue->irqlock, flags);
@@ -98,7 +100,7 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
 		 * directly. The next QBUF call will fail with -ENODEV.
 		 */
 		buf->state = UVC_BUF_STATE_ERROR;
-		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 	}
 
 	spin_unlock_irqrestore(&queue->irqlock, flags);
@@ -242,7 +244,7 @@ void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
 				       queue);
 		list_del(&buf->queue);
 		buf->state = UVC_BUF_STATE_ERROR;
-		vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
 	/* This must be protected by the irqlock spinlock to avoid race
 	 * conditions between uvc_queue_buffer and the disconnection event that
@@ -314,7 +316,7 @@ struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
 	if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
 	     buf->length != buf->bytesused) {
 		buf->state = UVC_BUF_STATE_QUEUED;
-		vb2_set_plane_payload(&buf->buf, 0, 0);
+		vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
 		return buf;
 	}
 
@@ -325,12 +327,12 @@ struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue,
 	else
 		nextbuf = NULL;
 
-	buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
-	buf->buf.v4l2_buf.sequence = queue->sequence++;
-	v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp);
+	buf->buf.field = V4L2_FIELD_NONE;
+	buf->buf.sequence = queue->sequence++;
+	v4l2_get_timestamp(&buf->buf.timestamp);
 
-	vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
-	vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
+	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
 
 	return nextbuf;
 }
diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h
index 0ffe498..ac461a9 100644
--- a/drivers/usb/gadget/function/uvc_queue.h
+++ b/drivers/usb/gadget/function/uvc_queue.h
@@ -26,7 +26,7 @@ enum uvc_buffer_state {
 };
 
 struct uvc_buffer {
-	struct vb2_buffer buf;
+	struct vb2_v4l2_buffer buf;
 	struct list_head queue;
 
 	enum uvc_buffer_state state;
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index 5c60da9..5a9597d 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -90,7 +90,7 @@ struct v4l2_m2m_ctx {
 };
 
 struct v4l2_m2m_buffer {
-	struct vb2_buffer	vb;
+	struct vb2_v4l2_buffer	vb;
 	struct list_head	list;
 };
 
@@ -105,9 +105,9 @@ void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
 			 struct v4l2_m2m_ctx *m2m_ctx);
 
 static inline void
-v4l2_m2m_buf_done(struct vb2_buffer *buf, enum vb2_buffer_state state)
+v4l2_m2m_buf_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state)
 {
-	vb2_buffer_done(buf, state);
+	vb2_buffer_done(&buf->vb2_buf, state);
 }
 
 int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
@@ -160,7 +160,8 @@ static inline void v4l2_m2m_set_dst_buffered(struct v4l2_m2m_ctx *m2m_ctx,
 
 void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx);
 
-void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb);
+void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,
+			struct vb2_v4l2_buffer *vbuf);
 
 /**
  * v4l2_m2m_num_src_bufs_ready() - return the number of source buffers ready for
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index dbf017b..b015b38 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -202,27 +202,28 @@ DECLARE_EVENT_CLASS(vb2_event_class,
 	),
 
 	TP_fast_assign(
+		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 		__entry->minor = q->owner ? q->owner->vdev->minor : -1;
 		__entry->queued_count = q->queued_count;
 		__entry->owned_by_drv_count =
 			atomic_read(&q->owned_by_drv_count);
-		__entry->index = vb->v4l2_buf.index;
-		__entry->type = vb->v4l2_buf.type;
-		__entry->bytesused = vb->v4l2_planes[0].bytesused;
-		__entry->flags = vb->v4l2_buf.flags;
-		__entry->field = vb->v4l2_buf.field;
-		__entry->timestamp = timeval_to_ns(&vb->v4l2_buf.timestamp);
-		__entry->timecode_type = vb->v4l2_buf.timecode.type;
-		__entry->timecode_flags = vb->v4l2_buf.timecode.flags;
-		__entry->timecode_frames = vb->v4l2_buf.timecode.frames;
-		__entry->timecode_seconds = vb->v4l2_buf.timecode.seconds;
-		__entry->timecode_minutes = vb->v4l2_buf.timecode.minutes;
-		__entry->timecode_hours = vb->v4l2_buf.timecode.hours;
-		__entry->timecode_userbits0 = vb->v4l2_buf.timecode.userbits[0];
-		__entry->timecode_userbits1 = vb->v4l2_buf.timecode.userbits[1];
-		__entry->timecode_userbits2 = vb->v4l2_buf.timecode.userbits[2];
-		__entry->timecode_userbits3 = vb->v4l2_buf.timecode.userbits[3];
-		__entry->sequence = vb->v4l2_buf.sequence;
+		__entry->index = vb->index;
+		__entry->type = vb->type;
+		__entry->bytesused = vb->planes[0].bytesused;
+		__entry->flags = vbuf->flags;
+		__entry->field = vbuf->field;
+		__entry->timestamp = timeval_to_ns(&vbuf->timestamp);
+		__entry->timecode_type = vbuf->timecode.type;
+		__entry->timecode_flags = vbuf->timecode.flags;
+		__entry->timecode_frames = vbuf->timecode.frames;
+		__entry->timecode_seconds = vbuf->timecode.seconds;
+		__entry->timecode_minutes = vbuf->timecode.minutes;
+		__entry->timecode_hours = vbuf->timecode.hours;
+		__entry->timecode_userbits0 = vbuf->timecode.userbits[0];
+		__entry->timecode_userbits1 = vbuf->timecode.userbits[1];
+		__entry->timecode_userbits2 = vbuf->timecode.userbits[2];
+		__entry->timecode_userbits3 = vbuf->timecode.userbits[3];
+		__entry->sequence = vbuf->sequence;
 	),
 
 	TP_printk("minor = %d, queued = %u, owned_by_drv = %d, index = %u, "
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH v3 4/5] media: videobuf2: Change queue_setup argument
  2015-08-26 11:59 [RFC PATCH v3 0/5] Refactoring Videobuf2 for common use Junghak Sung
                   ` (2 preceding siblings ...)
  2015-08-26 11:59 ` [RFC PATCH v3 3/5] media: videobuf2: Modify all device drivers Junghak Sung
@ 2015-08-26 11:59 ` Junghak Sung
  2015-08-27 10:45   ` Mauro Carvalho Chehab
  2015-08-26 11:59 ` [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts Junghak Sung
  4 siblings, 1 reply; 23+ messages in thread
From: Junghak Sung @ 2015-08-26 11:59 UTC (permalink / raw)
  To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, jh1009.sung, rany.kwon

Replace struct v4l2_format * with void * to make queue_setup()
for common use.
And then, modify all device drivers related with this change.

Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
 drivers/input/touchscreen/sur40.c                  |    3 ++-
 drivers/media/dvb-frontends/rtl2832_sdr.c          |    2 +-
 drivers/media/pci/cobalt/cobalt-v4l2.c             |    3 ++-
 drivers/media/pci/cx23885/cx23885-417.c            |    2 +-
 drivers/media/pci/cx23885/cx23885-dvb.c            |    2 +-
 drivers/media/pci/cx23885/cx23885-vbi.c            |    2 +-
 drivers/media/pci/cx23885/cx23885-video.c          |    2 +-
 drivers/media/pci/cx25821/cx25821-video.c          |    3 ++-
 drivers/media/pci/cx88/cx88-blackbird.c            |    2 +-
 drivers/media/pci/cx88/cx88-dvb.c                  |    2 +-
 drivers/media/pci/cx88/cx88-vbi.c                  |    2 +-
 drivers/media/pci/cx88/cx88-video.c                |    2 +-
 drivers/media/pci/dt3155/dt3155.c                  |    3 ++-
 drivers/media/pci/netup_unidvb/netup_unidvb_core.c |    2 +-
 drivers/media/pci/saa7134/saa7134-ts.c             |    2 +-
 drivers/media/pci/saa7134/saa7134-vbi.c            |    2 +-
 drivers/media/pci/saa7134/saa7134-video.c          |    2 +-
 drivers/media/pci/saa7134/saa7134.h                |    2 +-
 drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c     |    2 +-
 drivers/media/pci/solo6x10/solo6x10-v4l2.c         |    2 +-
 drivers/media/pci/sta2x11/sta2x11_vip.c            |    2 +-
 drivers/media/pci/tw68/tw68-video.c                |    3 ++-
 drivers/media/platform/am437x/am437x-vpfe.c        |    3 ++-
 drivers/media/platform/blackfin/bfin_capture.c     |    3 ++-
 drivers/media/platform/coda/coda-common.c          |    2 +-
 drivers/media/platform/davinci/vpbe_display.c      |    3 ++-
 drivers/media/platform/davinci/vpif_capture.c      |    3 ++-
 drivers/media/platform/davinci/vpif_display.c      |    3 ++-
 drivers/media/platform/exynos-gsc/gsc-m2m.c        |    2 +-
 drivers/media/platform/exynos4-is/fimc-capture.c   |    3 ++-
 drivers/media/platform/exynos4-is/fimc-isp-video.c |    3 ++-
 drivers/media/platform/exynos4-is/fimc-lite.c      |    3 ++-
 drivers/media/platform/exynos4-is/fimc-m2m.c       |    2 +-
 drivers/media/platform/m2m-deinterlace.c           |    2 +-
 drivers/media/platform/marvell-ccic/mcam-core.c    |    3 ++-
 drivers/media/platform/mx2_emmaprp.c               |    2 +-
 drivers/media/platform/omap3isp/ispvideo.c         |    2 +-
 drivers/media/platform/rcar_jpu.c                  |    3 ++-
 drivers/media/platform/s3c-camif/camif-capture.c   |    3 ++-
 drivers/media/platform/s5p-g2d/g2d.c               |    2 +-
 drivers/media/platform/s5p-jpeg/jpeg-core.c        |    2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c       |    2 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c       |    2 +-
 drivers/media/platform/s5p-tv/mixer_video.c        |    2 +-
 drivers/media/platform/sh_veu.c                    |    3 ++-
 drivers/media/platform/sh_vou.c                    |    3 ++-
 drivers/media/platform/soc_camera/atmel-isi.c      |    2 +-
 drivers/media/platform/soc_camera/mx2_camera.c     |    3 ++-
 drivers/media/platform/soc_camera/mx3_camera.c     |    3 ++-
 drivers/media/platform/soc_camera/rcar_vin.c       |    3 ++-
 .../platform/soc_camera/sh_mobile_ceu_camera.c     |    6 ++++--
 drivers/media/platform/sti/bdisp/bdisp-v4l2.c      |    3 ++-
 drivers/media/platform/ti-vpe/vpe.c                |    2 +-
 drivers/media/platform/vim2m.c                     |    3 ++-
 drivers/media/platform/vivid/vivid-sdr-cap.c       |    2 +-
 drivers/media/platform/vivid/vivid-vbi-cap.c       |    2 +-
 drivers/media/platform/vivid/vivid-vbi-out.c       |    2 +-
 drivers/media/platform/vivid/vivid-vid-cap.c       |    3 ++-
 drivers/media/platform/vivid/vivid-vid-out.c       |    3 ++-
 drivers/media/platform/vsp1/vsp1_video.c           |    3 ++-
 drivers/media/platform/xilinx/xilinx-dma.c         |    3 ++-
 drivers/media/usb/airspy/airspy.c                  |    2 +-
 drivers/media/usb/au0828/au0828-vbi.c              |    3 ++-
 drivers/media/usb/au0828/au0828-video.c            |    3 ++-
 drivers/media/usb/em28xx/em28xx-vbi.c              |    3 ++-
 drivers/media/usb/em28xx/em28xx-video.c            |    3 ++-
 drivers/media/usb/go7007/go7007-v4l2.c             |    2 +-
 drivers/media/usb/hackrf/hackrf.c                  |    2 +-
 drivers/media/usb/msi2500/msi2500.c                |    2 +-
 drivers/media/usb/pwc/pwc-if.c                     |    2 +-
 drivers/media/usb/s2255/s2255drv.c                 |    2 +-
 drivers/media/usb/stk1160/stk1160-v4l.c            |    2 +-
 drivers/media/usb/usbtv/usbtv-video.c              |    3 ++-
 drivers/media/usb/uvc/uvc_queue.c                  |    3 ++-
 drivers/staging/media/davinci_vpfe/vpfe_video.c    |    2 +-
 drivers/staging/media/omap4iss/iss_video.c         |    2 +-
 drivers/usb/gadget/function/uvc_queue.c            |    2 +-
 include/media/videobuf2-core.h                     |    2 +-
 78 files changed, 114 insertions(+), 79 deletions(-)

diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index 8d0b6f0..767ddc8 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -643,10 +643,11 @@ static void sur40_disconnect(struct usb_interface *interface)
  * minimum number: many DMA engines need a minimum of 2 buffers in the
  * queue and you need to have another available for userspace processing.
  */
-static int sur40_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int sur40_queue_setup(struct vb2_queue *q, const void *parg,
 		       unsigned int *nbuffers, unsigned int *nplanes,
 		       unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct sur40_state *sur40 = vb2_get_drv_priv(q);
 
 	if (q->num_buffers + *nbuffers < 3)
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 3501215..7d884c5 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -488,7 +488,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
 
 /* Videobuf2 operations */
 static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
-		const struct v4l2_format *fmt, unsigned int *nbuffers,
+		const void *parg, unsigned int *nbuffers,
 		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq);
diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c
index e72480a..0c083b3 100644
--- a/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -44,10 +44,11 @@ static const struct v4l2_dv_timings cea1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
 /* vb2 DMA streaming ops */
 
 static int cobalt_queue_setup(struct vb2_queue *q,
-			const struct v4l2_format *fmt,
+			const void *parg,
 			unsigned int *num_buffers, unsigned int *num_planes,
 			unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct cobalt_stream *s = q->drv_priv;
 	unsigned size = s->stride * s->height;
 
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index 316a322..88a3afb 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1138,7 +1138,7 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 09ad512..c4307ad 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -92,7 +92,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
index 6c9bb03..cf3cb13 100644
--- a/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -121,7 +121,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev    *dev,
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index b6a193d..71a80e2 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -315,7 +315,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
 	return 0;
 }
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index f1deb8f..69ee134 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -141,10 +141,11 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
 	return handled;
 }
 
-static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int cx25821_queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct cx25821_channel *chan = q->drv_priv;
 	unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3;
 
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index 49d0b7c..8b88913 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -637,7 +637,7 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index f0923fb..f048350 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -82,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 1d65543..007a5ee 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -107,7 +107,7 @@ int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index c6a337a..f3b12db 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -429,7 +429,7 @@ static int restart_video_queue(struct cx8800_dev    *dev,
 
 /* ------------------------------------------------------------------ */
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c
index f27a858..d041526 100644
--- a/drivers/media/pci/dt3155/dt3155.c
+++ b/drivers/media/pci/dt3155/dt3155.c
@@ -131,11 +131,12 @@ static int wait_i2c_reg(void __iomem *addr)
 }
 
 static int
-dt3155_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+dt3155_queue_setup(struct vb2_queue *vq, const void *parg,
 		unsigned int *nbuffers, unsigned int *num_planes,
 		unsigned int sizes[], void *alloc_ctxs[])
 
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct dt3155_priv *pd = vb2_get_drv_priv(vq);
 	unsigned size = pd->width * pd->height;
 
diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
index b012aa65..f0d5a40 100644
--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -279,7 +279,7 @@ static irqreturn_t netup_unidvb_isr(int irq, void *dev_id)
 }
 
 static int netup_unidvb_queue_setup(struct vb2_queue *vq,
-				    const struct v4l2_format *fmt,
+				    const void *parg,
 				    unsigned int *nbuffers,
 				    unsigned int *nplanes,
 				    unsigned int sizes[],
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index b0ef37d..7fb5ee7 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -116,7 +116,7 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
 }
 EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
 
-int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index fb1605e..6271b0e 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -138,7 +138,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
 				    saa7134_buffer_startpage(buf));
 }
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 602d53d..518086c 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -904,7 +904,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
 				    saa7134_buffer_startpage(buf));
 }
 
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index 002ba1d8..984e81d 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -819,7 +819,7 @@ void saa7134_video_fini(struct saa7134_dev *dev);
 
 int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
 int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
-int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[]);
 int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count);
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index fb71f2f..b79fc6f 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -659,7 +659,7 @@ static int solo_ring_thread(void *data)
 }
 
 static int solo_enc_queue_setup(struct vb2_queue *q,
-				const struct v4l2_format *fmt,
+				const void *parg,
 				unsigned int *num_buffers,
 				unsigned int *num_planes, unsigned int sizes[],
 				void *alloc_ctxs[])
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
index 63ae8a6..d2c9a83 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -311,7 +311,7 @@ static void solo_stop_thread(struct solo_dev *solo_dev)
 	solo_dev->kthread = NULL;
 }
 
-static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int solo_queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index 8fe6ea6..7a8e4b4 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -265,7 +265,7 @@ static void vip_active_buf_next(struct sta2x11_vip *vip)
 
 
 /* Videobuf2 Operations */
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned int *nbuffers, unsigned int *nplanes,
 		       unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index ae06535..85ad311 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -376,10 +376,11 @@ static int tw68_buffer_count(unsigned int size, unsigned int count)
 /* ------------------------------------------------------------- */
 /* vb2 queue operations                                          */
 
-static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+static int tw68_queue_setup(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct tw68_dev *dev = vb2_get_drv_priv(q);
 	unsigned tot_bufs = q->num_buffers + *num_buffers;
 
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index 85649ca..5ef5a1e 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -1907,10 +1907,11 @@ static void vpfe_calculate_offsets(struct vpfe_device *vpfe)
  * the buffer count and buffer size
  */
 static int vpfe_queue_setup(struct vb2_queue *vq,
-			    const struct v4l2_format *fmt,
+			    const void *parg,
 			    unsigned int *nbuffers, unsigned int *nplanes,
 			    unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct vpfe_device *vpfe = vb2_get_drv_priv(vq);
 
 	if (fmt && fmt->fmt.pix.sizeimage < vpfe->fmt.fmt.pix.sizeimage)
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index 4bb3208..2dc2351 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -202,10 +202,11 @@ static void bcap_free_sensor_formats(struct bcap_device *bcap_dev)
 }
 
 static int bcap_queue_setup(struct vb2_queue *vq,
-				const struct v4l2_format *fmt,
+				const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct bcap_device *bcap_dev = vb2_get_drv_priv(vq);
 
 	if (fmt && fmt->fmt.pix.sizeimage < bcap_dev->fmt.sizeimage)
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 6e0c9be..be63ab9 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -1132,7 +1132,7 @@ static void set_default_params(struct coda_ctx *ctx)
  * Queue operations
  */
 static int coda_queue_setup(struct vb2_queue *vq,
-				const struct v4l2_format *fmt,
+				const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index f69cdd7..5798247 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -228,11 +228,12 @@ static int vpbe_buffer_prepare(struct vb2_buffer *vb)
  * This function allocates memory for the buffers
  */
 static int
-vpbe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+vpbe_buffer_queue_setup(struct vb2_queue *vq, const void *parg,
 			unsigned int *nbuffers, unsigned int *nplanes,
 			unsigned int sizes[], void *alloc_ctxs[])
 
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	/* Get the file handle object and layer object */
 	struct vpbe_layer *layer = vb2_get_drv_priv(vq);
 	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index d7ddc7d..f8a7338 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -112,10 +112,11 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
  * the buffer count and buffer size
  */
 static int vpif_buffer_queue_setup(struct vb2_queue *vq,
-				const struct v4l2_format *fmt,
+				const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct channel_obj *ch = vb2_get_drv_priv(vq);
 	struct common_obj *common;
 
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index f641bc0..5df9b1e 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -107,10 +107,11 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
  * the buffer count and buffer size
  */
 static int vpif_buffer_queue_setup(struct vb2_queue *vq,
-				const struct v4l2_format *fmt,
+				const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct channel_obj *ch = vb2_get_drv_priv(vq);
 	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index d5cffef..d967f17 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -212,7 +212,7 @@ put_device:
 }
 
 static int gsc_m2m_queue_setup(struct vb2_queue *vq,
-			const struct v4l2_format *fmt,
+			const void *parg,
 			unsigned int *num_buffers, unsigned int *num_planes,
 			unsigned int sizes[], void *allocators[])
 {
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index 3844d6c..fd545a0 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -344,10 +344,11 @@ int fimc_capture_resume(struct fimc_dev *fimc)
 
 }
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned int *num_buffers, unsigned int *num_planes,
 		       unsigned int sizes[], void *allocators[])
 {
+	struct v4l2_format *pfmt = (struct v4l2_format *)parg;
 	const struct v4l2_pix_format_mplane *pixm = NULL;
 	struct fimc_ctx *ctx = vq->drv_priv;
 	struct fimc_frame *frame = &ctx->d_frame;
diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
index 195f9b5..4b583ed 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
+++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
@@ -39,10 +39,11 @@
 #include "fimc-is-param.h"
 
 static int isp_video_capture_queue_setup(struct vb2_queue *vq,
-			const struct v4l2_format *pfmt,
+			const void *parg,
 			unsigned int *num_buffers, unsigned int *num_planes,
 			unsigned int sizes[], void *allocators[])
 {
+	struct v4l2_format *pfmt = (struct v4l2_format *)parg;
 	struct fimc_isp *isp = vb2_get_drv_priv(vq);
 	struct v4l2_pix_format_mplane *vid_fmt = &isp->video_capture.pixfmt;
 	const struct v4l2_pix_format_mplane *pixm = NULL;
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index 21527cf..fdb4fcf 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -360,10 +360,11 @@ static void stop_streaming(struct vb2_queue *q)
 	fimc_lite_stop_capture(fimc, false);
 }
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned int *num_buffers, unsigned int *num_planes,
 		       unsigned int sizes[], void *allocators[])
 {
+	struct v4l2_format *pfmt = (struct v4l2_format *)parg;
 	const struct v4l2_pix_format_mplane *pixm = NULL;
 	struct fimc_lite *fimc = vq->drv_priv;
 	struct flite_frame *frame = &fimc->out_frame;
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
index 9c27335..bd72ab3 100644
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -176,7 +176,7 @@ static void fimc_job_abort(void *priv)
 	fimc_m2m_shutdown(priv);
 }
 
-static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int fimc_queue_setup(struct vb2_queue *vq, const void *parg,
 			    unsigned int *num_buffers, unsigned int *num_planes,
 			    unsigned int sizes[], void *allocators[])
 {
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index bdd8f11..29973f9 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -798,7 +798,7 @@ struct vb2_dc_conf {
 };
 
 static int deinterlace_queue_setup(struct vb2_queue *vq,
-				const struct v4l2_format *fmt,
+				const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 1d95842..fb9615b 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1049,10 +1049,11 @@ static int mcam_read_setup(struct mcam_camera *cam)
  */
 
 static int mcam_vb_queue_setup(struct vb2_queue *vq,
-		const struct v4l2_format *fmt, unsigned int *nbufs,
+		const void *parg, unsigned int *nbufs,
 		unsigned int *num_planes, unsigned int sizes[],
 		void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct mcam_camera *cam = vb2_get_drv_priv(vq);
 	int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2;
 
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
index 87314b7..0a4c336 100644
--- a/drivers/media/platform/mx2_emmaprp.c
+++ b/drivers/media/platform/mx2_emmaprp.c
@@ -689,7 +689,7 @@ static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = {
  * Queue operations
  */
 static int emmaprp_queue_setup(struct vb2_queue *vq,
-				const struct v4l2_format *fmt,
+				const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index 08c9f62..3aa61e8 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -320,7 +320,7 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
  */
 
 static int isp_video_queue_setup(struct vb2_queue *queue,
-				 const struct v4l2_format *fmt,
+				 const void *parg,
 				 unsigned int *count, unsigned int *num_planes,
 				 unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c
index 18e62d0..935eadb 100644
--- a/drivers/media/platform/rcar_jpu.c
+++ b/drivers/media/platform/rcar_jpu.c
@@ -1015,10 +1015,11 @@ error_free:
  * ============================================================================
  */
 static int jpu_queue_setup(struct vb2_queue *vq,
-			   const struct v4l2_format *fmt,
+			   const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct jpu_ctx *ctx = vb2_get_drv_priv(vq);
 	struct jpu_q_data *q_data;
 	unsigned int i;
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index dc67c4ec..8573922 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -441,10 +441,11 @@ static void stop_streaming(struct vb2_queue *vq)
 	camif_stop_capture(vp);
 }
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned int *num_buffers, unsigned int *num_planes,
 		       unsigned int sizes[], void *allocators[])
 {
+	struct v4l2_format *pfmt = (struct v4l2_format *)parg;
 	const struct v4l2_pix_format *pix = NULL;
 	struct camif_vp *vp = vb2_get_drv_priv(vq);
 	struct camif_dev *camif = vp->camif;
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index 81483da..b11497f 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -101,7 +101,7 @@ static struct g2d_frame *get_frame(struct g2d_ctx *ctx,
 	}
 }
 
-static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int g2d_queue_setup(struct vb2_queue *vq, const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 5b1861b..b89976e 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -2120,7 +2120,7 @@ static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
  */
 
 static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
-			   const struct v4l2_format *fmt,
+			   const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 2fd59e7..8443cb3 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -883,7 +883,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
 };
 
 static int s5p_mfc_queue_setup(struct vb2_queue *vq,
-			const struct v4l2_format *fmt, unsigned int *buf_count,
+			const void *parg, unsigned int *buf_count,
 			unsigned int *plane_count, unsigned int psize[],
 			void *allocators[])
 {
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index e42014c..c94f6d2 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -1812,7 +1812,7 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
 }
 
 static int s5p_mfc_queue_setup(struct vb2_queue *vq,
-			const struct v4l2_format *fmt,
+			const void *parg,
 			unsigned int *buf_count, unsigned int *plane_count,
 			unsigned int psize[], void *allocators[])
 {
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index 5347a6c..6117045 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -881,7 +881,7 @@ static const struct v4l2_file_operations mxr_fops = {
 	.unlocked_ioctl = video_ioctl2,
 };
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 	unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[],
 	void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index 6455cb9..461099e 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -865,10 +865,11 @@ static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = {
 		/* ========== Queue operations ========== */
 
 static int sh_veu_queue_setup(struct vb2_queue *vq,
-			      const struct v4l2_format *f,
+			      const void *parg,
 			      unsigned int *nbuffers, unsigned int *nplanes,
 			      unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *f = (struct v4l2_format *)parg;
 	struct sh_veu_dev *veu = vb2_get_drv_priv(vq);
 	struct sh_veu_vfmt *vfmt;
 	unsigned int size, count = *nbuffers;
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index 7014f2e..e624ada 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -241,10 +241,11 @@ static void sh_vou_stream_config(struct sh_vou_device *vou_dev)
 }
 
 /* Locking: caller holds fop_lock mutex */
-static int sh_vou_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int sh_vou_queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned int *nbuffers, unsigned int *nplanes,
 		       unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq);
 	struct v4l2_pix_format *pix = &vou_dev->pix;
 	int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8;
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 6b312a4..f604114 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -235,7 +235,7 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset)
 /* ------------------------------------------------------------------
 	Videobuf operations
    ------------------------------------------------------------------*/
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index f4398bb..e07e1ec 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -469,10 +469,11 @@ static void mx2_camera_clock_stop(struct soc_camera_host *ici)
  *  Videobuf operations
  */
 static int mx2_videobuf_setup(struct vb2_queue *vq,
-			const struct v4l2_format *fmt,
+			const void *parg,
 			unsigned int *count, unsigned int *num_planes,
 			unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx2_camera_dev *pcdev = ici->priv;
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index dcd7dc1..16ad897 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -185,10 +185,11 @@ static void mx3_cam_dma_done(void *arg)
  * Calculate the __buffer__ (not data) size and number of buffers.
  */
 static int mx3_videobuf_setup(struct vb2_queue *vq,
-			const struct v4l2_format *fmt,
+			const void *parg,
 			unsigned int *count, unsigned int *num_planes,
 			unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index cd45fa9..b983361 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -527,11 +527,12 @@ struct rcar_vin_cam {
  * required
  */
 static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
-				   const struct v4l2_format *fmt,
+				   const void *parg,
 				   unsigned int *count,
 				   unsigned int *num_planes,
 				   unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct rcar_vin_priv *priv = ici->priv;
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 161b614..ac68c55 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -210,11 +210,13 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev)
  *		  for the current frame format if required
  */
 static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
-			const struct v4l2_format *fmt,
+			const void *parg,
 			unsigned int *count, unsigned int *num_planes,
 			unsigned int sizes[], void *alloc_ctxs[])
 {
-	struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
+	struct soc_camera_device *icd = container_of(vq,
+			struct soc_camera_device, vb2_vidq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
 
diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
index df61355..5bb3354 100644
--- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
+++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
@@ -438,10 +438,11 @@ static void bdisp_ctrls_delete(struct bdisp_ctx *ctx)
 }
 
 static int bdisp_queue_setup(struct vb2_queue *vq,
-			     const struct v4l2_format *fmt,
+			     const void *parg,
 			     unsigned int *nb_buf, unsigned int *nb_planes,
 			     unsigned int sizes[], void *allocators[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct bdisp_ctx *ctx = vb2_get_drv_priv(vq);
 	struct bdisp_frame *frame = ctx_get_frame(ctx, vq->type);
 
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index d82c2f2..22f820c 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -1798,7 +1798,7 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = {
  * Queue operations
  */
 static int vpe_queue_setup(struct vb2_queue *vq,
-			   const struct v4l2_format *fmt,
+			   const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 295fde5..fad0ac9 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -710,10 +710,11 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
  */
 
 static int vim2m_queue_setup(struct vb2_queue *vq,
-				const struct v4l2_format *fmt,
+				const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct vim2m_ctx *ctx = vb2_get_drv_priv(vq);
 	struct vim2m_q_data *q_data;
 	unsigned int size, count = *nbuffers;
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index bae5b8a..a5ff809 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -210,7 +210,7 @@ static int vivid_thread_sdr_cap(void *data)
 	return 0;
 }
 
-static int sdr_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int sdr_cap_queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned *nbuffers, unsigned *nplanes,
 		       unsigned sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
index 73e9c0b..83aee19 100644
--- a/drivers/media/platform/vivid/vivid-vbi-cap.c
+++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
@@ -135,7 +135,7 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *bu
 	buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
 }
 
-static int vbi_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_cap_queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned *nbuffers, unsigned *nplanes,
 		       unsigned sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c
index 1333f96..055cef6 100644
--- a/drivers/media/platform/vivid/vivid-vbi-out.c
+++ b/drivers/media/platform/vivid/vivid-vbi-out.c
@@ -27,7 +27,7 @@
 #include "vivid-vbi-out.h"
 #include "vivid-vbi-cap.h"
 
-static int vbi_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_out_queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned *nbuffers, unsigned *nplanes,
 		       unsigned sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 4572709..79fc026 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -95,10 +95,11 @@ static const struct v4l2_discrete_probe webcam_probe = {
 	VIVID_WEBCAM_SIZES
 };
 
-static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vid_cap_queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned *nbuffers, unsigned *nplanes,
 		       unsigned sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct vivid_dev *dev = vb2_get_drv_priv(vq);
 	unsigned buffers = tpg_g_buffers(&dev->tpg);
 	unsigned h = dev->fmt_cap_rect.height;
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index 73c8f97..fe9a72d 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -31,10 +31,11 @@
 #include "vivid-kthread-out.h"
 #include "vivid-vid-out.h"
 
-static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vid_out_queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned *nbuffers, unsigned *nplanes,
 		       unsigned sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct vivid_dev *dev = vb2_get_drv_priv(vq);
 	const struct vivid_fmt *vfmt = dev->fmt_out;
 	unsigned planes = vfmt->buffers;
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 5837bc1..a1d8892 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -787,10 +787,11 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
  */
 
 static int
-vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+vsp1_video_queue_setup(struct vb2_queue *vq, const void *parg,
 		     unsigned int *nbuffers, unsigned int *nplanes,
 		     unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct vsp1_video *video = vb2_get_drv_priv(vq);
 	const struct v4l2_pix_format_mplane *format;
 	struct v4l2_pix_format_mplane pix_mp;
diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
index 3b6112e..bd9c29b 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -309,10 +309,11 @@ static void xvip_dma_complete(void *param)
 }
 
 static int
-xvip_dma_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+xvip_dma_queue_setup(struct vb2_queue *vq, const void *parg,
 		     unsigned int *nbuffers, unsigned int *nplanes,
 		     unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct xvip_dma *dma = vb2_get_drv_priv(vq);
 
 	/* Make sure the image size is large enough. */
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
index bc45104..e346619 100644
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -486,7 +486,7 @@ static void airspy_disconnect(struct usb_interface *intf)
 
 /* Videobuf2 operations */
 static int airspy_queue_setup(struct vb2_queue *vq,
-		const struct v4l2_format *fmt, unsigned int *nbuffers,
+		const void *parg, unsigned int *nbuffers,
 		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct airspy *s = vb2_get_drv_priv(vq);
diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c
index 44d1d46..d4ae272 100644
--- a/drivers/media/usb/au0828/au0828-vbi.c
+++ b/drivers/media/usb/au0828/au0828-vbi.c
@@ -30,10 +30,11 @@
 
 /* ------------------------------------------------------------------ */
 
-static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_queue_setup(struct vb2_queue *vq, const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct au0828_dev *dev = vb2_get_drv_priv(vq);
 	unsigned long img_size = dev->vbi_width * dev->vbi_height * 2;
 	unsigned long size;
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 065b9c8..6b6e772 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -638,10 +638,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
 	return rc;
 }
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned int *nbuffers, unsigned int *nplanes,
 		       unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct au0828_dev *dev = vb2_get_drv_priv(vq);
 	unsigned long img_size = dev->height * dev->bytesperline;
 	unsigned long size;
diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
index a4d7f41..db76cf1 100644
--- a/drivers/media/usb/em28xx/em28xx-vbi.c
+++ b/drivers/media/usb/em28xx/em28xx-vbi.c
@@ -31,10 +31,11 @@
 
 /* ------------------------------------------------------------------ */
 
-static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int vbi_queue_setup(struct vb2_queue *vq, const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct em28xx *dev = vb2_get_drv_priv(vq);
 	struct em28xx_v4l2 *v4l2 = dev->v4l2;
 	unsigned long size;
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index 5b6fdd2..a7f034c 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -871,10 +871,11 @@ static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
 	Videobuf2 operations
    ------------------------------------------------------------------*/
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned int *nbuffers, unsigned int *nplanes,
 		       unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct em28xx *dev = vb2_get_drv_priv(vq);
 	struct em28xx_v4l2 *v4l2 = dev->v4l2;
 	unsigned long size;
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index 63d87a2..f3d187d 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -369,7 +369,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 }
 
 static int go7007_queue_setup(struct vb2_queue *q,
-		const struct v4l2_format *fmt,
+		const void *parg,
 		unsigned int *num_buffers, unsigned int *num_planes,
 		unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index e932f0b..458514d 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -464,7 +464,7 @@ static void hackrf_disconnect(struct usb_interface *intf)
 
 /* Videobuf2 operations */
 static int hackrf_queue_setup(struct vb2_queue *vq,
-		const struct v4l2_format *fmt, unsigned int *nbuffers,
+		const void *parg, unsigned int *nbuffers,
 		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
 	struct hackrf_dev *dev = vb2_get_drv_priv(vq);
diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c
index 6ba87d0..9345a84 100644
--- a/drivers/media/usb/msi2500/msi2500.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -614,7 +614,7 @@ static int msi2500_querycap(struct file *file, void *fh,
 
 /* Videobuf2 operations */
 static int msi2500_queue_setup(struct vb2_queue *vq,
-			       const struct v4l2_format *fmt,
+			       const void *parg,
 			       unsigned int *nbuffers,
 			       unsigned int *nplanes, unsigned int sizes[],
 			       void *alloc_ctxs[])
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index a33ce99..30d0957 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -571,7 +571,7 @@ static void pwc_video_release(struct v4l2_device *v)
 /***************************************************************************/
 /* Videobuf2 operations */
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index 32b5115..e7acb12 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -660,7 +660,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
    Videobuf operations
    ------------------------------------------------------------------*/
 
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 		       unsigned int *nbuffers, unsigned int *nplanes,
 		       unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index 10e35e6..0bd34f1 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -664,7 +664,7 @@ static const struct v4l2_ioctl_ops stk1160_ioctl_ops = {
 /*
  * Videobuf2 operations
  */
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt,
+static int queue_setup(struct vb2_queue *vq, const void *parg,
 				unsigned int *nbuffers, unsigned int *nplanes,
 				unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index ce5d502..9116289 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -599,9 +599,10 @@ static struct v4l2_file_operations usbtv_fops = {
 };
 
 static int usbtv_queue_setup(struct vb2_queue *vq,
-	const struct v4l2_format *fmt, unsigned int *nbuffers,
+	const void *parg, unsigned int *nbuffers,
 	unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct usbtv *usbtv = vb2_get_drv_priv(vq);
 	unsigned size = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
 
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index b49bcab..bccb2da 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -69,10 +69,11 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue,
  * videobuf2 queue operations
  */
 
-static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
+	struct v4l2_format *fmt = (struct v4l2_format *)parg;
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
 	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
 
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 87048a1..c7de69b 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -1078,7 +1078,7 @@ vpfe_g_dv_timings(struct file *file, void *fh,
  * the buffer nbuffers and buffer size
  */
 static int
-vpfe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+vpfe_buffer_queue_setup(struct vb2_queue *vq, const void *parg,
 			unsigned int *nbuffers, unsigned int *nplanes,
 			unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
index 40405d8..1cb307a 100644
--- a/drivers/staging/media/omap4iss/iss_video.c
+++ b/drivers/staging/media/omap4iss/iss_video.c
@@ -288,7 +288,7 @@ iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh)
  */
 
 static int iss_video_queue_setup(struct vb2_queue *vq,
-				 const struct v4l2_format *fmt,
+				 const void *parg,
 				 unsigned int *count, unsigned int *num_planes,
 				 unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
index 3628938..51d4a17 100644
--- a/drivers/usb/gadget/function/uvc_queue.c
+++ b/drivers/usb/gadget/function/uvc_queue.c
@@ -41,7 +41,7 @@
  * videobuf2 queue operations
  */
 
-static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
 			   unsigned int *nbuffers, unsigned int *nplanes,
 			   unsigned int sizes[], void *alloc_ctxs[])
 {
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 8787a6c..09d7529 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -312,7 +312,7 @@ struct vb2_buffer {
  *			pre-queued buffers before calling STREAMON.
  */
 struct vb2_ops {
-	int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
+	int (*queue_setup)(struct vb2_queue *q, const void *parg,
 			   unsigned int *num_buffers, unsigned int *num_planes,
 			   unsigned int sizes[], void *alloc_ctxs[]);
 
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts
  2015-08-26 11:59 [RFC PATCH v3 0/5] Refactoring Videobuf2 for common use Junghak Sung
                   ` (3 preceding siblings ...)
  2015-08-26 11:59 ` [RFC PATCH v3 4/5] media: videobuf2: Change queue_setup argument Junghak Sung
@ 2015-08-26 11:59 ` Junghak Sung
  2015-08-27 11:43   ` Mauro Carvalho Chehab
  2015-08-28 13:50   ` Hans Verkuil
  4 siblings, 2 replies; 23+ messages in thread
From: Junghak Sung @ 2015-08-26 11:59 UTC (permalink / raw)
  To: linux-media, mchehab, hverkuil, laurent.pinchart, sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, jh1009.sung, rany.kwon

Divide videobuf2-core into core part and v4l2-specific part
- core part: videobuf2 core related with buffer management & memory
 allocation
- v4l2-specific part: v4l2-specific stuff

Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
---
 drivers/media/v4l2-core/videobuf2-core.c     | 1933 +++-----------------------
 drivers/media/v4l2-core/videobuf2-internal.h |  184 +++
 drivers/media/v4l2-core/videobuf2-v4l2.c     | 1640 ++++++++++++++++++++++
 include/media/videobuf2-core.h               |  157 +--
 include/media/videobuf2-v4l2.h               |  116 ++
 include/trace/events/v4l2.h                  |    4 +-
 6 files changed, 2154 insertions(+), 1880 deletions(-)
 create mode 100644 drivers/media/v4l2-core/videobuf2-internal.h

diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 9266d50..2cd4241 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -6,9 +6,6 @@
  * Author: Pawel Osciak <pawel@osciak.com>
  *	   Marek Szyprowski <m.szyprowski@samsung.com>
  *
- * The vb2_thread implementation was based on code from videobuf-dvb.c:
- *	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation.
@@ -24,164 +21,14 @@
 #include <linux/freezer.h>
 #include <linux/kthread.h>
 
-#include <media/v4l2-dev.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-common.h>
-#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-core.h>
+#include "videobuf2-internal.h"
 
 #include <trace/events/v4l2.h>
 
-static int debug;
-module_param(debug, int, 0644);
-
-#define dprintk(level, fmt, arg...)					\
-	do {								\
-		if (debug >= level)					\
-			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
-	} while (0)
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-
-/*
- * If advanced debugging is on, then count how often each op is called
- * successfully, which can either be per-buffer or per-queue.
- *
- * This makes it easy to check that the 'init' and 'cleanup'
- * (and variations thereof) stay balanced.
- */
-
-#define log_memop(vb, op)						\
-	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
-		(vb)->vb2_queue, (vb)->index, #op,			\
-		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
-
-#define call_memop(vb, op, args...)					\
-({									\
-	struct vb2_queue *_q = (vb)->vb2_queue;				\
-	int err;							\
-									\
-	log_memop(vb, op);						\
-	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
-	if (!err)							\
-		(vb)->cnt_mem_ ## op++;					\
-	err;								\
-})
-
-#define call_ptr_memop(vb, op, args...)					\
-({									\
-	struct vb2_queue *_q = (vb)->vb2_queue;				\
-	void *ptr;							\
-									\
-	log_memop(vb, op);						\
-	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
-	if (!IS_ERR_OR_NULL(ptr))					\
-		(vb)->cnt_mem_ ## op++;					\
-	ptr;								\
-})
-
-#define call_void_memop(vb, op, args...)				\
-({									\
-	struct vb2_queue *_q = (vb)->vb2_queue;				\
-									\
-	log_memop(vb, op);						\
-	if (_q->mem_ops->op)						\
-		_q->mem_ops->op(args);					\
-	(vb)->cnt_mem_ ## op++;						\
-})
-
-#define log_qop(q, op)							\
-	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
-		(q)->ops->op ? "" : " (nop)")
-
-#define call_qop(q, op, args...)					\
-({									\
-	int err;							\
-									\
-	log_qop(q, op);							\
-	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
-	if (!err)							\
-		(q)->cnt_ ## op++;					\
-	err;								\
-})
-
-#define call_void_qop(q, op, args...)					\
-({									\
-	log_qop(q, op);							\
-	if ((q)->ops->op)						\
-		(q)->ops->op(args);					\
-	(q)->cnt_ ## op++;						\
-})
-
-#define log_vb_qop(vb, op, args...)					\
-	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
-		(vb)->vb2_queue, (vb)->index, #op,			\
-		(vb)->vb2_queue->ops->op ? "" : " (nop)")
-
-#define call_vb_qop(vb, op, args...)					\
-({									\
-	int err;							\
-									\
-	log_vb_qop(vb, op);						\
-	err = (vb)->vb2_queue->ops->op ?				\
-		(vb)->vb2_queue->ops->op(args) : 0;			\
-	if (!err)							\
-		(vb)->cnt_ ## op++;					\
-	err;								\
-})
-
-#define call_void_vb_qop(vb, op, args...)				\
-({									\
-	log_vb_qop(vb, op);						\
-	if ((vb)->vb2_queue->ops->op)					\
-		(vb)->vb2_queue->ops->op(args);				\
-	(vb)->cnt_ ## op++;						\
-})
-
-#else
-
-#define call_memop(vb, op, args...)					\
-	((vb)->vb2_queue->mem_ops->op ?					\
-		(vb)->vb2_queue->mem_ops->op(args) : 0)
-
-#define call_ptr_memop(vb, op, args...)					\
-	((vb)->vb2_queue->mem_ops->op ?					\
-		(vb)->vb2_queue->mem_ops->op(args) : NULL)
-
-#define call_void_memop(vb, op, args...)				\
-	do {								\
-		if ((vb)->vb2_queue->mem_ops->op)			\
-			(vb)->vb2_queue->mem_ops->op(args);		\
-	} while (0)
-
-#define call_qop(q, op, args...)					\
-	((q)->ops->op ? (q)->ops->op(args) : 0)
-
-#define call_void_qop(q, op, args...)					\
-	do {								\
-		if ((q)->ops->op)					\
-			(q)->ops->op(args);				\
-	} while (0)
-
-#define call_vb_qop(vb, op, args...)					\
-	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
-
-#define call_void_vb_qop(vb, op, args...)				\
-	do {								\
-		if ((vb)->vb2_queue->ops->op)				\
-			(vb)->vb2_queue->ops->op(args);			\
-	} while (0)
-
-#endif
-
-/* Flags that are set by the vb2 core */
-#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
-				 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
-				 V4L2_BUF_FLAG_PREPARED | \
-				 V4L2_BUF_FLAG_TIMESTAMP_MASK)
-/* Output buffer flags that should be passed on to the driver */
-#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
-				 V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
+int vb2_debug;
+module_param_named(debug, vb2_debug, int, 0644);
+EXPORT_SYMBOL_GPL(vb2_debug);
 
 static void __vb2_queue_cancel(struct vb2_queue *q);
 static void __enqueue_in_driver(struct vb2_buffer *vb);
@@ -193,7 +40,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
 {
 	struct vb2_queue *q = vb->vb2_queue;
 	enum dma_data_direction dma_dir =
-		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+			q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 	void *mem_priv;
 	int plane;
 
@@ -249,7 +96,8 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
 
 	for (plane = 0; plane < vb->num_planes; ++plane) {
 		if (vb->planes[plane].mem_priv)
-			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
+			call_void_memop(vb, put_userptr,
+					vb->planes[plane].mem_priv);
 		vb->planes[plane].mem_priv = NULL;
 	}
 }
@@ -347,7 +195,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
  *
  * Returns the number of buffers successfully allocated.
  */
-static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
+static int __vb2_queue_alloc(struct vb2_queue *q, unsigned int memory,
 			unsigned int num_buffers, unsigned int num_planes)
 {
 	unsigned int buffer;
@@ -370,7 +218,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
 		vb->memory = memory;
 
 		/* Allocate video buffer memory for the MMAP type */
-		if (memory == V4L2_MEMORY_MMAP) {
+		if (memory == VB2_MEMORY_MMAP) {
 			ret = __vb2_buf_mem_alloc(vb);
 			if (ret) {
 				dprintk(1, "failed allocating memory for "
@@ -397,7 +245,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
 	}
 
 	__setup_lengths(q, buffer);
-	if (memory == V4L2_MEMORY_MMAP)
+	if (memory == VB2_MEMORY_MMAP)
 		__setup_offsets(q, buffer);
 
 	dprintk(1, "allocated %d buffers, %d plane(s) each\n",
@@ -421,9 +269,9 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
 			continue;
 
 		/* Free MMAP buffers or release USERPTR buffers */
-		if (q->memory == V4L2_MEMORY_MMAP)
+		if (q->memory == VB2_MEMORY_MMAP)
 			__vb2_buf_mem_free(vb);
-		else if (q->memory == V4L2_MEMORY_DMABUF)
+		else if (q->memory == VB2_MEMORY_DMABUF)
 			__vb2_buf_dmabuf_put(vb);
 		else
 			__vb2_buf_userptr_put(vb);
@@ -547,75 +395,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
 }
 
 /**
- * __verify_planes_array() - verify that the planes array passed in struct
- * v4l2_buffer from userspace can be safely used
- */
-static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
-{
-	if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
-		return 0;
-
-	/* Is memory for copying plane information present? */
-	if (NULL == b->m.planes) {
-		dprintk(1, "multi-planar buffer passed but "
-			   "planes array not provided\n");
-		return -EINVAL;
-	}
-
-	if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
-		dprintk(1, "incorrect planes array length, "
-			   "expected %d, got %d\n", vb->num_planes, b->length);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- * __verify_length() - Verify that the bytesused value for each plane fits in
- * the plane length and that the data offset doesn't exceed the bytesused value.
- */
-static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
-{
-	unsigned int length;
-	unsigned int bytesused;
-	unsigned int plane;
-
-	if (!V4L2_TYPE_IS_OUTPUT(b->type))
-		return 0;
-
-	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
-		for (plane = 0; plane < vb->num_planes; ++plane) {
-			length = (b->memory == V4L2_MEMORY_USERPTR ||
-				b->memory == V4L2_MEMORY_DMABUF)
-				? b->m.planes[plane].length
-				: vb->planes[plane].length;
-			bytesused = b->m.planes[plane].bytesused
-				? b->m.planes[plane].bytesused : length;
-
-			if (b->m.planes[plane].bytesused > length)
-				return -EINVAL;
-
-			if (b->m.planes[plane].data_offset > 0 &&
-				b->m.planes[plane].data_offset >= bytesused)
-				return -EINVAL;
-		}
-	} else {
-		length = (b->memory == V4L2_MEMORY_USERPTR)
-			? b->length : vb->planes[0].length;
-
-		if (b->bytesused > length)
-			return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- * __buffer_in_use() - return true if the buffer is in use and
+ * vb2_buffer_in_use() - return true if the buffer is in use and
  * the queue cannot be freed (by the means of REQBUFS(0)) call
  */
-static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
+bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
 {
 	unsigned int plane;
 	for (plane = 0; plane < vb->num_planes; ++plane) {
@@ -631,6 +414,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
 	}
 	return false;
 }
+EXPORT_SYMBOL_GPL(vb2_buffer_in_use);
 
 /**
  * __buffers_in_use() - return true if any buffers on the queue are in use and
@@ -640,142 +424,26 @@ static bool __buffers_in_use(struct vb2_queue *q)
 {
 	unsigned int buffer;
 	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
-		if (__buffer_in_use(q, q->bufs[buffer]))
+		if (vb2_buffer_in_use(q, q->bufs[buffer]))
 			return true;
 	}
 	return false;
 }
 
 /**
- * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
- * returned to userspace
- */
-static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
-{
-	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-	struct vb2_queue *q = vb->vb2_queue;
-	unsigned int plane;
-
-	/* Copy back data such as timestamp, flags, etc. */
-	b->index = vb->index;
-	b->type = vb->type;
-	b->memory = vb->memory;
-	b->bytesused = 0;
-
-	b->flags = vbuf->flags;
-	b->field = vbuf->field;
-	b->timestamp = vbuf->timestamp;
-	b->timecode = vbuf->timecode;
-	b->sequence = vbuf->sequence;
-
-	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
-		/*
-		 * Fill in plane-related data if userspace provided an array
-		 * for it. The caller has already verified memory and size.
-		 */
-		b->length = vb->num_planes;
-		for (plane = 0; plane < vb->num_planes; ++plane) {
-			struct v4l2_plane *pdst = &b->m.planes[plane];
-			struct vb2_plane *psrc = &vb->planes[plane];
-
-			pdst->bytesused = psrc->bytesused;
-			pdst->length = psrc->length;
-			if (q->memory == V4L2_MEMORY_MMAP)
-				pdst->m.mem_offset = psrc->m.offset;
-			else if (q->memory == V4L2_MEMORY_USERPTR)
-				pdst->m.userptr = psrc->m.userptr;
-			else if (q->memory == V4L2_MEMORY_DMABUF)
-				pdst->m.fd = psrc->m.fd;
-			pdst->data_offset = psrc->data_offset;
-		}
-	} else {
-		/*
-		 * We use length and offset in v4l2_planes array even for
-		 * single-planar buffers, but userspace does not.
-		 */
-		b->length = vb->planes[0].length;
-		b->bytesused = vb->planes[0].bytesused;
-		if (q->memory == V4L2_MEMORY_MMAP)
-			b->m.offset = vb->planes[0].m.offset;
-		else if (q->memory == V4L2_MEMORY_USERPTR)
-			b->m.userptr = vb->planes[0].m.userptr;
-		else if (q->memory == V4L2_MEMORY_DMABUF)
-			b->m.fd = vb->planes[0].m.fd;
-	}
-
-	/*
-	 * Clear any buffer state related flags.
-	 */
-	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
-	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
-	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
-			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
-		/*
-		 * For non-COPY timestamps, drop timestamp source bits
-		 * and obtain the timestamp source from the queue.
-		 */
-		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-	}
-
-	switch (vb->state) {
-	case VB2_BUF_STATE_QUEUED:
-	case VB2_BUF_STATE_ACTIVE:
-		b->flags |= V4L2_BUF_FLAG_QUEUED;
-		break;
-	case VB2_BUF_STATE_ERROR:
-		b->flags |= V4L2_BUF_FLAG_ERROR;
-		/* fall through */
-	case VB2_BUF_STATE_DONE:
-		b->flags |= V4L2_BUF_FLAG_DONE;
-		break;
-	case VB2_BUF_STATE_PREPARED:
-		b->flags |= V4L2_BUF_FLAG_PREPARED;
-		break;
-	case VB2_BUF_STATE_PREPARING:
-	case VB2_BUF_STATE_DEQUEUED:
-		/* nothing */
-		break;
-	}
-
-	if (__buffer_in_use(q, vb))
-		b->flags |= V4L2_BUF_FLAG_MAPPED;
-}
-
-/**
- * vb2_querybuf() - query video buffer information
+ * vb2_core_querybuf() - query video buffer information
  * @q:		videobuf queue
+ * @index:	id number of the buffer
  * @b:		buffer struct passed from userspace to vidioc_querybuf handler
  *		in driver
- *
- * Should be called from vidioc_querybuf ioctl handler in driver.
- * This function will verify the passed v4l2_buffer structure and fill the
- * relevant information for the userspace.
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_querybuf handler in driver.
  */
-int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
+int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
 {
-	struct vb2_buffer *vb;
-	int ret;
-
-	if (b->type != q->type) {
-		dprintk(1, "wrong buffer type\n");
-		return -EINVAL;
-	}
+	call_bufop(q, fill_user_buffer, q->bufs[index], pb);
 
-	if (b->index >= q->num_buffers) {
-		dprintk(1, "buffer index out of range\n");
-		return -EINVAL;
-	}
-	vb = q->bufs[b->index];
-	ret = __verify_planes_array(vb, b);
-	if (!ret)
-		__fill_v4l2_buffer(vb, b);
-	return ret;
+	return 0;
 }
-EXPORT_SYMBOL(vb2_querybuf);
+EXPORT_SYMBOL_GPL(vb2_core_querybuf);
 
 /**
  * __verify_userptr_ops() - verify that all memory operations required for
@@ -818,14 +486,14 @@ static int __verify_dmabuf_ops(struct vb2_queue *q)
 }
 
 /**
- * __verify_memory_type() - Check whether the memory type and buffer type
+ * vb2_verify_memory_type() - Check whether the memory type and buffer type
  * passed to a buffer operation are compatible with the queue.
  */
-static int __verify_memory_type(struct vb2_queue *q,
-		enum v4l2_memory memory, enum v4l2_buf_type type)
+int vb2_verify_memory_type(struct vb2_queue *q,
+		unsigned int memory, unsigned int type)
 {
-	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
-			memory != V4L2_MEMORY_DMABUF) {
+	if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
+		memory != VB2_MEMORY_DMABUF) {
 		dprintk(1, "unsupported memory type\n");
 		return -EINVAL;
 	}
@@ -839,37 +507,30 @@ static int __verify_memory_type(struct vb2_queue *q,
 	 * Make sure all the required memory ops for given memory type
 	 * are available.
 	 */
-	if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
+	if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
 		dprintk(1, "MMAP for current setup unsupported\n");
 		return -EINVAL;
 	}
 
-	if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
+	if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
 		dprintk(1, "USERPTR for current setup unsupported\n");
 		return -EINVAL;
 	}
 
-	if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
+	if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
 		dprintk(1, "DMABUF for current setup unsupported\n");
 		return -EINVAL;
 	}
 
-	/*
-	 * Place the busy tests at the end: -EBUSY can be ignored when
-	 * create_bufs is called with count == 0, but count == 0 should still
-	 * do the memory and type validation.
-	 */
-	if (vb2_fileio_is_active(q)) {
-		dprintk(1, "file io in progress\n");
-		return -EBUSY;
-	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(vb2_verify_memory_type);
 
 /**
- * __reqbufs() - Initiate streaming
+ * vb2_core_reqbufs() - Initiate streaming
  * @q:		videobuf2 queue
- * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
+ * @memory:
+ * @count:
  *
  * Should be called from vidioc_reqbufs ioctl handler of a driver.
  * This function:
@@ -889,7 +550,8 @@ static int __verify_memory_type(struct vb2_queue *q,
  * The return values from this function are intended to be directly returned
  * from vidioc_reqbufs handler in driver.
  */
-static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
+int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
+		unsigned int *count)
 {
 	unsigned int num_buffers, allocated_buffers, num_planes = 0;
 	int ret;
@@ -899,13 +561,13 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
 		return -EBUSY;
 	}
 
-	if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
+	if (*count == 0 || q->num_buffers != 0 || q->memory != memory) {
 		/*
 		 * We already have buffers allocated, so first check if they
 		 * are not in use and can be freed.
 		 */
 		mutex_lock(&q->mmap_lock);
-		if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) {
+		if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
 			mutex_unlock(&q->mmap_lock);
 			dprintk(1, "memory in use, cannot free\n");
 			return -EBUSY;
@@ -926,18 +588,18 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
 		 * In case of REQBUFS(0) return immediately without calling
 		 * driver's queue_setup() callback and allocating resources.
 		 */
-		if (req->count == 0)
+		if (*count == 0)
 			return 0;
 	}
 
 	/*
 	 * Make sure the requested values and current defaults are sane.
 	 */
-	num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
+	num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME);
 	num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed);
 	memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
 	memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
-	q->memory = req->memory;
+	q->memory = memory;
 
 	/*
 	 * Ask the driver how many buffers and planes per buffer it requires.
@@ -949,7 +611,8 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
 		return ret;
 
 	/* Finally, allocate buffers and video memory */
-	allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
+	allocated_buffers =
+		__vb2_queue_alloc(q, memory, num_buffers, num_planes);
 	if (allocated_buffers == 0) {
 		dprintk(1, "memory allocation failed\n");
 		return -ENOMEM;
@@ -998,28 +661,15 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
 	 * Return the number of successfully allocated buffers
 	 * to the userspace.
 	 */
-	req->count = allocated_buffers;
-	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
+	*count = allocated_buffers;
+	q->waiting_for_buffers = !q->is_output;
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
 
 /**
- * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and
- * type values.
- * @q:		videobuf2 queue
- * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
- */
-int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
-{
-	int ret = __verify_memory_type(q, req->memory, req->type);
-
-	return ret ? ret : __reqbufs(q, req);
-}
-EXPORT_SYMBOL_GPL(vb2_reqbufs);
-
-/**
- * __create_bufs() - Allocate buffers and any required auxiliary structs
+ * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs
  * @q:		videobuf2 queue
  * @create:	creation parameters, passed from userspace to vidioc_create_bufs
  *		handler in driver
@@ -1033,12 +683,13 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs);
  * The return values from this function are intended to be directly returned
  * from vidioc_create_bufs handler in driver.
  */
-static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
+int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
+		unsigned int *count, void *parg)
 {
 	unsigned int num_planes = 0, num_buffers, allocated_buffers;
 	int ret;
 
-	if (q->num_buffers == VIDEO_MAX_FRAME) {
+	if (q->num_buffers == VB2_MAX_FRAME) {
 		dprintk(1, "maximum number of buffers already allocated\n");
 		return -ENOBUFS;
 	}
@@ -1046,23 +697,23 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
 	if (!q->num_buffers) {
 		memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
 		memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
-		q->memory = create->memory;
-		q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
+		q->memory = memory;
+		q->waiting_for_buffers = !q->is_output;
 	}
 
-	num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
+	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
 
 	/*
 	 * Ask the driver, whether the requested number of buffers, planes per
 	 * buffer and their sizes are acceptable
 	 */
-	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+	ret = call_qop(q, queue_setup, q, parg, &num_buffers,
 			&num_planes, q->plane_sizes, q->alloc_ctx);
 	if (ret)
 		return ret;
 
 	/* Finally, allocate buffers and video memory */
-	allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers,
+	allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
 				num_planes);
 	if (allocated_buffers == 0) {
 		dprintk(1, "memory allocation failed\n");
@@ -1079,7 +730,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
 		 * q->num_buffers contains the total number of buffers, that the
 		 * queue driver has set up
 		 */
-		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
+		ret = call_qop(q, queue_setup, q, parg, &num_buffers,
 				&num_planes, q->plane_sizes, q->alloc_ctx);
 
 		if (!ret && allocated_buffers < num_buffers)
@@ -1109,28 +760,11 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
 	 * Return the number of successfully allocated buffers
 	 * to the userspace.
 	 */
-	create->count = allocated_buffers;
+	*count = allocated_buffers;
 
 	return 0;
 }
-
-/**
- * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the
- * memory and type values.
- * @q:		videobuf2 queue
- * @create:	creation parameters, passed from userspace to vidioc_create_bufs
- *		handler in driver
- */
-int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
-{
-	int ret = __verify_memory_type(q, create->memory, create->format.type);
-
-	create->index = q->num_buffers;
-	if (create->count == 0)
-		return ret != -EBUSY ? ret : 0;
-	return ret ? ret : __create_bufs(q, create);
-}
-EXPORT_SYMBOL_GPL(vb2_create_bufs);
+EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
 
 /**
  * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
@@ -1263,7 +897,7 @@ void vb2_discard_done(struct vb2_queue *q)
 }
 EXPORT_SYMBOL_GPL(vb2_discard_done);
 
-static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
+void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
 {
 	static bool __check_once __read_mostly;
 
@@ -1279,162 +913,34 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
 	else
 		pr_warn_once("use the actual size instead.\n");
 }
-
-/**
- * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
- * v4l2_buffer by the userspace. The caller has already verified that struct
- * v4l2_buffer has a valid number of planes.
- */
-static void __fill_vb2_buffer(struct vb2_buffer *vb,
-		const struct v4l2_buffer *b, struct vb2_plane *planes)
-{
-	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-	unsigned int plane;
-
-	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
-		if (b->memory == V4L2_MEMORY_USERPTR) {
-			for (plane = 0; plane < vb->num_planes; ++plane) {
-				planes[plane].m.userptr =
-					b->m.planes[plane].m.userptr;
-				planes[plane].length =
-					b->m.planes[plane].length;
-			}
-		}
-		if (b->memory == V4L2_MEMORY_DMABUF) {
-			for (plane = 0; plane < vb->num_planes; ++plane) {
-				planes[plane].m.fd =
-					b->m.planes[plane].m.fd;
-				planes[plane].length =
-					b->m.planes[plane].length;
-			}
-		}
-
-		/* Fill in driver-provided information for OUTPUT types */
-		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
-			/*
-			 * Will have to go up to b->length when API starts
-			 * accepting variable number of planes.
-			 *
-			 * If bytesused == 0 for the output buffer, then fall
-			 * back to the full buffer size. In that case
-			 * userspace clearly never bothered to set it and
-			 * it's a safe assumption that they really meant to
-			 * use the full plane sizes.
-			 *
-			 * Some drivers, e.g. old codec drivers, use bytesused == 0
-			 * as a way to indicate that streaming is finished.
-			 * In that case, the driver should use the
-			 * allow_zero_bytesused flag to keep old userspace
-			 * applications working.
-			 */
-			for (plane = 0; plane < vb->num_planes; ++plane) {
-				struct vb2_plane *pdst = &planes[plane];
-				struct v4l2_plane *psrc = &b->m.planes[plane];
-
-				if (psrc->bytesused == 0)
-					vb2_warn_zero_bytesused(vb);
-
-				if (vb->vb2_queue->allow_zero_bytesused)
-					pdst->bytesused = psrc->bytesused;
-				else
-					pdst->bytesused = psrc->bytesused ?
-						psrc->bytesused : pdst->length;
-				pdst->data_offset = psrc->data_offset;
-			}
-		}
-	} else {
-		/*
-		 * Single-planar buffers do not use planes array,
-		 * so fill in relevant v4l2_buffer struct fields instead.
-		 * In videobuf we use our internal V4l2_planes struct for
-		 * single-planar buffers as well, for simplicity.
-		 *
-		 * If bytesused == 0 for the output buffer, then fall back
-		 * to the full buffer size as that's a sensible default.
-		 *
-		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
-		 * a way to indicate that streaming is finished. In that case,
-		 * the driver should use the allow_zero_bytesused flag to keep
-		 * old userspace applications working.
-		 */
-		if (b->memory == V4L2_MEMORY_USERPTR) {
-			planes[0].m.userptr = b->m.userptr;
-			planes[0].length = b->length;
-		}
-
-		if (b->memory == V4L2_MEMORY_DMABUF) {
-			planes[0].m.fd = b->m.fd;
-			planes[0].length = b->length;
-		}
-
-		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
-			if (b->bytesused == 0)
-				vb2_warn_zero_bytesused(vb);
-
-			if (vb->vb2_queue->allow_zero_bytesused)
-				planes[0].bytesused = b->bytesused;
-			else
-				planes[0].bytesused = b->bytesused ?
-					b->bytesused : planes[0].length;
-		} else
-			planes[0].bytesused = 0;
-
-	}
-
-	/* Zero flags that the vb2 core handles */
-	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
-	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
-			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
-			!V4L2_TYPE_IS_OUTPUT(b->type)) {
-		/*
-		 * Non-COPY timestamps and non-OUTPUT queues will get
-		 * their timestamp and timestamp source flags from the
-		 * queue.
-		 */
-		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-	}
-
-	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
-		/*
-		 * For output buffers mask out the timecode flag:
-		 * this will be handled later in vb2_internal_qbuf().
-		 * The 'field' is valid metadata for this output buffer
-		 * and so that needs to be copied here.
-		 */
-		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
-		vbuf->field = b->field;
-	} else {
-		/* Zero any output buffer flags as this is a capture buffer */
-		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
-	}
-}
+EXPORT_SYMBOL_GPL(vb2_warn_zero_bytesused);
 
 /**
  * __qbuf_mmap() - handle qbuf of an MMAP buffer
  */
-static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __qbuf_mmap(struct vb2_buffer *vb, void *pb)
 {
-	__fill_vb2_buffer(vb, b, vb->planes);
+	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, vb->planes);
 	return call_vb_qop(vb, buf_prepare, vb);
 }
 
 /**
  * __qbuf_userptr() - handle qbuf of a USERPTR buffer
  */
-static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __qbuf_userptr(struct vb2_buffer *vb, void *pb)
 {
-	struct vb2_plane planes[VIDEO_MAX_PLANES];
+	struct vb2_plane planes[VB2_MAX_PLANES];
 	struct vb2_queue *q = vb->vb2_queue;
 	void *mem_priv;
 	unsigned int plane;
 	int ret;
 	enum dma_data_direction dma_dir =
-		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 	bool reacquired = vb->planes[0].mem_priv == NULL;
 
 	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
 	/* Copy relevant information provided by the userspace */
-	__fill_vb2_buffer(vb, b, planes);
+	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
 
 	for (plane = 0; plane < vb->num_planes; ++plane) {
 		/* Skip the plane if already verified */
@@ -1462,7 +968,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 				reacquired = true;
 				call_void_vb_qop(vb, buf_cleanup, vb);
 			}
-			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
+			call_void_memop(vb, put_userptr,
+					vb->planes[plane].mem_priv);
 		}
 
 		vb->planes[plane].mem_priv = NULL;
@@ -1533,20 +1040,20 @@ err:
 /**
  * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
  */
-static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __qbuf_dmabuf(struct vb2_buffer *vb, void *pb)
 {
-	struct vb2_plane planes[VIDEO_MAX_PLANES];
+	struct vb2_plane planes[VB2_MAX_PLANES];
 	struct vb2_queue *q = vb->vb2_queue;
 	void *mem_priv;
 	unsigned int plane;
 	int ret;
 	enum dma_data_direction dma_dir =
-		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 	bool reacquired = vb->planes[0].mem_priv == NULL;
 
 	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
 	/* Copy relevant information provided by the userspace */
-	__fill_vb2_buffer(vb, b, planes);
+	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
 
 	for (plane = 0; plane < vb->num_planes; ++plane) {
 		struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
@@ -1591,9 +1098,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 		vb->planes[plane].data_offset = 0;
 
 		/* Acquire each plane's memory */
-		mem_priv = call_ptr_memop(vb, attach_dmabuf,
-			q->alloc_ctx[plane], dbuf, planes[plane].length,
-			dma_dir);
+		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
+			dbuf, planes[plane].length, dma_dir);
 		if (IS_ERR(mem_priv)) {
 			dprintk(1, "failed to attach dmabuf\n");
 			ret = PTR_ERR(mem_priv);
@@ -1626,7 +1132,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	for (plane = 0; plane < vb->num_planes; ++plane) {
 		vb->planes[plane].bytesused = planes[plane].bytesused;
 		vb->planes[plane].length = planes[plane].length;
-		vb->planes[plane].m.fd = planes[plane].m.userptr;
+		vb->planes[plane].m.fd = planes[plane].m.fd;
 		vb->planes[plane].data_offset = planes[plane].data_offset;
 	}
 
@@ -1677,52 +1183,27 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
 	call_void_vb_qop(vb, buf_queue, vb);
 }
 
-static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+static int __buf_prepare(struct vb2_buffer *vb, void *pb)
 {
-	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct vb2_queue *q = vb->vb2_queue;
 	int ret;
 
-	ret = __verify_length(vb, b);
-	if (ret < 0) {
-		dprintk(1, "plane parameters verification failed: %d\n", ret);
-		return ret;
-	}
-	if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) {
-		/*
-		 * If the format's field is ALTERNATE, then the buffer's field
-		 * should be either TOP or BOTTOM, not ALTERNATE since that
-		 * makes no sense. The driver has to know whether the
-		 * buffer represents a top or a bottom field in order to
-		 * program any DMA correctly. Using ALTERNATE is wrong, since
-		 * that just says that it is either a top or a bottom field,
-		 * but not which of the two it is.
-		 */
-		dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
-		return -EINVAL;
-	}
-
 	if (q->error) {
 		dprintk(1, "fatal error occurred on queue\n");
 		return -EIO;
 	}
 
-	vb->state = VB2_BUF_STATE_PREPARING;
-	vbuf->timestamp.tv_sec = 0;
-	vbuf->timestamp.tv_usec = 0;
-	vbuf->sequence = 0;
-
 	switch (q->memory) {
-	case V4L2_MEMORY_MMAP:
-		ret = __qbuf_mmap(vb, b);
+	case VB2_MEMORY_MMAP:
+		ret = __qbuf_mmap(vb, pb);
 		break;
-	case V4L2_MEMORY_USERPTR:
+	case VB2_MEMORY_USERPTR:
 		down_read(&current->mm->mmap_sem);
-		ret = __qbuf_userptr(vb, b);
+		ret = __qbuf_userptr(vb, pb);
 		up_read(&current->mm->mmap_sem);
 		break;
-	case V4L2_MEMORY_DMABUF:
-		ret = __qbuf_dmabuf(vb, b);
+	case VB2_MEMORY_DMABUF:
+		ret = __qbuf_dmabuf(vb, pb);
 		break;
 	default:
 		WARN(1, "Invalid queue type\n");
@@ -1736,35 +1217,56 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 	return ret;
 }
 
-static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
-					const char *opname)
+int vb2_verify_buffer(struct vb2_queue *q,
+			unsigned int memory, unsigned int type,
+			unsigned int index, unsigned int nplanes,
+			void *pplane, const char *opname)
 {
-	if (b->type != q->type) {
+	if (type != q->type) {
 		dprintk(1, "%s: invalid buffer type\n", opname);
 		return -EINVAL;
 	}
 
-	if (b->index >= q->num_buffers) {
+	if (index >= q->num_buffers) {
 		dprintk(1, "%s: buffer index out of range\n", opname);
 		return -EINVAL;
 	}
 
-	if (q->bufs[b->index] == NULL) {
+	if (q->bufs[index] == NULL) {
 		/* Should never happen */
 		dprintk(1, "%s: buffer is NULL\n", opname);
 		return -EINVAL;
 	}
 
-	if (b->memory != q->memory) {
+	if (memory != VB2_MEMORY_UNKNOWN && memory != q->memory) {
 		dprintk(1, "%s: invalid memory type\n", opname);
 		return -EINVAL;
 	}
 
-	return __verify_planes_array(q->bufs[b->index], b);
+	if (q->is_multiplanar) {
+		struct vb2_buffer *vb = q->bufs[index];
+
+		/* Is memory for copying plane information present? */
+		if (NULL == pplane) {
+			dprintk(1, "%s: multi-planar buffer passed but "
+				"planes array not provided\n", opname);
+			return -EINVAL;
+		}
+
+		if (nplanes < vb->num_planes || nplanes > VB2_MAX_PLANES) {
+			dprintk(1, "%s: incorrect planes array length, "
+				"expected %d, got %d\n",
+				opname, vb->num_planes, nplanes);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
 }
+EXPORT_SYMBOL_GPL(vb2_verify_buffer);
 
 /**
- * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
+ * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
  * @q:		videobuf2 queue
  * @b:		buffer structure passed from userspace to vidioc_prepare_buf
  *		handler in driver
@@ -1778,37 +1280,28 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
  * The return values from this function are intended to be directly returned
  * from vidioc_prepare_buf handler in driver.
  */
-int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 {
 	struct vb2_buffer *vb;
 	int ret;
 
-	if (vb2_fileio_is_active(q)) {
-		dprintk(1, "file io in progress\n");
-		return -EBUSY;
-	}
-
-	ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
-	if (ret)
-		return ret;
-
-	vb = q->bufs[b->index];
+	vb = q->bufs[index];
 	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
 		dprintk(1, "invalid buffer state %d\n",
 			vb->state);
 		return -EINVAL;
 	}
 
-	ret = __buf_prepare(vb, b);
+	ret = __buf_prepare(vb, pb);
 	if (!ret) {
 		/* Fill buffer information for the userspace */
-		__fill_v4l2_buffer(vb, b);
+		call_bufop(q, fill_user_buffer, vb, pb);
 
 		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
 	}
 	return ret;
 }
-EXPORT_SYMBOL_GPL(vb2_prepare_buf);
+EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
 /**
  * vb2_start_streaming() - Attempt to start streaming.
@@ -1873,21 +1366,16 @@ static int vb2_start_streaming(struct vb2_queue *q)
 	return ret;
 }
 
-static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
 {
-	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
+	int ret;
 	struct vb2_buffer *vb;
-	struct vb2_v4l2_buffer *vbuf;
-
-	if (ret)
-		return ret;
 
-	vb = q->bufs[b->index];
-	vbuf = to_vb2_v4l2_buffer(vb);
+	vb = q->bufs[index];
 
 	switch (vb->state) {
 	case VB2_BUF_STATE_DEQUEUED:
-		ret = __buf_prepare(vb, b);
+		ret = __buf_prepare(vb, pb);
 		if (ret)
 			return ret;
 		break;
@@ -1909,18 +1397,9 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 	q->queued_count++;
 	q->waiting_for_buffers = false;
 	vb->state = VB2_BUF_STATE_QUEUED;
-	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
-		/*
-		 * For output buffers copy the timestamp if needed,
-		 * and the timecode field and flag if needed.
-		 */
-		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
-				V4L2_BUF_FLAG_TIMESTAMP_COPY)
-			vbuf->timestamp = b->timestamp;
-		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
-		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
-			vbuf->timecode = b->timecode;
-	}
+
+	if (q->is_output)
+		call_bufop(q, fill_vb2_timestamp, vb, pb);
 
 	trace_vb2_qbuf(q, vb);
 
@@ -1932,7 +1411,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 		__enqueue_in_driver(vb);
 
 	/* Fill buffer information for the userspace */
-	__fill_v4l2_buffer(vb, b);
+	call_bufop(q, fill_user_buffer, vb, pb);
 
 	/*
 	 * If streamon has been called, and we haven't yet called
@@ -1950,34 +1429,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
 	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
 	return 0;
 }
-
-/**
- * vb2_qbuf() - Queue a buffer from userspace
- * @q:		videobuf2 queue
- * @b:		buffer structure passed from userspace to vidioc_qbuf handler
- *		in driver
- *
- * Should be called from vidioc_qbuf ioctl handler of a driver.
- * This function:
- * 1) verifies the passed buffer,
- * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
- *    which driver-specific buffer initialization can be performed,
- * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
- *    callback for processing.
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_qbuf handler in driver.
- */
-int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
-{
-	if (vb2_fileio_is_active(q)) {
-		dprintk(1, "file io in progress\n");
-		return -EBUSY;
-	}
-
-	return vb2_internal_qbuf(q, b);
-}
-EXPORT_SYMBOL_GPL(vb2_qbuf);
+EXPORT_SYMBOL_GPL(vb2_core_qbuf);
 
 /**
  * __vb2_wait_for_done_vb() - wait for a buffer to become available
@@ -2061,7 +1513,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
  * Will sleep if required for nonblocking == false.
  */
 static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
-				struct v4l2_buffer *b, int nonblocking)
+				int nonblocking)
 {
 	unsigned long flags;
 	int ret;
@@ -2082,10 +1534,11 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
 	/*
 	 * Only remove the buffer from done_list if v4l2_buffer can handle all
 	 * the planes.
+	 * ret = __verify_planes_array(*vb, pb);
+	 * But, actually that's unnecessary since this is checked already
+	 * before the buffer is queued/prepared. So it can never fails
 	 */
-	ret = __verify_planes_array(*vb, b);
-	if (!ret)
-		list_del(&(*vb)->done_entry);
+	list_del(&(*vb)->done_entry);
 	spin_unlock_irqrestore(&q->done_lock, flags);
 
 	return ret;
@@ -2128,27 +1581,22 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
 	vb->state = VB2_BUF_STATE_DEQUEUED;
 
 	/* unmap DMABUF buffer */
-	if (q->memory == V4L2_MEMORY_DMABUF)
+	if (q->memory == VB2_MEMORY_DMABUF)
 		for (i = 0; i < vb->num_planes; ++i) {
 			if (!vb->planes[i].dbuf_mapped)
 				continue;
-			call_void_memop(vb, unmap_dmabuf, vb->planes[i].mem_priv);
+			call_void_memop(vb, unmap_dmabuf,
+					vb->planes[i].mem_priv);
 			vb->planes[i].dbuf_mapped = 0;
 		}
 }
 
-static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
-		bool nonblocking)
+int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
 {
 	struct vb2_buffer *vb = NULL;
-	struct vb2_v4l2_buffer *vbuf = NULL;
 	int ret;
 
-	if (b->type != q->type) {
-		dprintk(1, "invalid buffer type\n");
-		return -EINVAL;
-	}
-	ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
+	ret = __vb2_get_done_vb(q, &vb, nonblocking);
 	if (ret < 0)
 		return ret;
 
@@ -2167,16 +1615,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
 	call_void_vb_qop(vb, buf_finish, vb);
 
 	/* Fill buffer information for the userspace */
-	__fill_v4l2_buffer(vb, b);
+	call_bufop(q, fill_user_buffer, vb, pb);
 	/* Remove from videobuf queue */
 	list_del(&vb->queued_entry);
 	q->queued_count--;
 
 	trace_vb2_dqbuf(q, vb);
 
-	vbuf = to_vb2_v4l2_buffer(vb);
-	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
-			vbuf->flags & V4L2_BUF_FLAG_LAST)
+	if (!q->is_output &&
+			call_bufop(q, is_last, vb))
 		q->last_buffer_dequeued = true;
 	/* go back to dequeued state */
 	__vb2_dqbuf(vb);
@@ -2186,37 +1633,7 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
 
 	return 0;
 }
-
-/**
- * vb2_dqbuf() - Dequeue a buffer to the userspace
- * @q:		videobuf2 queue
- * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
- *		in driver
- * @nonblocking: if true, this call will not sleep waiting for a buffer if no
- *		 buffers ready for dequeuing are present. Normally the driver
- *		 would be passing (file->f_flags & O_NONBLOCK) here
- *
- * Should be called from vidioc_dqbuf ioctl handler of a driver.
- * This function:
- * 1) verifies the passed buffer,
- * 2) calls buf_finish callback in the driver (if provided), in which
- *    driver can perform any additional operations that may be required before
- *    returning the buffer to userspace, such as cache sync,
- * 3) the buffer struct members are filled with relevant information for
- *    the userspace.
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_dqbuf handler in driver.
- */
-int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
-{
-	if (vb2_fileio_is_active(q)) {
-		dprintk(1, "file io in progress\n");
-		return -EBUSY;
-	}
-	return vb2_internal_dqbuf(q, b, nonblocking);
-}
-EXPORT_SYMBOL_GPL(vb2_dqbuf);
+EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
 
 /**
  * __vb2_queue_cancel() - cancel and stop (pause) streaming
@@ -2286,15 +1703,10 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 	}
 }
 
-static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
+int vb2_core_streamon(struct vb2_queue *q)
 {
 	int ret;
 
-	if (type != q->type) {
-		dprintk(1, "invalid stream type\n");
-		return -EINVAL;
-	}
-
 	if (q->streaming) {
 		dprintk(3, "already streaming\n");
 		return 0;
@@ -2328,6 +1740,7 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
 	dprintk(3, "successful\n");
 	return 0;
 }
+EXPORT_SYMBOL_GPL(vb2_core_streamon);
 
 /**
  * vb2_queue_error() - signal a fatal error on the queue
@@ -2350,36 +1763,8 @@ void vb2_queue_error(struct vb2_queue *q)
 }
 EXPORT_SYMBOL_GPL(vb2_queue_error);
 
-/**
- * vb2_streamon - start streaming
- * @q:		videobuf2 queue
- * @type:	type argument passed from userspace to vidioc_streamon handler
- *
- * Should be called from vidioc_streamon handler of a driver.
- * This function:
- * 1) verifies current state
- * 2) passes any previously queued buffers to the driver and starts streaming
- *
- * The return values from this function are intended to be directly returned
- * from vidioc_streamon handler in the driver.
- */
-int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
-{
-	if (vb2_fileio_is_active(q)) {
-		dprintk(1, "file io in progress\n");
-		return -EBUSY;
-	}
-	return vb2_internal_streamon(q, type);
-}
-EXPORT_SYMBOL_GPL(vb2_streamon);
-
-static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
+int vb2_core_streamoff(struct vb2_queue *q)
 {
-	if (type != q->type) {
-		dprintk(1, "invalid stream type\n");
-		return -EINVAL;
-	}
-
 	/*
 	 * Cancel will pause streaming and remove all buffers from the driver
 	 * and videobuf, effectively returning control over them to userspace.
@@ -2390,37 +1775,13 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
 	 * their normal dequeued state.
 	 */
 	__vb2_queue_cancel(q);
-	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
+	q->waiting_for_buffers = !q->is_output;
 	q->last_buffer_dequeued = false;
 
 	dprintk(3, "successful\n");
 	return 0;
 }
-
-/**
- * vb2_streamoff - stop streaming
- * @q:		videobuf2 queue
- * @type:	type argument passed from userspace to vidioc_streamoff handler
- *
- * Should be called from vidioc_streamoff handler of a driver.
- * This function:
- * 1) verifies current state,
- * 2) stop streaming and dequeues any queued buffers, including those previously
- *    passed to the driver (after waiting for the driver to finish).
- *
- * This call can be used for pausing playback.
- * The return values from this function are intended to be directly returned
- * from vidioc_streamoff handler in the driver
- */
-int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
-{
-	if (vb2_fileio_is_active(q)) {
-		dprintk(1, "file io in progress\n");
-		return -EBUSY;
-	}
-	return vb2_internal_streamoff(q, type);
-}
-EXPORT_SYMBOL_GPL(vb2_streamoff);
+EXPORT_SYMBOL_GPL(vb2_core_streamoff);
 
 /**
  * __find_plane_by_offset() - find plane associated with the given offset off
@@ -2452,7 +1813,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
 }
 
 /**
- * vb2_expbuf() - Export a buffer as a file descriptor
+ * vb2_core_expbuf() - Export a buffer as a file descriptor
  * @q:		videobuf2 queue
  * @eb:		export buffer structure passed from userspace to vidioc_expbuf
  *		handler in driver
@@ -2460,14 +1821,15 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
  * The return values from this function are intended to be directly returned
  * from vidioc_expbuf handler in driver.
  */
-int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
+		unsigned int index, unsigned int plane, unsigned int flags)
 {
 	struct vb2_buffer *vb = NULL;
 	struct vb2_plane *vb_plane;
 	int ret;
 	struct dma_buf *dbuf;
 
-	if (q->memory != V4L2_MEMORY_MMAP) {
+	if (q->memory != VB2_MEMORY_MMAP) {
 		dprintk(1, "queue is not currently set up for mmap\n");
 		return -EINVAL;
 	}
@@ -2477,78 +1839,60 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
 		return -EINVAL;
 	}
 
-	if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
+	if (flags & ~(O_CLOEXEC | O_ACCMODE)) {
 		dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n");
 		return -EINVAL;
 	}
 
-	if (eb->type != q->type) {
+	if (type != q->type) {
 		dprintk(1, "invalid buffer type\n");
 		return -EINVAL;
 	}
 
-	if (eb->index >= q->num_buffers) {
+	if (index >= q->num_buffers) {
 		dprintk(1, "buffer index out of range\n");
 		return -EINVAL;
 	}
 
-	vb = q->bufs[eb->index];
+	vb = q->bufs[index];
 
-	if (eb->plane >= vb->num_planes) {
+	if (plane >= vb->num_planes) {
 		dprintk(1, "buffer plane out of range\n");
 		return -EINVAL;
 	}
 
-	if (vb2_fileio_is_active(q)) {
-		dprintk(1, "expbuf: file io in progress\n");
-		return -EBUSY;
-	}
+	vb_plane = &vb->planes[plane];
 
-	vb_plane = &vb->planes[eb->plane];
-
-	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
+	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv,
+				flags & O_ACCMODE);
 	if (IS_ERR_OR_NULL(dbuf)) {
 		dprintk(1, "failed to export buffer %d, plane %d\n",
-			eb->index, eb->plane);
+			index, plane);
 		return -EINVAL;
 	}
 
-	ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
+	ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
 	if (ret < 0) {
 		dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
-			eb->index, eb->plane, ret);
+			index, plane, ret);
 		dma_buf_put(dbuf);
 		return ret;
 	}
 
 	dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
-		eb->index, eb->plane, ret);
-	eb->fd = ret;
+		index, plane, ret);
+	*fd = ret;
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(vb2_expbuf);
+EXPORT_SYMBOL_GPL(vb2_core_expbuf);
 
 /**
- * vb2_mmap() - map video buffers into application address space
+ * vb2_core_mmap() - map video buffers into application address space
  * @q:		videobuf2 queue
  * @vma:	vma passed to the mmap file operation handler in the driver
- *
- * Should be called from mmap file operation handler of a driver.
- * This function maps one plane of one of the available video buffers to
- * userspace. To map whole video memory allocated on reqbufs, this function
- * has to be called once per each plane per each buffer previously allocated.
- *
- * When the userspace application calls mmap, it passes to it an offset returned
- * to it earlier by the means of vidioc_querybuf handler. That offset acts as
- * a "cookie", which is then used to identify the plane to be mapped.
- * This function finds a plane with a matching offset and a mapping is performed
- * by the means of a provided memory operation.
- *
- * The return values from this function are intended to be directly returned
- * from the mmap handler in driver.
  */
-int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
+int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 {
 	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
 	struct vb2_buffer *vb;
@@ -2556,7 +1900,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 	int ret;
 	unsigned long length;
 
-	if (q->memory != V4L2_MEMORY_MMAP) {
+	if (q->memory != VB2_MEMORY_MMAP) {
 		dprintk(1, "queue is not currently set up for mmap\n");
 		return -EINVAL;
 	}
@@ -2568,7 +1912,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 		dprintk(1, "invalid vma flags, VM_SHARED needed\n");
 		return -EINVAL;
 	}
-	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+	if (q->is_output) {
 		if (!(vma->vm_flags & VM_WRITE)) {
 			dprintk(1, "invalid vma flags, VM_WRITE needed\n");
 			return -EINVAL;
@@ -2579,10 +1923,6 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 			return -EINVAL;
 		}
 	}
-	if (vb2_fileio_is_active(q)) {
-		dprintk(1, "mmap: file io in progress\n");
-		return -EBUSY;
-	}
 
 	/*
 	 * Find the plane corresponding to the offset passed by userspace.
@@ -2614,7 +1954,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
 	dprintk(3, "buffer %d, plane %d successfully mapped\n", buffer, plane);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(vb2_mmap);
+EXPORT_SYMBOL_GPL(vb2_core_mmap);
 
 #ifndef CONFIG_MMU
 unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
@@ -2629,7 +1969,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 	void *vaddr;
 	int ret;
 
-	if (q->memory != V4L2_MEMORY_MMAP) {
+	if (q->memory != VB2_MEMORY_MMAP) {
 		dprintk(1, "queue is not currently set up for mmap\n");
 		return -EINVAL;
 	}
@@ -2649,123 +1989,8 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
 #endif
 
-static int __vb2_init_fileio(struct vb2_queue *q, int read);
-static int __vb2_cleanup_fileio(struct vb2_queue *q);
-
-/**
- * vb2_poll() - implements poll userspace operation
- * @q:		videobuf2 queue
- * @file:	file argument passed to the poll file operation handler
- * @wait:	wait argument passed to the poll file operation handler
- *
- * This function implements poll file operation handler for a driver.
- * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
- * be informed that the file descriptor of a video device is available for
- * reading.
- * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
- * will be reported as available for writing.
- *
- * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
- * pending events.
- *
- * The return values from this function are intended to be directly returned
- * from poll handler in driver.
- */
-unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
-{
-	struct video_device *vfd = video_devdata(file);
-	unsigned long req_events = poll_requested_events(wait);
-	struct vb2_buffer *vb = NULL;
-	unsigned int res = 0;
-	unsigned long flags;
-
-	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
-		struct v4l2_fh *fh = file->private_data;
-
-		if (v4l2_event_pending(fh))
-			res = POLLPRI;
-		else if (req_events & POLLPRI)
-			poll_wait(file, &fh->wait, wait);
-	}
-
-	if (!V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLIN | POLLRDNORM)))
-		return res;
-	if (V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLOUT | POLLWRNORM)))
-		return res;
-
-	/*
-	 * Start file I/O emulator only if streaming API has not been used yet.
-	 */
-	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
-		if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
-				(req_events & (POLLIN | POLLRDNORM))) {
-			if (__vb2_init_fileio(q, 1))
-				return res | POLLERR;
-		}
-		if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
-				(req_events & (POLLOUT | POLLWRNORM))) {
-			if (__vb2_init_fileio(q, 0))
-				return res | POLLERR;
-			/*
-			 * Write to OUTPUT queue can be done immediately.
-			 */
-			return res | POLLOUT | POLLWRNORM;
-		}
-	}
-
-	/*
-	 * There is nothing to wait for if the queue isn't streaming, or if the
-	 * error flag is set.
-	 */
-	if (!vb2_is_streaming(q) || q->error)
-		return res | POLLERR;
-	/*
-	 * For compatibility with vb1: if QBUF hasn't been called yet, then
-	 * return POLLERR as well. This only affects capture queues, output
-	 * queues will always initialize waiting_for_buffers to false.
-	 */
-	if (q->waiting_for_buffers)
-		return res | POLLERR;
-
-	/*
-	 * For output streams you can write as long as there are fewer buffers
-	 * queued than there are buffers available.
-	 */
-	if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
-		return res | POLLOUT | POLLWRNORM;
-
-	if (list_empty(&q->done_list)) {
-		/*
-		 * If the last buffer was dequeued from a capture queue,
-		 * return immediately. DQBUF will return -EPIPE.
-		 */
-		if (q->last_buffer_dequeued)
-			return res | POLLIN | POLLRDNORM;
-
-		poll_wait(file, &q->done_wq, wait);
-	}
-
-	/*
-	 * Take first buffer available for dequeuing.
-	 */
-	spin_lock_irqsave(&q->done_lock, flags);
-	if (!list_empty(&q->done_list))
-		vb = list_first_entry(&q->done_list, struct vb2_buffer,
-					done_entry);
-	spin_unlock_irqrestore(&q->done_lock, flags);
-
-	if (vb && (vb->state == VB2_BUF_STATE_DONE
-			|| vb->state == VB2_BUF_STATE_ERROR)) {
-		return (V4L2_TYPE_IS_OUTPUT(q->type)) ?
-				res | POLLOUT | POLLWRNORM :
-				res | POLLIN | POLLRDNORM;
-	}
-	return res;
-}
-EXPORT_SYMBOL_GPL(vb2_poll);
-
 /**
- * vb2_queue_init() - initialize a videobuf2 queue
+ * vb2_core_queue_init() - initialize a videobuf2 queue
  * @q:		videobuf2 queue; this structure should be allocated in driver
  *
  * The vb2_queue structure should be allocated by the driver. The driver is
@@ -2775,7 +2000,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
  * to the struct vb2_queue description in include/media/videobuf2-core.h
  * for more information.
  */
-int vb2_queue_init(struct vb2_queue *q)
+int vb2_core_queue_init(struct vb2_queue *q)
 {
 	/*
 	 * Sanity check
@@ -2783,19 +2008,13 @@ int vb2_queue_init(struct vb2_queue *q)
 	if (WARN_ON(!q)				||
 		WARN_ON(!q->ops)		||
 		WARN_ON(!q->mem_ops)		||
+		WARN_ON(!q->buf_ops)		||
 		WARN_ON(!q->type)		||
 		WARN_ON(!q->io_modes)		||
 		WARN_ON(!q->ops->queue_setup)	||
-		WARN_ON(!q->ops->buf_queue)	||
-		WARN_ON(q->timestamp_flags &
-			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
-			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
+		WARN_ON(!q->ops->buf_queue))
 		return -EINVAL;
 
-	/* Warn that the driver should choose an appropriate timestamp type */
-	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
-		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
-
 	INIT_LIST_HEAD(&q->queued_list);
 	INIT_LIST_HEAD(&q->done_list);
 	spin_lock_init(&q->done_lock);
@@ -2807,822 +2026,24 @@ int vb2_queue_init(struct vb2_queue *q)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(vb2_queue_init);
+EXPORT_SYMBOL_GPL(vb2_core_queue_init);
 
 /**
- * vb2_queue_release() - stop streaming, release the queue and free memory
+ * vb2_core_queue_release() - stop streaming, release the queue and free memory
  * @q:		videobuf2 queue
  *
  * This function stops streaming and performs necessary clean ups, including
  * freeing video buffer memory. The driver is responsible for freeing
  * the vb2_queue structure itself.
  */
-void vb2_queue_release(struct vb2_queue *q)
+void vb2_core_queue_release(struct vb2_queue *q)
 {
-	__vb2_cleanup_fileio(q);
 	__vb2_queue_cancel(q);
 	mutex_lock(&q->mmap_lock);
 	__vb2_queue_free(q, q->num_buffers);
 	mutex_unlock(&q->mmap_lock);
 }
-EXPORT_SYMBOL_GPL(vb2_queue_release);
-
-/**
- * struct vb2_fileio_buf - buffer context used by file io emulator
- *
- * vb2 provides a compatibility layer and emulator of file io (read and
- * write) calls on top of streaming API. This structure is used for
- * tracking context related to the buffers.
- */
-struct vb2_fileio_buf {
-	void *vaddr;
-	unsigned int size;
-	unsigned int pos;
-	unsigned int queued:1;
-};
-
-/**
- * struct vb2_fileio_data - queue context used by file io emulator
- *
- * @cur_index:	the index of the buffer currently being read from or
- *		written to. If equal to q->num_buffers then a new buffer
- *		must be dequeued.
- * @initial_index: in the read() case all buffers are queued up immediately
- *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
- *		buffers. However, in the write() case no buffers are initially
- *		queued, instead whenever a buffer is full it is queued up by
- *		__vb2_perform_fileio(). Only once all available buffers have
- *		been queued up will __vb2_perform_fileio() start to dequeue
- *		buffers. This means that initially __vb2_perform_fileio()
- *		needs to know what buffer index to use when it is queuing up
- *		the buffers for the first time. That initial index is stored
- *		in this field. Once it is equal to q->num_buffers all
- *		available buffers have been queued and __vb2_perform_fileio()
- *		should start the normal dequeue/queue cycle.
- *
- * vb2 provides a compatibility layer and emulator of file io (read and
- * write) calls on top of streaming API. For proper operation it required
- * this structure to save the driver state between each call of the read
- * or write function.
- */
-struct vb2_fileio_data {
-	struct v4l2_requestbuffers req;
-	struct v4l2_plane p;
-	struct v4l2_buffer b;
-	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
-	unsigned int cur_index;
-	unsigned int initial_index;
-	unsigned int q_count;
-	unsigned int dq_count;
-	unsigned read_once:1;
-	unsigned write_immediately:1;
-};
-
-/**
- * __vb2_init_fileio() - initialize file io emulator
- * @q:		videobuf2 queue
- * @read:	mode selector (1 means read, 0 means write)
- */
-static int __vb2_init_fileio(struct vb2_queue *q, int read)
-{
-	struct vb2_fileio_data *fileio;
-	int i, ret;
-	unsigned int count = 0;
-
-	/*
-	 * Sanity check
-	 */
-	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
-			(!read && !(q->io_modes & VB2_WRITE))))
-		return -EINVAL;
-
-	/*
-	 * Check if device supports mapping buffers to kernel virtual space.
-	 */
-	if (!q->mem_ops->vaddr)
-		return -EBUSY;
-
-	/*
-	 * Check if streaming api has not been already activated.
-	 */
-	if (q->streaming || q->num_buffers > 0)
-		return -EBUSY;
-
-	/*
-	 * Start with count 1, driver can increase it in queue_setup()
-	 */
-	count = 1;
-
-	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
-		(read) ? "read" : "write", count, q->fileio_read_once,
-		q->fileio_write_immediately);
-
-	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
-	if (fileio == NULL)
-		return -ENOMEM;
-
-	fileio->read_once = q->fileio_read_once;
-	fileio->write_immediately = q->fileio_write_immediately;
-
-	/*
-	 * Request buffers and use MMAP type to force driver
-	 * to allocate buffers by itself.
-	 */
-	fileio->req.count = count;
-	fileio->req.memory = V4L2_MEMORY_MMAP;
-	fileio->req.type = q->type;
-	q->fileio = fileio;
-	ret = __reqbufs(q, &fileio->req);
-	if (ret)
-		goto err_kfree;
-
-	/*
-	 * Check if plane_count is correct
-	 * (multiplane buffers are not supported).
-	 */
-	if (q->bufs[0]->num_planes != 1) {
-		ret = -EBUSY;
-		goto err_reqbufs;
-	}
-
-	/*
-	 * Get kernel address of each buffer.
-	 */
-	for (i = 0; i < q->num_buffers; i++) {
-		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
-		if (fileio->bufs[i].vaddr == NULL) {
-			ret = -EINVAL;
-			goto err_reqbufs;
-		}
-		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
-	}
-
-	/*
-	 * Read mode requires pre queuing of all buffers.
-	 */
-	if (read) {
-		bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
-
-		/*
-		 * Queue all buffers.
-		 */
-		for (i = 0; i < q->num_buffers; i++) {
-			struct v4l2_buffer *b = &fileio->b;
-
-			memset(b, 0, sizeof(*b));
-			b->type = q->type;
-			if (is_multiplanar) {
-				memset(&fileio->p, 0, sizeof(fileio->p));
-				b->m.planes = &fileio->p;
-				b->length = 1;
-			}
-			b->memory = q->memory;
-			b->index = i;
-			ret = vb2_internal_qbuf(q, b);
-			if (ret)
-				goto err_reqbufs;
-			fileio->bufs[i].queued = 1;
-		}
-		/*
-		 * All buffers have been queued, so mark that by setting
-		 * initial_index to q->num_buffers
-		 */
-		fileio->initial_index = q->num_buffers;
-		fileio->cur_index = q->num_buffers;
-	}
-
-	/*
-	 * Start streaming.
-	 */
-	ret = vb2_internal_streamon(q, q->type);
-	if (ret)
-		goto err_reqbufs;
-
-	return ret;
-
-err_reqbufs:
-	fileio->req.count = 0;
-	__reqbufs(q, &fileio->req);
-
-err_kfree:
-	q->fileio = NULL;
-	kfree(fileio);
-	return ret;
-}
-
-/**
- * __vb2_cleanup_fileio() - free resourced used by file io emulator
- * @q:		videobuf2 queue
- */
-static int __vb2_cleanup_fileio(struct vb2_queue *q)
-{
-	struct vb2_fileio_data *fileio = q->fileio;
-
-	if (fileio) {
-		vb2_internal_streamoff(q, q->type);
-		q->fileio = NULL;
-		fileio->req.count = 0;
-		vb2_reqbufs(q, &fileio->req);
-		kfree(fileio);
-		dprintk(3, "file io emulator closed\n");
-	}
-	return 0;
-}
-
-/**
- * __vb2_perform_fileio() - perform a single file io (read or write) operation
- * @q:		videobuf2 queue
- * @data:	pointed to target userspace buffer
- * @count:	number of bytes to read or write
- * @ppos:	file handle position tracking pointer
- * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
- * @read:	access mode selector (1 means read, 0 means write)
- */
-static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
-		loff_t *ppos, int nonblock, int read)
-{
-	struct vb2_fileio_data *fileio;
-	struct vb2_fileio_buf *buf;
-	bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
-	/*
-	 * When using write() to write data to an output video node the vb2 core
-	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
-	 * else is able to provide this information with the write() operation.
-	 */
-	bool set_timestamp = !read &&
-		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
-		V4L2_BUF_FLAG_TIMESTAMP_COPY;
-	int ret, index;
-
-	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
-		read ? "read" : "write", (long)*ppos, count,
-		nonblock ? "non" : "");
-
-	if (!data)
-		return -EINVAL;
-
-	/*
-	 * Initialize emulator on first call.
-	 */
-	if (!vb2_fileio_is_active(q)) {
-		ret = __vb2_init_fileio(q, read);
-		dprintk(3, "vb2_init_fileio result: %d\n", ret);
-		if (ret)
-			return ret;
-	}
-	fileio = q->fileio;
-
-	/*
-	 * Check if we need to dequeue the buffer.
-	 */
-	index = fileio->cur_index;
-	if (index >= q->num_buffers) {
-		/*
-		 * Call vb2_dqbuf to get buffer back.
-		 */
-		memset(&fileio->b, 0, sizeof(fileio->b));
-		fileio->b.type = q->type;
-		fileio->b.memory = q->memory;
-		if (is_multiplanar) {
-			memset(&fileio->p, 0, sizeof(fileio->p));
-			fileio->b.m.planes = &fileio->p;
-			fileio->b.length = 1;
-		}
-		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
-		dprintk(5, "vb2_dqbuf result: %d\n", ret);
-		if (ret)
-			return ret;
-		fileio->dq_count += 1;
-
-		fileio->cur_index = index = fileio->b.index;
-		buf = &fileio->bufs[index];
-
-		/*
-		 * Get number of bytes filled by the driver
-		 */
-		buf->pos = 0;
-		buf->queued = 0;
-		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
-				 : vb2_plane_size(q->bufs[index], 0);
-		/*
-		 * Compensate for data_offset on read
-		 * in the multiplanar case
-		 */
-		if (is_multiplanar && read &&
-			fileio->b.m.planes[0].data_offset < buf->size) {
-			buf->pos = fileio->b.m.planes[0].data_offset;
-			buf->size -= buf->pos;
-		}
-	} else {
-		buf = &fileio->bufs[index];
-	}
-
-	/*
-	 * Limit count on last few bytes of the buffer.
-	 */
-	if (buf->pos + count > buf->size) {
-		count = buf->size - buf->pos;
-		dprintk(5, "reducing read count: %zd\n", count);
-	}
-
-	/*
-	 * Transfer data to userspace.
-	 */
-	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
-		count, index, buf->pos);
-	if (read)
-		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
-	else
-		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
-	if (ret) {
-		dprintk(3, "error copying data\n");
-		return -EFAULT;
-	}
-
-	/*
-	 * Update counters.
-	 */
-	buf->pos += count;
-	*ppos += count;
-
-	/*
-	 * Queue next buffer if required.
-	 */
-	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
-		/*
-		 * Check if this is the last buffer to read.
-		 */
-		if (read && fileio->read_once && fileio->dq_count == 1) {
-			dprintk(3, "read limit reached\n");
-			return __vb2_cleanup_fileio(q);
-		}
-
-		/*
-		 * Call vb2_qbuf and give buffer to the driver.
-		 */
-		memset(&fileio->b, 0, sizeof(fileio->b));
-		fileio->b.type = q->type;
-		fileio->b.memory = q->memory;
-		fileio->b.index = index;
-		fileio->b.bytesused = buf->pos;
-		if (is_multiplanar) {
-			memset(&fileio->p, 0, sizeof(fileio->p));
-			fileio->p.bytesused = buf->pos;
-			fileio->b.m.planes = &fileio->p;
-			fileio->b.length = 1;
-		}
-		if (set_timestamp)
-			v4l2_get_timestamp(&fileio->b.timestamp);
-		ret = vb2_internal_qbuf(q, &fileio->b);
-		dprintk(5, "vb2_dbuf result: %d\n", ret);
-		if (ret)
-			return ret;
-
-		/*
-		 * Buffer has been queued, update the status
-		 */
-		buf->pos = 0;
-		buf->queued = 1;
-		buf->size = vb2_plane_size(q->bufs[index], 0);
-		fileio->q_count += 1;
-		/*
-		 * If we are queuing up buffers for the first time, then
-		 * increase initial_index by one.
-		 */
-		if (fileio->initial_index < q->num_buffers)
-			fileio->initial_index++;
-		/*
-		 * The next buffer to use is either a buffer that's going to be
-		 * queued for the first time (initial_index < q->num_buffers)
-		 * or it is equal to q->num_buffers, meaning that the next
-		 * time we need to dequeue a buffer since we've now queued up
-		 * all the 'first time' buffers.
-		 */
-		fileio->cur_index = fileio->initial_index;
-	}
-
-	/*
-	 * Return proper number of bytes processed.
-	 */
-	if (ret == 0)
-		ret = count;
-	return ret;
-}
-
-size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
-		loff_t *ppos, int nonblocking)
-{
-	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
-}
-EXPORT_SYMBOL_GPL(vb2_read);
-
-size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
-		loff_t *ppos, int nonblocking)
-{
-	return __vb2_perform_fileio(q, (char __user *) data, count,
-							ppos, nonblocking, 0);
-}
-EXPORT_SYMBOL_GPL(vb2_write);
-
-struct vb2_threadio_data {
-	struct task_struct *thread;
-	vb2_thread_fnc fnc;
-	void *priv;
-	bool stop;
-};
-
-static int vb2_thread(void *data)
-{
-	struct vb2_queue *q = data;
-	struct vb2_threadio_data *threadio = q->threadio;
-	struct vb2_fileio_data *fileio = q->fileio;
-	bool set_timestamp = false;
-	int prequeue = 0;
-	int index = 0;
-	int ret = 0;
-
-	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
-		prequeue = q->num_buffers;
-		set_timestamp =
-			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
-			V4L2_BUF_FLAG_TIMESTAMP_COPY;
-	}
-
-	set_freezable();
-
-	for (;;) {
-		struct vb2_buffer *vb;
-
-		/*
-		 * Call vb2_dqbuf to get buffer back.
-		 */
-		memset(&fileio->b, 0, sizeof(fileio->b));
-		fileio->b.type = q->type;
-		fileio->b.memory = q->memory;
-		if (prequeue) {
-			fileio->b.index = index++;
-			prequeue--;
-		} else {
-			call_void_qop(q, wait_finish, q);
-			if (!threadio->stop)
-				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
-			call_void_qop(q, wait_prepare, q);
-			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
-		}
-		if (ret || threadio->stop)
-			break;
-		try_to_freeze();
-
-		vb = q->bufs[fileio->b.index];
-		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
-			if (threadio->fnc(vb, threadio->priv))
-				break;
-		call_void_qop(q, wait_finish, q);
-		if (set_timestamp)
-			v4l2_get_timestamp(&fileio->b.timestamp);
-		if (!threadio->stop)
-			ret = vb2_internal_qbuf(q, &fileio->b);
-		call_void_qop(q, wait_prepare, q);
-		if (ret || threadio->stop)
-			break;
-	}
-
-	/* Hmm, linux becomes *very* unhappy without this ... */
-	while (!kthread_should_stop()) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule();
-	}
-	return 0;
-}
-
-/*
- * This function should not be used for anything else but the videobuf2-dvb
- * support. If you think you have another good use-case for this, then please
- * contact the linux-media mailinglist first.
- */
-int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
-			const char *thread_name)
-{
-	struct vb2_threadio_data *threadio;
-	int ret = 0;
-
-	if (q->threadio)
-		return -EBUSY;
-	if (vb2_is_busy(q))
-		return -EBUSY;
-	if (WARN_ON(q->fileio))
-		return -EBUSY;
-
-	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
-	if (threadio == NULL)
-		return -ENOMEM;
-	threadio->fnc = fnc;
-	threadio->priv = priv;
-
-	ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type));
-	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
-	if (ret)
-		goto nomem;
-	q->threadio = threadio;
-	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
-	if (IS_ERR(threadio->thread)) {
-		ret = PTR_ERR(threadio->thread);
-		threadio->thread = NULL;
-		goto nothread;
-	}
-	return 0;
-
-nothread:
-	__vb2_cleanup_fileio(q);
-nomem:
-	kfree(threadio);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(vb2_thread_start);
-
-int vb2_thread_stop(struct vb2_queue *q)
-{
-	struct vb2_threadio_data *threadio = q->threadio;
-	int err;
-
-	if (threadio == NULL)
-		return 0;
-	threadio->stop = true;
-	/* Wake up all pending sleeps in the thread */
-	vb2_queue_error(q);
-	err = kthread_stop(threadio->thread);
-	__vb2_cleanup_fileio(q);
-	threadio->thread = NULL;
-	kfree(threadio);
-	q->threadio = NULL;
-	return err;
-}
-EXPORT_SYMBOL_GPL(vb2_thread_stop);
-
-/*
- * The following functions are not part of the vb2 core API, but are helper
- * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
- * and struct vb2_ops.
- * They contain boilerplate code that most if not all drivers have to do
- * and so they simplify the driver code.
- */
-
-/* The queue is busy if there is a owner and you are not that owner. */
-static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
-{
-	return vdev->queue->owner && vdev->queue->owner != file->private_data;
-}
-
-/* vb2 ioctl helpers */
-
-int vb2_ioctl_reqbufs(struct file *file, void *priv,
-			  struct v4l2_requestbuffers *p)
-{
-	struct video_device *vdev = video_devdata(file);
-	int res = __verify_memory_type(vdev->queue, p->memory, p->type);
-
-	if (res)
-		return res;
-	if (vb2_queue_is_busy(vdev, file))
-		return -EBUSY;
-	res = __reqbufs(vdev->queue, p);
-	/* If count == 0, then the owner has released all buffers and he
-	   is no longer owner of the queue. Otherwise we have a new owner. */
-	if (res == 0)
-		vdev->queue->owner = p->count ? file->private_data : NULL;
-	return res;
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
-
-int vb2_ioctl_create_bufs(struct file *file, void *priv,
-			  struct v4l2_create_buffers *p)
-{
-	struct video_device *vdev = video_devdata(file);
-	int res = __verify_memory_type(vdev->queue, p->memory, p->format.type);
-
-	p->index = vdev->queue->num_buffers;
-	/* If count == 0, then just check if memory and type are valid.
-	   Any -EBUSY result from __verify_memory_type can be mapped to 0. */
-	if (p->count == 0)
-		return res != -EBUSY ? res : 0;
-	if (res)
-		return res;
-	if (vb2_queue_is_busy(vdev, file))
-		return -EBUSY;
-	res = __create_bufs(vdev->queue, p);
-	if (res == 0)
-		vdev->queue->owner = file->private_data;
-	return res;
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
-
-int vb2_ioctl_prepare_buf(struct file *file, void *priv,
-			  struct v4l2_buffer *p)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	if (vb2_queue_is_busy(vdev, file))
-		return -EBUSY;
-	return vb2_prepare_buf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
-
-int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
-	return vb2_querybuf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
-
-int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	if (vb2_queue_is_busy(vdev, file))
-		return -EBUSY;
-	return vb2_qbuf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
-
-int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	if (vb2_queue_is_busy(vdev, file))
-		return -EBUSY;
-	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
-
-int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	if (vb2_queue_is_busy(vdev, file))
-		return -EBUSY;
-	return vb2_streamon(vdev->queue, i);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
-
-int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	if (vb2_queue_is_busy(vdev, file))
-		return -EBUSY;
-	return vb2_streamoff(vdev->queue, i);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
-
-int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	if (vb2_queue_is_busy(vdev, file))
-		return -EBUSY;
-	return vb2_expbuf(vdev->queue, p);
-}
-EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
-
-/* v4l2_file_operations helpers */
-
-int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	return vb2_mmap(vdev->queue, vma);
-}
-EXPORT_SYMBOL_GPL(vb2_fop_mmap);
-
-int _vb2_fop_release(struct file *file, struct mutex *lock)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	if (lock)
-		mutex_lock(lock);
-	if (file->private_data == vdev->queue->owner) {
-		vb2_queue_release(vdev->queue);
-		vdev->queue->owner = NULL;
-	}
-	if (lock)
-		mutex_unlock(lock);
-	return v4l2_fh_release(file);
-}
-EXPORT_SYMBOL_GPL(_vb2_fop_release);
-
-int vb2_fop_release(struct file *file)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
-
-	return _vb2_fop_release(file, lock);
-}
-EXPORT_SYMBOL_GPL(vb2_fop_release);
-
-ssize_t vb2_fop_write(struct file *file, const char __user *buf,
-		size_t count, loff_t *ppos)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
-	int err = -EBUSY;
-
-	if (!(vdev->queue->io_modes & VB2_WRITE))
-		return -EINVAL;
-	if (lock && mutex_lock_interruptible(lock))
-		return -ERESTARTSYS;
-	if (vb2_queue_is_busy(vdev, file))
-		goto exit;
-	err = vb2_write(vdev->queue, buf, count, ppos,
-			file->f_flags & O_NONBLOCK);
-	if (vdev->queue->fileio)
-		vdev->queue->owner = file->private_data;
-exit:
-	if (lock)
-		mutex_unlock(lock);
-	return err;
-}
-EXPORT_SYMBOL_GPL(vb2_fop_write);
-
-ssize_t vb2_fop_read(struct file *file, char __user *buf,
-		size_t count, loff_t *ppos)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
-	int err = -EBUSY;
-
-	if (!(vdev->queue->io_modes & VB2_READ))
-		return -EINVAL;
-	if (lock && mutex_lock_interruptible(lock))
-		return -ERESTARTSYS;
-	if (vb2_queue_is_busy(vdev, file))
-		goto exit;
-	err = vb2_read(vdev->queue, buf, count, ppos,
-			file->f_flags & O_NONBLOCK);
-	if (vdev->queue->fileio)
-		vdev->queue->owner = file->private_data;
-exit:
-	if (lock)
-		mutex_unlock(lock);
-	return err;
-}
-EXPORT_SYMBOL_GPL(vb2_fop_read);
-
-unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct vb2_queue *q = vdev->queue;
-	struct mutex *lock = q->lock ? q->lock : vdev->lock;
-	unsigned res;
-	void *fileio;
-
-	/*
-	 * If this helper doesn't know how to lock, then you shouldn't be using
-	 * it but you should write your own.
-	 */
-	WARN_ON(!lock);
-
-	if (lock && mutex_lock_interruptible(lock))
-		return POLLERR;
-
-	fileio = q->fileio;
-
-	res = vb2_poll(vdev->queue, file, wait);
-
-	/* If fileio was started, then we have a new queue owner. */
-	if (!fileio && q->fileio)
-		q->owner = file->private_data;
-	if (lock)
-		mutex_unlock(lock);
-	return res;
-}
-EXPORT_SYMBOL_GPL(vb2_fop_poll);
-
-#ifndef CONFIG_MMU
-unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
-		unsigned long len, unsigned long pgoff, unsigned long flags)
-{
-	struct video_device *vdev = video_devdata(file);
-
-	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
-}
-EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
-#endif
-
-/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
-
-void vb2_ops_wait_prepare(struct vb2_queue *vq)
-{
-	mutex_unlock(vq->lock);
-}
-EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
-
-void vb2_ops_wait_finish(struct vb2_queue *vq)
-{
-	mutex_lock(vq->lock);
-}
-EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
+EXPORT_SYMBOL_GPL(vb2_core_queue_release);
 
 MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
 MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h
new file mode 100644
index 0000000..3998ac9
--- /dev/null
+++ b/drivers/media/v4l2-core/videobuf2-internal.h
@@ -0,0 +1,184 @@
+#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H
+#define _MEDIA_VIDEOBUF2_INTERNAL_H
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <media/videobuf2-core.h>
+
+extern int vb2_debug;
+
+#define dprintk(level, fmt, arg...)					\
+	do {								\
+		if (vb2_debug >= level)					\
+			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
+	} while (0)
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+
+/*
+ * If advanced debugging is on, then count how often each op is called
+ * successfully, which can either be per-buffer or per-queue.
+ *
+ * This makes it easy to check that the 'init' and 'cleanup'
+ * (and variations thereof) stay balanced.
+ */
+
+#define log_memop(vb, op)						\
+	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
+		(vb)->vb2_queue, (vb)->index, #op,			\
+		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
+
+#define call_memop(vb, op, args...)					\
+({									\
+	struct vb2_queue *_q = (vb)->vb2_queue;				\
+	int err;							\
+									\
+	log_memop(vb, op);						\
+	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
+	if (!err)							\
+		(vb)->cnt_mem_ ## op++;					\
+	err;								\
+})
+
+#define call_ptr_memop(vb, op, args...)					\
+({									\
+	struct vb2_queue *_q = (vb)->vb2_queue;				\
+	void *ptr;							\
+									\
+	log_memop(vb, op);						\
+	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
+	if (!IS_ERR_OR_NULL(ptr))					\
+		(vb)->cnt_mem_ ## op++;					\
+	ptr;								\
+})
+
+#define call_void_memop(vb, op, args...)				\
+({									\
+	struct vb2_queue *_q = (vb)->vb2_queue;				\
+									\
+	log_memop(vb, op);						\
+	if (_q->mem_ops->op)						\
+		_q->mem_ops->op(args);					\
+	(vb)->cnt_mem_ ## op++;						\
+})
+
+#define log_qop(q, op)							\
+	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
+		(q)->ops->op ? "" : " (nop)")
+
+#define call_qop(q, op, args...)					\
+({									\
+	int err;							\
+									\
+	log_qop(q, op);							\
+	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
+	if (!err)							\
+		(q)->cnt_ ## op++;					\
+	err;								\
+})
+
+#define call_void_qop(q, op, args...)					\
+({									\
+	log_qop(q, op);							\
+	if ((q)->ops->op)						\
+		(q)->ops->op(args);					\
+	(q)->cnt_ ## op++;						\
+})
+
+#define log_vb_qop(vb, op, args...)					\
+	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
+		(vb)->vb2_queue, (vb)->index, #op,			\
+		(vb)->vb2_queue->ops->op ? "" : " (nop)")
+
+#define call_vb_qop(vb, op, args...)					\
+({									\
+	int err;							\
+									\
+	log_vb_qop(vb, op);						\
+	err = (vb)->vb2_queue->ops->op ?				\
+		(vb)->vb2_queue->ops->op(args) : 0;			\
+	if (!err)							\
+		(vb)->cnt_ ## op++;					\
+	err;								\
+})
+
+#define call_void_vb_qop(vb, op, args...)				\
+({									\
+	log_vb_qop(vb, op);						\
+	if ((vb)->vb2_queue->ops->op)					\
+		(vb)->vb2_queue->ops->op(args);				\
+	(vb)->cnt_ ## op++;						\
+})
+
+#else
+
+#define call_memop(vb, op, args...)					\
+	((vb)->vb2_queue->mem_ops->op ?					\
+		(vb)->vb2_queue->mem_ops->op(args) : 0)
+
+#define call_ptr_memop(vb, op, args...)					\
+	((vb)->vb2_queue->mem_ops->op ?					\
+		(vb)->vb2_queue->mem_ops->op(args) : NULL)
+
+#define call_void_memop(vb, op, args...)				\
+	do {								\
+		if ((vb)->vb2_queue->mem_ops->op)			\
+			(vb)->vb2_queue->mem_ops->op(args);		\
+	} while (0)
+
+#define call_qop(q, op, args...)					\
+	((q)->ops->op ? (q)->ops->op(args) : 0)
+
+#define call_void_qop(q, op, args...)					\
+	do {								\
+		if ((q)->ops->op)					\
+			(q)->ops->op(args);				\
+	} while (0)
+
+#define call_vb_qop(vb, op, args...)					\
+	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
+
+#define call_void_vb_qop(vb, op, args...)				\
+	do {								\
+		if ((vb)->vb2_queue->ops->op)				\
+			(vb)->vb2_queue->ops->op(args);			\
+	} while (0)
+
+#endif
+
+#define call_bufop(q, op, args...)					\
+({									\
+	int ret = 0;							\
+	if (q && q->buf_ops && q->buf_ops->op)				\
+		ret = q->buf_ops->op(args);				\
+	ret;								\
+})
+
+bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
+int vb2_verify_memory_type(struct vb2_queue *q,
+		unsigned int memory, unsigned int type);
+int vb2_verify_buffer(struct vb2_queue *q,
+			unsigned int memory, unsigned int type,
+			unsigned int index, unsigned int nplanes,
+			void *pplane, const char *opname);
+void vb2_warn_zero_bytesused(struct vb2_buffer *vb);
+
+int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb);
+int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
+		unsigned int *count);
+int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
+		unsigned int *count, void *parg);
+int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb);
+int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblock);
+int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
+		unsigned int index, unsigned int plane, unsigned int flags);
+int vb2_core_streamon(struct vb2_queue *q);
+int vb2_core_streamoff(struct vb2_queue *q);
+int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
+
+int __must_check vb2_core_queue_init(struct vb2_queue *q);
+void vb2_core_queue_release(struct vb2_queue *q);
+
+#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
index 2f2b738..9fc6bef 100644
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
@@ -24,8 +24,1648 @@
 #include <linux/freezer.h>
 #include <linux/kthread.h>
 
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-common.h>
 #include <media/videobuf2-v4l2.h>
 
+#include "videobuf2-internal.h"
+
+/* Flags that are set by the vb2 core */
+#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | \
+				V4L2_BUF_FLAG_QUEUED | \
+				V4L2_BUF_FLAG_DONE | \
+				V4L2_BUF_FLAG_ERROR | \
+				V4L2_BUF_FLAG_PREPARED | \
+				V4L2_BUF_FLAG_TIMESTAMP_MASK)
+
+/* Output buffer flags that should be passed on to the driver */
+#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | \
+				V4L2_BUF_FLAG_BFRAME | \
+				V4L2_BUF_FLAG_KEYFRAME | \
+				V4L2_BUF_FLAG_TIMECODE)
+
+/**
+ * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
+ * returned to userspace
+ */
+static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
+{
+	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int plane;
+
+	/* Copy back data such as timestamp, flags, etc. */
+	b->index = vb->index;
+	b->type = vb->type;
+	b->memory = vb->memory;
+	b->bytesused = 0;
+
+	b->flags = vbuf->flags;
+	b->field = vbuf->field;
+	b->timestamp = vbuf->timestamp;
+	b->timecode = vbuf->timecode;
+	b->sequence = vbuf->sequence;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
+		/*
+		 * Fill in plane-related data if userspace provided an array
+		 * for it. The caller has already verified memory and size.
+		 */
+		b->length = vb->num_planes;
+		for (plane = 0; plane < vb->num_planes; ++plane) {
+			struct v4l2_plane *pdst = &b->m.planes[plane];
+			struct vb2_plane *psrc = &vb->planes[plane];
+
+			pdst->bytesused = psrc->bytesused;
+			pdst->length = psrc->length;
+			if (q->memory == V4L2_MEMORY_MMAP)
+				pdst->m.mem_offset = psrc->m.offset;
+			else if (q->memory == V4L2_MEMORY_USERPTR)
+				pdst->m.userptr = psrc->m.userptr;
+			else if (q->memory == V4L2_MEMORY_DMABUF)
+				pdst->m.fd = psrc->m.fd;
+			pdst->data_offset = psrc->data_offset;
+		}
+	} else {
+		/*
+		 * We use length and offset in v4l2_planes array even for
+		 * single-planar buffers, but userspace does not.
+		 */
+		b->length = vb->planes[0].length;
+		b->bytesused = vb->planes[0].bytesused;
+		if (q->memory == V4L2_MEMORY_MMAP)
+			b->m.offset = vb->planes[0].m.offset;
+		else if (q->memory == V4L2_MEMORY_USERPTR)
+			b->m.userptr = vb->planes[0].m.userptr;
+		else if (q->memory == V4L2_MEMORY_DMABUF)
+			b->m.fd = vb->planes[0].m.fd;
+	}
+
+	/*
+	 * Clear any buffer state related flags.
+	 */
+	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
+	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
+	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
+			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
+		/*
+		 * For non-COPY timestamps, drop timestamp source bits
+		 * and obtain the timestamp source from the queue.
+		 */
+		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+	}
+
+	switch (vb->state) {
+	case VB2_BUF_STATE_QUEUED:
+	case VB2_BUF_STATE_ACTIVE:
+		b->flags |= V4L2_BUF_FLAG_QUEUED;
+		break;
+	case VB2_BUF_STATE_ERROR:
+		b->flags |= V4L2_BUF_FLAG_ERROR;
+		/* fall through */
+	case VB2_BUF_STATE_DONE:
+		b->flags |= V4L2_BUF_FLAG_DONE;
+		break;
+	case VB2_BUF_STATE_PREPARED:
+		b->flags |= V4L2_BUF_FLAG_PREPARED;
+		break;
+	case VB2_BUF_STATE_PREPARING:
+	case VB2_BUF_STATE_DEQUEUED:
+		/* nothing */
+		break;
+	}
+
+	if (vb2_buffer_in_use(q, vb))
+		b->flags |= V4L2_BUF_FLAG_MAPPED;
+
+	return 0;
+}
+
+/**
+ * __verify_length() - Verify that the bytesused value for each plane fits in
+ * the plane length and that the data offset doesn't exceed the bytesused value.
+ */
+static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
+{
+	unsigned int length;
+	unsigned int bytesused;
+	unsigned int plane;
+
+	if (!V4L2_TYPE_IS_OUTPUT(b->type))
+		return 0;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+		for (plane = 0; plane < vb->num_planes; ++plane) {
+			length = (b->memory == V4L2_MEMORY_USERPTR ||
+				b->memory == V4L2_MEMORY_DMABUF)
+				? b->m.planes[plane].length
+				: vb->planes[plane].length;
+			bytesused = b->m.planes[plane].bytesused
+				? b->m.planes[plane].bytesused : length;
+
+			if (b->m.planes[plane].bytesused > length)
+				return -EINVAL;
+
+			if (b->m.planes[plane].data_offset > 0 &&
+				b->m.planes[plane].data_offset >= bytesused)
+				return -EINVAL;
+		}
+	} else {
+		length = (b->memory == V4L2_MEMORY_USERPTR)
+			? b->length : vb->planes[0].length;
+
+		if (b->bytesused > length)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
+ * v4l2_buffer by the userspace. It also verifies that struct
+ * v4l2_buffer has a valid number of planes.
+ */
+static int __fill_vb2_buffer(struct vb2_buffer *vb, void *pb,
+				struct vb2_plane *planes)
+{
+	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	unsigned int plane;
+	int ret;
+
+	ret = __verify_length(vb, b);
+	if (ret < 0) {
+		dprintk(1, "plane parameters verification failed: %d\n", ret);
+		return ret;
+	}
+	vb->state = VB2_BUF_STATE_PREPARING;
+	vbuf->timestamp.tv_sec = 0;
+	vbuf->timestamp.tv_usec = 0;
+	vbuf->sequence = 0;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+		if (b->memory == V4L2_MEMORY_USERPTR) {
+			for (plane = 0; plane < vb->num_planes; ++plane) {
+				planes[plane].m.userptr =
+					b->m.planes[plane].m.userptr;
+				planes[plane].length =
+					b->m.planes[plane].length;
+			}
+		}
+		if (b->memory == V4L2_MEMORY_DMABUF) {
+			for (plane = 0; plane < vb->num_planes; ++plane) {
+				planes[plane].m.fd =
+					b->m.planes[plane].m.fd;
+				planes[plane].length =
+					b->m.planes[plane].length;
+			}
+		}
+
+		/* Fill in driver-provided information for OUTPUT types */
+		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+			/*
+			 * Will have to go up to b->length when API starts
+			 * accepting variable number of planes.
+			 *
+			 * If bytesused == 0 for the output buffer, then fall
+			 * back to the full buffer size. In that case
+			 * userspace clearly never bothered to set it and
+			 * it's a safe assumption that they really meant to
+			 * use the full plane sizes.
+			 *
+			 * Some drivers, e.g. old codec drivers, use bytesused == 0
+			 * as a way to indicate that streaming is finished.
+			 * In that case, the driver should use the
+			 * allow_zero_bytesused flag to keep old userspace
+			 * applications working.
+			 */
+			for (plane = 0; plane < vb->num_planes; ++plane) {
+				struct vb2_plane *pdst = &planes[plane];
+				struct v4l2_plane *psrc = &b->m.planes[plane];
+
+				if (psrc->bytesused == 0)
+					vb2_warn_zero_bytesused(vb);
+
+				if (vb->vb2_queue->allow_zero_bytesused)
+					pdst->bytesused = psrc->bytesused;
+				else
+					pdst->bytesused = psrc->bytesused ?
+						psrc->bytesused : pdst->length;
+				pdst->data_offset = psrc->data_offset;
+			}
+		}
+	} else {
+		/*
+		 * Single-planar buffers do not use planes array,
+		 * so fill in relevant v4l2_buffer struct fields instead.
+		 * In videobuf we use our internal V4l2_planes struct for
+		 * single-planar buffers as well, for simplicity.
+		 *
+		 * If bytesused == 0 for the output buffer, then fall back
+		 * to the full buffer size as that's a sensible default.
+		 *
+		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
+		 * a way to indicate that streaming is finished. In that case,
+		 * the driver should use the allow_zero_bytesused flag to keep
+		 * old userspace applications working.
+		 */
+		if (b->memory == V4L2_MEMORY_USERPTR) {
+			planes[0].m.userptr = b->m.userptr;
+			planes[0].length = b->length;
+		}
+
+		if (b->memory == V4L2_MEMORY_DMABUF) {
+			planes[0].m.fd = b->m.fd;
+			planes[0].length = b->length;
+		}
+
+		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+			if (b->bytesused == 0)
+				vb2_warn_zero_bytesused(vb);
+
+			if (vb->vb2_queue->allow_zero_bytesused)
+				planes[0].bytesused = b->bytesused;
+			else
+				planes[0].bytesused = b->bytesused ?
+					b->bytesused : planes[0].length;
+		} else
+			planes[0].bytesused = 0;
+
+	}
+
+	/* Zero flags that the vb2 core handles */
+	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
+	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
+			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
+			!V4L2_TYPE_IS_OUTPUT(b->type)) {
+		/*
+		 * Non-COPY timestamps and non-OUTPUT queues will get
+		 * their timestamp and timestamp source flags from the
+		 * queue.
+		 */
+		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+	}
+
+	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+		/*
+		 * For output buffers mask out the timecode flag:
+		 * this will be handled later in vb2_internal_qbuf().
+		 * The 'field' is valid metadata for this output buffer
+		 * and so that needs to be copied here.
+		 */
+		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
+		vbuf->field = b->field;
+	} else {
+		/* Zero any output buffer flags as this is a capture buffer */
+		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
+	}
+
+	return 0;
+}
+
+static int __fill_vb2_timestamp(struct vb2_buffer *vb, void *pb)
+{
+	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vb2_queue *q = vb->vb2_queue;
+
+	/*
+	 * For output buffers copy the timestamp if needed,
+	 * and the timecode field and flag if needed.
+	 */
+	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+			V4L2_BUF_FLAG_TIMESTAMP_COPY)
+		vbuf->timestamp = b->timestamp;
+	vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
+	if (b->flags & V4L2_BUF_FLAG_TIMECODE)
+		vbuf->timecode = b->timecode;
+
+	return 0;
+};
+
+static int __is_last(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+	return (vbuf->flags & V4L2_BUF_FLAG_LAST);
+}
+
+const struct vb2_buf_ops v4l2_buf_ops = {
+	.fill_user_buffer	= __fill_v4l2_buffer,
+	.fill_vb2_buffer	= __fill_vb2_buffer,
+	.fill_vb2_timestamp	= __fill_vb2_timestamp,
+	.is_last		= __is_last,
+};
+
+/**
+ * vb2_querybuf() - query video buffer information
+ * @q:		videobuf queue
+ * @b:		buffer struct passed from userspace to vidioc_querybuf handler
+ *		in driver
+ *
+ * Should be called from vidioc_querybuf ioctl handler in driver.
+ * This function will verify the passed v4l2_buffer structure and fill the
+ * relevant information for the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_querybuf handler in driver.
+ */
+int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
+			b->length, b->m.planes, "querybuf");
+
+	return ret ? ret : vb2_core_querybuf(q, b->index, b);
+}
+EXPORT_SYMBOL(vb2_querybuf);
+
+/**
+ * vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies
+ * the memory and type values.
+ * @q:		videobuf2 queue
+ * @req:	struct passed from userspace to vidioc_reqbufs handler
+ *		in driver
+ */
+int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
+{
+	int ret = vb2_verify_memory_type(q, req->memory, req->type);
+
+	if (ret)
+		return ret;
+	if (vb2_fileio_is_active(q)) {
+		dprintk(1, "file io in progress\n");
+		return -EBUSY;
+	}
+
+	return vb2_core_reqbufs(q, req->memory, &req->count);
+}
+EXPORT_SYMBOL_GPL(vb2_reqbufs);
+
+/**
+ * vb2_create_bufs() - Wrapper for vb2_core_create_bufs() that also verifies
+ * the memory and type values.
+ * @q:		videobuf2 queue
+ * @create:	creation parameters, passed from userspace to vidioc_create_bufs
+ *		handler in driver
+ */
+int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
+{
+	int ret = vb2_verify_memory_type(q, create->memory, create->format.type);
+
+	if (ret)
+		return ret;
+	if (create->count && vb2_fileio_is_active(q)) {
+		dprintk(1, "file io in progress\n");
+		return -EBUSY;
+	}
+	return vb2_core_create_bufs(q, create->memory, &create->count, &create->format);
+}
+EXPORT_SYMBOL_GPL(vb2_create_bufs);
+
+/**
+ * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
+ * @q:		videobuf2 queue
+ * @b:		buffer structure passed from userspace to vidioc_prepare_buf
+ *		handler in driver
+ *
+ * Should be called from vidioc_prepare_buf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) calls buf_prepare callback in the driver (if provided), in which
+ *    driver-specific buffer initialization can be performed,
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_prepare_buf handler in driver.
+ */
+int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+	int ret;
+
+	if (vb2_fileio_is_active(q)) {
+		dprintk(1, "file io in progress\n");
+		return -EBUSY;
+	}
+
+	ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
+			b->length, b->m.planes, "prepare_buf");
+	if (ret)
+		return ret;
+
+	if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
+		/*
+		 * If the format's field is ALTERNATE, then the buffer's field
+		 * should be either TOP or BOTTOM, not ALTERNATE since that
+		 * makes no sense. The driver has to know whether the
+		 * buffer represents a top or a bottom field in order to
+		 * program any DMA correctly. Using ALTERNATE is wrong, since
+		 * that just says that it is either a top or a bottom field,
+		 * but not which of the two it is.
+		 */
+		dprintk(1, "the field is incorrectly set to ALTERNATE "
+				"for an output buffer\n");
+		return -EINVAL;
+	}
+
+	return vb2_core_prepare_buf(q, b->index, b);
+}
+EXPORT_SYMBOL_GPL(vb2_prepare_buf);
+
+static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
+			b->length, b->m.planes, "qbuf");
+	struct vb2_buffer *vb;
+
+	if (ret)
+		return ret;
+
+	vb = q->bufs[b->index];
+
+	if (vb->state == VB2_BUF_STATE_DEQUEUED
+			&& b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
+		dprintk(1, "the field is incorrectly set to ALTERNATE "
+				"for an output buffer\n");
+		return -EINVAL;
+	}
+
+	return ret ? ret : vb2_core_qbuf(q, b->index, b);
+}
+
+/**
+ * vb2_qbuf() - Queue a buffer from userspace
+ * @q:		videobuf2 queue
+ * @b:		buffer structure passed from userspace to vidioc_qbuf handler
+ *		in driver
+ *
+ * Should be called from vidioc_qbuf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
+ *    which driver-specific buffer initialization can be performed,
+ * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
+ *    callback for processing.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_qbuf handler in driver.
+ */
+int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+	if (vb2_fileio_is_active(q)) {
+		dprintk(1, "file io in progress\n");
+		return -EBUSY;
+	}
+
+	return vb2_internal_qbuf(q, b);
+}
+EXPORT_SYMBOL_GPL(vb2_qbuf);
+
+static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
+			bool nonblocking)
+{
+	if (b->type != q->type) {
+		dprintk(1, "invalid buffer type\n");
+		return -EINVAL;
+	}
+	return vb2_core_dqbuf(q, b, nonblocking);
+}
+
+/**
+ * vb2_dqbuf() - Dequeue a buffer to the userspace
+ * @q:		videobuf2 queue
+ * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
+ *		in driver
+ * @nonblocking: if true, this call will not sleep waiting for a buffer if no
+ *		 buffers ready for dequeuing are present. Normally the driver
+ *		 would be passing (file->f_flags & O_NONBLOCK) here
+ *
+ * Should be called from vidioc_dqbuf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) calls buf_finish callback in the driver (if provided), in which
+ *    driver can perform any additional operations that may be required before
+ *    returning the buffer to userspace, such as cache sync,
+ * 3) the buffer struct members are filled with relevant information for
+ *    the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_dqbuf handler in driver.
+ */
+int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
+{
+	if (vb2_fileio_is_active(q)) {
+		dprintk(1, "file io in progress\n");
+		return -EBUSY;
+	}
+	return vb2_internal_dqbuf(q, b, nonblocking);
+}
+EXPORT_SYMBOL_GPL(vb2_dqbuf);
+
+/**
+ * vb2_expbuf() - Export a buffer as a file descriptor
+ * @q:		videobuf2 queue
+ * @eb:		export buffer structure passed from userspace to vidioc_expbuf
+ *		handler in driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_expbuf handler in driver.
+ */
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
+{
+	if (vb2_fileio_is_active(q)) {
+		dprintk(1, "file io in progress\n");
+		return -EBUSY;
+	}
+
+	return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index,
+				eb->plane, eb->flags);
+}
+EXPORT_SYMBOL_GPL(vb2_expbuf);
+
+static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+	if (type != q->type) {
+		dprintk(1, "invalid stream type\n");
+		return -EINVAL;
+	}
+	return vb2_core_streamon(q);
+}
+
+/**
+ * vb2_streamon - start streaming
+ * @q:		videobuf2 queue
+ * @type:	type argument passed from userspace to vidioc_streamon handler
+ *
+ * Should be called from vidioc_streamon handler of a driver.
+ * This function:
+ * 1) verifies current state
+ * 2) passes any previously queued buffers to the driver and starts streaming
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_streamon handler in the driver.
+ */
+int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+	if (vb2_fileio_is_active(q)) {
+		dprintk(1, "file io in progress\n");
+		return -EBUSY;
+	}
+	return vb2_internal_streamon(q, type);
+}
+EXPORT_SYMBOL_GPL(vb2_streamon);
+
+static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+	if (type != q->type) {
+		dprintk(1, "invalid stream type\n");
+		return -EINVAL;
+	}
+	return vb2_core_streamoff(q);
+}
+
+/**
+ * vb2_streamoff - stop streaming
+ * @q:		videobuf2 queue
+ * @type:	type argument passed from userspace to vidioc_streamoff handler
+ *
+ * Should be called from vidioc_streamoff handler of a driver.
+ * This function:
+ * 1) verifies current state,
+ * 2) stop streaming and dequeues any queued buffers, including those previously
+ *    passed to the driver (after waiting for the driver to finish).
+ *
+ * This call can be used for pausing playback.
+ * The return values from this function are intended to be directly returned
+ * from vidioc_streamoff handler in the driver
+ */
+int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+	if (vb2_fileio_is_active(q)) {
+		dprintk(1, "file io in progress\n");
+		return -EBUSY;
+	}
+	return vb2_internal_streamoff(q, type);
+}
+EXPORT_SYMBOL_GPL(vb2_streamoff);
+
+/**
+ * vb2_mmap() - map video buffers into application address space
+ * @q:		videobuf2 queue
+ * @vma:	vma passed to the mmap file operation handler in the driver
+ *
+ * Should be called from mmap file operation handler of a driver.
+ * This function maps one plane of one of the available video buffers to
+ * userspace. To map whole video memory allocated on reqbufs, this function
+ * has to be called once per each plane per each buffer previously allocated.
+ *
+ * When the userspace application calls mmap, it passes to it an offset returned
+ * to it earlier by the means of vidioc_querybuf handler. That offset acts as
+ * a "cookie", which is then used to identify the plane to be mapped.
+ * This function finds a plane with a matching offset and a mapping is performed
+ * by the means of a provided memory operation.
+ *
+ * The return values from this function are intended to be directly returned
+ * from the mmap handler in driver.
+ */
+int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
+{
+	if (vb2_fileio_is_active(q)) {
+		dprintk(1, "mmap: file io in progress\n");
+		return -EBUSY;
+	}
+
+	return vb2_core_mmap(q, vma);
+}
+EXPORT_SYMBOL_GPL(vb2_mmap);
+
+static int __vb2_init_fileio(struct vb2_queue *q, int read);
+static int __vb2_cleanup_fileio(struct vb2_queue *q);
+
+/**
+ * vb2_poll() - implements poll userspace operation
+ * @q:		videobuf2 queue
+ * @file:	file argument passed to the poll file operation handler
+ * @wait:	wait argument passed to the poll file operation handler
+ *
+ * This function implements poll file operation handler for a driver.
+ * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
+ * be informed that the file descriptor of a video device is available for
+ * reading.
+ * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
+ * will be reported as available for writing.
+ *
+ * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
+ * pending events.
+ *
+ * The return values from this function are intended to be directly returned
+ * from poll handler in driver.
+ */
+unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
+{
+	struct video_device *vfd = video_devdata(file);
+	unsigned long req_events = poll_requested_events(wait);
+	struct vb2_buffer *vb = NULL;
+	unsigned int res = 0;
+	unsigned long flags;
+
+	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
+		struct v4l2_fh *fh = file->private_data;
+
+		if (v4l2_event_pending(fh))
+			res = POLLPRI;
+		else if (req_events & POLLPRI)
+			poll_wait(file, &fh->wait, wait);
+	}
+
+	if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
+		return res;
+	if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
+		return res;
+
+	/*
+	 * Start file I/O emulator only if streaming API has not been used yet.
+	 */
+	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
+		if (!q->is_output && (q->io_modes & VB2_READ) &&
+				(req_events & (POLLIN | POLLRDNORM))) {
+			if (__vb2_init_fileio(q, 1))
+				return res | POLLERR;
+		}
+		if (q->is_output && (q->io_modes & VB2_WRITE) &&
+				(req_events & (POLLOUT | POLLWRNORM))) {
+			if (__vb2_init_fileio(q, 0))
+				return res | POLLERR;
+			/*
+			 * Write to OUTPUT queue can be done immediately.
+			 */
+			return res | POLLOUT | POLLWRNORM;
+		}
+	}
+
+	/*
+	 * There is nothing to wait for if the queue isn't streaming, or if the
+	 * error flag is set.
+	 */
+	if (!vb2_is_streaming(q) || q->error)
+		return res | POLLERR;
+	/*
+	 * For compatibility with vb1: if QBUF hasn't been called yet, then
+	 * return POLLERR as well. This only affects capture queues, output
+	 * queues will always initialize waiting_for_buffers to false.
+	 */
+	if (q->waiting_for_buffers)
+		return res | POLLERR;
+
+	/*
+	 * For output streams you can write as long as there are fewer buffers
+	 * queued than there are buffers available.
+	 */
+	if (q->is_output && q->queued_count < q->num_buffers)
+		return res | POLLOUT | POLLWRNORM;
+
+	if (list_empty(&q->done_list)) {
+		/*
+		 * If the last buffer was dequeued from a capture queue,
+		 * return immediately. DQBUF will return -EPIPE.
+		 */
+		if (q->last_buffer_dequeued)
+			return res | POLLIN | POLLRDNORM;
+
+		poll_wait(file, &q->done_wq, wait);
+	}
+
+	/*
+	 * Take first buffer available for dequeuing.
+	 */
+	spin_lock_irqsave(&q->done_lock, flags);
+	if (!list_empty(&q->done_list))
+		vb = list_first_entry(&q->done_list, struct vb2_buffer,
+					done_entry);
+	spin_unlock_irqrestore(&q->done_lock, flags);
+
+	if (vb && (vb->state == VB2_BUF_STATE_DONE
+			|| vb->state == VB2_BUF_STATE_ERROR)) {
+		return (q->is_output) ?
+				res | POLLOUT | POLLWRNORM :
+				res | POLLIN | POLLRDNORM;
+	}
+	return res;
+}
+EXPORT_SYMBOL_GPL(vb2_poll);
+
+/**
+ * vb2_queue_init() - initialize a videobuf2 queue
+ * @q:		videobuf2 queue; this structure should be allocated in driver
+ *
+ * The vb2_queue structure should be allocated by the driver. The driver is
+ * responsible of clearing it's content and setting initial values for some
+ * required entries before calling this function.
+ * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
+ * to the struct vb2_queue description in include/media/videobuf2-core.h
+ * for more information.
+ */
+int vb2_queue_init(struct vb2_queue *q)
+{
+	if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
+		|| WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
+		|| WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
+		return -EINVAL;
+	/*
+	 * Sanity check
+	 */
+	if (WARN_ON(!q)	|| WARN_ON(!q->type))
+		return -EINVAL;
+
+	if (WARN_ON(q->timestamp_flags &
+		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
+		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
+		return -EINVAL;
+
+	/* Warn that the driver should choose an appropriate timestamp type */
+	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
+
+	if (q->buf_struct_size == 0)
+		q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
+
+	q->buf_ops = &v4l2_buf_ops;
+	q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
+	q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
+
+	return vb2_core_queue_init(q);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_init);
+
+/**
+ * vb2_queue_release() - stop streaming, release the queue and free memory
+ * @q:		videobuf2 queue
+ *
+ * This function stops streaming and performs necessary clean ups, including
+ * freeing video buffer memory. The driver is responsible for freeing
+ * the vb2_queue structure itself.
+ */
+void vb2_queue_release(struct vb2_queue *q)
+{
+	__vb2_cleanup_fileio(q);
+	vb2_core_queue_release(q);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_release);
+
+/**
+ * struct vb2_fileio_buf - buffer context used by file io emulator
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. This structure is used for
+ * tracking context related to the buffers.
+ */
+struct vb2_fileio_buf {
+	void *vaddr;
+	unsigned int size;
+	unsigned int pos;
+	unsigned int queued:1;
+};
+
+/**
+ * struct vb2_fileio_data - queue context used by file io emulator
+ *
+ * @cur_index:	the index of the buffer currently being read from or
+ *		written to. If equal to q->num_buffers then a new buffer
+ *		must be dequeued.
+ * @initial_index: in the read() case all buffers are queued up immediately
+ *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
+ *		buffers. However, in the write() case no buffers are initially
+ *		queued, instead whenever a buffer is full it is queued up by
+ *		__vb2_perform_fileio(). Only once all available buffers have
+ *		been queued up will __vb2_perform_fileio() start to dequeue
+ *		buffers. This means that initially __vb2_perform_fileio()
+ *		needs to know what buffer index to use when it is queuing up
+ *		the buffers for the first time. That initial index is stored
+ *		in this field. Once it is equal to q->num_buffers all
+ *		available buffers have been queued and __vb2_perform_fileio()
+ *		should start the normal dequeue/queue cycle.
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. For proper operation it required
+ * this structure to save the driver state between each call of the read
+ * or write function.
+ */
+struct vb2_fileio_data {
+	struct v4l2_requestbuffers req;
+	struct v4l2_plane p;
+	struct v4l2_buffer b;
+	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
+	unsigned int cur_index;
+	unsigned int initial_index;
+	unsigned int q_count;
+	unsigned int dq_count;
+	unsigned read_once:1;
+	unsigned write_immediately:1;
+};
+
+/**
+ * __vb2_init_fileio() - initialize file io emulator
+ * @q:		videobuf2 queue
+ * @read:	mode selector (1 means read, 0 means write)
+ */
+static int __vb2_init_fileio(struct vb2_queue *q, int read)
+{
+	struct vb2_fileio_data *fileio;
+	int i, ret;
+	unsigned int count = 0;
+
+	/*
+	 * Sanity check
+	 */
+	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
+			(!read && !(q->io_modes & VB2_WRITE))))
+		return -EINVAL;
+
+	/*
+	 * Check if device supports mapping buffers to kernel virtual space.
+	 */
+	if (!q->mem_ops->vaddr)
+		return -EBUSY;
+
+	/*
+	 * Check if streaming api has not been already activated.
+	 */
+	if (q->streaming || q->num_buffers > 0)
+		return -EBUSY;
+
+	/*
+	 * Start with count 1, driver can increase it in queue_setup()
+	 */
+	count = 1;
+
+	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, "
+		"write_immediately %d\n",
+		(read) ? "read" : "write", count, q->fileio_read_once,
+		q->fileio_write_immediately);
+
+	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
+	if (fileio == NULL)
+		return -ENOMEM;
+
+	fileio->read_once = q->fileio_read_once;
+	fileio->write_immediately = q->fileio_write_immediately;
+
+	/*
+	 * Request buffers and use MMAP type to force driver
+	 * to allocate buffers by itself.
+	 */
+	fileio->req.count = count;
+	fileio->req.memory = V4L2_MEMORY_MMAP;
+	fileio->req.type = q->type;
+	q->fileio = fileio;
+	ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
+	if (ret)
+		goto err_kfree;
+
+	/*
+	 * Check if plane_count is correct
+	 * (multiplane buffers are not supported).
+	 */
+	if (q->bufs[0]->num_planes != 1) {
+		ret = -EBUSY;
+		goto err_reqbufs;
+	}
+
+	/*
+	 * Get kernel address of each buffer.
+	 */
+	for (i = 0; i < q->num_buffers; i++) {
+		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+		if (fileio->bufs[i].vaddr == NULL) {
+			ret = -EINVAL;
+			goto err_reqbufs;
+		}
+		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
+	}
+
+	/*
+	 * Read mode requires pre queuing of all buffers.
+	 */
+	if (read) {
+		bool is_multiplanar = q->is_multiplanar;
+
+		/*
+		 * Queue all buffers.
+		 */
+		for (i = 0; i < q->num_buffers; i++) {
+			struct v4l2_buffer *b = &fileio->b;
+
+			memset(b, 0, sizeof(*b));
+			b->type = q->type;
+			if (is_multiplanar) {
+				memset(&fileio->p, 0, sizeof(fileio->p));
+				b->m.planes = &fileio->p;
+				b->length = 1;
+			}
+			b->memory = q->memory;
+			b->index = i;
+			ret = vb2_internal_qbuf(q, b);
+			if (ret)
+				goto err_reqbufs;
+			fileio->bufs[i].queued = 1;
+		}
+		/*
+		 * All buffers have been queued, so mark that by setting
+		 * initial_index to q->num_buffers
+		 */
+		fileio->initial_index = q->num_buffers;
+		fileio->cur_index = q->num_buffers;
+	}
+
+	/*
+	 * Start streaming.
+	 */
+	ret = vb2_internal_streamon(q, q->type);
+	if (ret)
+		goto err_reqbufs;
+
+	return ret;
+
+err_reqbufs:
+	fileio->req.count = 0;
+	vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
+
+err_kfree:
+	q->fileio = NULL;
+	kfree(fileio);
+	return ret;
+}
+
+/**
+ * __vb2_cleanup_fileio() - free resourced used by file io emulator
+ * @q:		videobuf2 queue
+ */
+static int __vb2_cleanup_fileio(struct vb2_queue *q)
+{
+	struct vb2_fileio_data *fileio = q->fileio;
+
+	if (fileio) {
+		vb2_internal_streamoff(q, q->type);
+		q->fileio = NULL;
+		fileio->req.count = 0;
+		vb2_reqbufs(q, &fileio->req);
+		kfree(fileio);
+		dprintk(3, "file io emulator closed\n");
+	}
+	return 0;
+}
+
+/**
+ * __vb2_perform_fileio() - perform a single file io (read or write) operation
+ * @q:		videobuf2 queue
+ * @data:	pointed to target userspace buffer
+ * @count:	number of bytes to read or write
+ * @ppos:	file handle position tracking pointer
+ * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
+ * @read:	access mode selector (1 means read, 0 means write)
+ */
+static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data,
+		size_t count, loff_t *ppos, int nonblock, int read)
+{
+	struct vb2_fileio_data *fileio;
+	struct vb2_fileio_buf *buf;
+	bool is_multiplanar = q->is_multiplanar;
+	/*
+	 * When using write() to write data to an output video node the vb2 core
+	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
+	 * else is able to provide this information with the write() operation.
+	 */
+	bool set_timestamp = !read &&
+		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+		V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	int ret, index;
+
+	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
+		read ? "read" : "write", (long)*ppos, count,
+		nonblock ? "non" : "");
+
+	if (!data)
+		return -EINVAL;
+
+	/*
+	 * Initialize emulator on first call.
+	 */
+	if (!vb2_fileio_is_active(q)) {
+		ret = __vb2_init_fileio(q, read);
+		dprintk(3, "vb2_init_fileio result: %d\n", ret);
+		if (ret)
+			return ret;
+	}
+	fileio = q->fileio;
+
+	/*
+	 * Check if we need to dequeue the buffer.
+	 */
+	index = fileio->cur_index;
+	if (index >= q->num_buffers) {
+		/*
+		 * Call vb2_dqbuf to get buffer back.
+		 */
+		memset(&fileio->b, 0, sizeof(fileio->b));
+		fileio->b.type = q->type;
+		fileio->b.memory = q->memory;
+		if (is_multiplanar) {
+			memset(&fileio->p, 0, sizeof(fileio->p));
+			fileio->b.m.planes = &fileio->p;
+			fileio->b.length = 1;
+		}
+		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
+		dprintk(5, "vb2_dqbuf result: %d\n", ret);
+		if (ret)
+			return ret;
+		fileio->dq_count += 1;
+
+		fileio->cur_index = index = fileio->b.index;
+		buf = &fileio->bufs[index];
+
+		/*
+		 * Get number of bytes filled by the driver
+		 */
+		buf->pos = 0;
+		buf->queued = 0;
+		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
+				 : vb2_plane_size(q->bufs[index], 0);
+
+		/*
+		 * Compensate for data_offset on read
+		 * in the multiplanar case.
+		 */
+		if (is_multiplanar && read &&
+			fileio->b.m.planes[0].data_offset < buf->size) {
+			buf->pos = fileio->b.m.planes[0].data_offset;
+			buf->size -= buf->pos;
+		}
+	} else {
+		buf = &fileio->bufs[index];
+	}
+
+	/*
+	 * Limit count on last few bytes of the buffer.
+	 */
+	if (buf->pos + count > buf->size) {
+		count = buf->size - buf->pos;
+		dprintk(5, "reducing read count: %zd\n", count);
+	}
+
+	/*
+	 * Transfer data to userspace.
+	 */
+	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
+		count, index, buf->pos);
+	if (read)
+		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
+	else
+		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
+	if (ret) {
+		dprintk(3, "error copying data\n");
+		return -EFAULT;
+	}
+
+	/*
+	 * Update counters.
+	 */
+	buf->pos += count;
+	*ppos += count;
+
+	/*
+	 * Queue next buffer if required.
+	 */
+	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
+		/*
+		 * Check if this is the last buffer to read.
+		 */
+		if (read && fileio->read_once && fileio->dq_count == 1) {
+			dprintk(3, "read limit reached\n");
+			return __vb2_cleanup_fileio(q);
+		}
+
+		/*
+		 * Call vb2_qbuf and give buffer to the driver.
+		 */
+		memset(&fileio->b, 0, sizeof(fileio->b));
+		fileio->b.type = q->type;
+		fileio->b.memory = q->memory;
+		fileio->b.index = index;
+		fileio->b.bytesused = buf->pos;
+		if (is_multiplanar) {
+			memset(&fileio->p, 0, sizeof(fileio->p));
+			fileio->p.bytesused = buf->pos;
+			fileio->b.m.planes = &fileio->p;
+			fileio->b.length = 1;
+		}
+		if (set_timestamp)
+			v4l2_get_timestamp(&fileio->b.timestamp);
+		ret = vb2_internal_qbuf(q, &fileio->b);
+		dprintk(5, "vb2_dbuf result: %d\n", ret);
+		if (ret)
+			return ret;
+
+		/*
+		 * Buffer has been queued, update the status
+		 */
+		buf->pos = 0;
+		buf->queued = 1;
+		buf->size = vb2_plane_size(q->bufs[index], 0);
+		fileio->q_count += 1;
+		/*
+		 * If we are queuing up buffers for the first time, then
+		 * increase initial_index by one.
+		 */
+		if (fileio->initial_index < q->num_buffers)
+			fileio->initial_index++;
+		/*
+		 * The next buffer to use is either a buffer that's going to be
+		 * queued for the first time (initial_index < q->num_buffers)
+		 * or it is equal to q->num_buffers, meaning that the next
+		 * time we need to dequeue a buffer since we've now queued up
+		 * all the 'first time' buffers.
+		 */
+		fileio->cur_index = fileio->initial_index;
+	}
+
+	/*
+	 * Return proper number of bytes processed.
+	 */
+	if (ret == 0)
+		ret = count;
+	return ret;
+}
+
+size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+		loff_t *ppos, int nonblocking)
+{
+	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
+}
+EXPORT_SYMBOL_GPL(vb2_read);
+
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
+		loff_t *ppos, int nonblocking)
+{
+	return __vb2_perform_fileio(q, (char __user *) data, count,
+							ppos, nonblocking, 0);
+}
+EXPORT_SYMBOL_GPL(vb2_write);
+
+struct vb2_threadio_data {
+	struct task_struct *thread;
+	vb2_thread_fnc fnc;
+	void *priv;
+	bool stop;
+};
+
+static int vb2_thread(void *data)
+{
+	struct vb2_queue *q = data;
+	struct vb2_threadio_data *threadio = q->threadio;
+	struct vb2_fileio_data *fileio = q->fileio;
+	bool set_timestamp = false;
+	int prequeue = 0;
+	int index = 0;
+	int ret = 0;
+
+	if (q->is_output) {
+		prequeue = q->num_buffers;
+		set_timestamp =
+			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
+			V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	}
+
+	set_freezable();
+
+	for (;;) {
+		struct vb2_buffer *vb;
+
+		/*
+		 * Call vb2_dqbuf to get buffer back.
+		 */
+		memset(&fileio->b, 0, sizeof(fileio->b));
+		fileio->b.type = q->type;
+		fileio->b.memory = q->memory;
+		if (prequeue) {
+			fileio->b.index = index++;
+			prequeue--;
+		} else {
+			call_void_qop(q, wait_finish, q);
+			if (!threadio->stop)
+				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
+			call_void_qop(q, wait_prepare, q);
+			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
+		}
+		if (ret || threadio->stop)
+			break;
+		try_to_freeze();
+
+		vb = q->bufs[fileio->b.index];
+		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
+			if (threadio->fnc(vb, threadio->priv))
+				break;
+		call_void_qop(q, wait_finish, q);
+		if (set_timestamp)
+			v4l2_get_timestamp(&fileio->b.timestamp);
+		if (!threadio->stop)
+			ret = vb2_internal_qbuf(q, &fileio->b);
+		call_void_qop(q, wait_prepare, q);
+		if (ret || threadio->stop)
+			break;
+	}
+
+	/* Hmm, linux becomes *very* unhappy without this ... */
+	while (!kthread_should_stop()) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+	}
+	return 0;
+}
+
+/*
+ * This function should not be used for anything else but the videobuf2-dvb
+ * support. If you think you have another good use-case for this, then please
+ * contact the linux-media mailinglist first.
+ */
+int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
+			const char *thread_name)
+{
+	struct vb2_threadio_data *threadio;
+	int ret = 0;
+
+	if (q->threadio)
+		return -EBUSY;
+	if (vb2_is_busy(q))
+		return -EBUSY;
+	if (WARN_ON(q->fileio))
+		return -EBUSY;
+
+	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
+	if (threadio == NULL)
+		return -ENOMEM;
+	threadio->fnc = fnc;
+	threadio->priv = priv;
+
+	ret = __vb2_init_fileio(q, !q->is_output);
+	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
+	if (ret)
+		goto nomem;
+	q->threadio = threadio;
+	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
+	if (IS_ERR(threadio->thread)) {
+		ret = PTR_ERR(threadio->thread);
+		threadio->thread = NULL;
+		goto nothread;
+	}
+	return 0;
+
+nothread:
+	__vb2_cleanup_fileio(q);
+nomem:
+	kfree(threadio);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_thread_start);
+
+int vb2_thread_stop(struct vb2_queue *q)
+{
+	struct vb2_threadio_data *threadio = q->threadio;
+	int err;
+
+	if (threadio == NULL)
+		return 0;
+	threadio->stop = true;
+	/* Wake up all pending sleeps in the thread */
+	vb2_queue_error(q);
+	err = kthread_stop(threadio->thread);
+	__vb2_cleanup_fileio(q);
+	threadio->thread = NULL;
+	kfree(threadio);
+	q->threadio = NULL;
+	return err;
+}
+EXPORT_SYMBOL_GPL(vb2_thread_stop);
+
+/*
+ * The following functions are not part of the vb2 core API, but are helper
+ * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
+ * and struct vb2_ops.
+ * They contain boilerplate code that most if not all drivers have to do
+ * and so they simplify the driver code.
+ */
+
+/* The queue is busy if there is a owner and you are not that owner. */
+static inline
+bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
+{
+	return vdev->queue->owner && vdev->queue->owner != file->private_data;
+}
+
+/* vb2 ioctl helpers */
+
+int vb2_ioctl_reqbufs(struct file *file, void *priv,
+			  struct v4l2_requestbuffers *p)
+{
+	struct video_device *vdev = video_devdata(file);
+	int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
+
+	if (res)
+		return res;
+	if (vb2_fileio_is_active(vdev->queue))
+		return -EBUSY;
+	if (vb2_queue_is_busy(vdev, file))
+		return -EBUSY;
+	res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count);
+	/* If count == 0, then the owner has released all buffers and he
+	   is no longer owner of the queue. Otherwise we have a new owner. */
+	if (res == 0)
+		vdev->queue->owner = p->count ? file->private_data : NULL;
+	return res;
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
+
+int vb2_ioctl_create_bufs(struct file *file, void *priv,
+			  struct v4l2_create_buffers *p)
+{
+	struct video_device *vdev = video_devdata(file);
+	int res = vb2_verify_memory_type(vdev->queue,
+				p->memory, p->format.type);
+
+	if (vb2_fileio_is_active(vdev->queue))
+		return -EBUSY;
+	p->index = vdev->queue->num_buffers;
+	/* If count == 0, then just check if memory and type are valid.
+	   Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. */
+	if (p->count == 0)
+		return res != -EBUSY ? res : 0;
+	if (res)
+		return res;
+	if (vb2_queue_is_busy(vdev, file))
+		return -EBUSY;
+	res = vb2_core_create_bufs(vdev->queue,
+				p->memory, &p->count, &p->format);
+	if (res == 0)
+		vdev->queue->owner = file->private_data;
+	return res;
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
+
+int vb2_ioctl_prepare_buf(struct file *file, void *priv,
+			  struct v4l2_buffer *p)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_queue_is_busy(vdev, file))
+		return -EBUSY;
+	return vb2_prepare_buf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
+
+int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
+	return vb2_querybuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
+
+int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_queue_is_busy(vdev, file))
+		return -EBUSY;
+	return vb2_qbuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
+
+int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_queue_is_busy(vdev, file))
+		return -EBUSY;
+	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
+
+int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_queue_is_busy(vdev, file))
+		return -EBUSY;
+	return vb2_streamon(vdev->queue, i);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
+
+int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_queue_is_busy(vdev, file))
+		return -EBUSY;
+	return vb2_streamoff(vdev->queue, i);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
+
+int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_queue_is_busy(vdev, file))
+		return -EBUSY;
+	return vb2_expbuf(vdev->queue, p);
+}
+EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
+
+/* v4l2_file_operations helpers */
+
+int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (vb2_fileio_is_active(vdev->queue)) {
+		dprintk(1, "mmap: file io in progress\n");
+		return -EBUSY;
+	}
+
+	return vb2_mmap(vdev->queue, vma);
+}
+EXPORT_SYMBOL_GPL(vb2_fop_mmap);
+
+int _vb2_fop_release(struct file *file, struct mutex *lock)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	if (lock)
+		mutex_lock(lock);
+	if (file->private_data == vdev->queue->owner) {
+		vb2_queue_release(vdev->queue);
+		vdev->queue->owner = NULL;
+	}
+	if (lock)
+		mutex_unlock(lock);
+	return v4l2_fh_release(file);
+}
+EXPORT_SYMBOL_GPL(_vb2_fop_release);
+
+int vb2_fop_release(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+
+	return _vb2_fop_release(file, lock);
+}
+EXPORT_SYMBOL_GPL(vb2_fop_release);
+
+ssize_t vb2_fop_write(struct file *file, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+	int err = -EBUSY;
+
+	if (!(vdev->queue->io_modes & VB2_WRITE))
+		return -EINVAL;
+	if (lock && mutex_lock_interruptible(lock))
+		return -ERESTARTSYS;
+	if (vb2_queue_is_busy(vdev, file))
+		goto exit;
+	err = vb2_write(vdev->queue, buf, count, ppos,
+			file->f_flags & O_NONBLOCK);
+	if (vdev->queue->fileio)
+		vdev->queue->owner = file->private_data;
+exit:
+	if (lock)
+		mutex_unlock(lock);
+	return err;
+}
+EXPORT_SYMBOL_GPL(vb2_fop_write);
+
+ssize_t vb2_fop_read(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
+	int err = -EBUSY;
+
+	if (!(vdev->queue->io_modes & VB2_READ))
+		return -EINVAL;
+	if (lock && mutex_lock_interruptible(lock))
+		return -ERESTARTSYS;
+	if (vb2_queue_is_busy(vdev, file))
+		goto exit;
+	err = vb2_read(vdev->queue, buf, count, ppos,
+			file->f_flags & O_NONBLOCK);
+	if (vdev->queue->fileio)
+		vdev->queue->owner = file->private_data;
+exit:
+	if (lock)
+		mutex_unlock(lock);
+	return err;
+}
+EXPORT_SYMBOL_GPL(vb2_fop_read);
+
+unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct vb2_queue *q = vdev->queue;
+	struct mutex *lock = q->lock ? q->lock : vdev->lock;
+	unsigned res;
+	void *fileio;
+
+	/*
+	 * If this helper doesn't know how to lock, then you shouldn't be using
+	 * it but you should write your own.
+	 */
+	WARN_ON(!lock);
+
+	if (lock && mutex_lock_interruptible(lock))
+		return POLLERR;
+
+	fileio = q->fileio;
+
+	res = vb2_poll(vdev->queue, file, wait);
+
+	/* If fileio was started, then we have a new queue owner. */
+	if (!fileio && q->fileio)
+		q->owner = file->private_data;
+	if (lock)
+		mutex_unlock(lock);
+	return res;
+}
+EXPORT_SYMBOL_GPL(vb2_fop_poll);
+
+#ifndef CONFIG_MMU
+unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
+		unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
+}
+EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
+#endif
+
+/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
+
+void vb2_ops_wait_prepare(struct vb2_queue *vq)
+{
+	mutex_unlock(vq->lock);
+}
+EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
+
+void vb2_ops_wait_finish(struct vb2_queue *vq)
+{
+	mutex_lock(vq->lock);
+}
+EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
+
 MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
 MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
 MODULE_LICENSE("GPL");
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 09d7529..4044bed 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -15,9 +15,18 @@
 #include <linux/mm_types.h>
 #include <linux/mutex.h>
 #include <linux/poll.h>
-#include <linux/videodev2.h>
 #include <linux/dma-buf.h>
 
+#define VB2_MAX_FRAME	(32)
+#define VB2_MAX_PLANES	(8)
+
+enum vb2_memory {
+	VB2_MEMORY_UNKNOWN	= 0,
+	VB2_MEMORY_MMAP		= 1,
+	VB2_MEMORY_USERPTR	= 2,
+	VB2_MEMORY_DMABUF	= 4,
+};
+
 struct vb2_alloc_ctx;
 struct vb2_fileio_data;
 struct vb2_threadio_data;
@@ -198,7 +207,7 @@ struct vb2_buffer {
 	unsigned int		type;
 	unsigned int		memory;
 	unsigned int		num_planes;
-	struct vb2_plane	planes[VIDEO_MAX_PLANES];
+	struct vb2_plane	planes[VB2_MAX_PLANES];
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	/*
@@ -330,18 +339,24 @@ struct vb2_ops {
 	void (*buf_queue)(struct vb2_buffer *vb);
 };
 
-struct v4l2_fh;
+struct vb2_buf_ops {
+	int (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
+	int (*fill_vb2_buffer)(struct vb2_buffer *vb, void *pb,
+				struct vb2_plane *planes);
+	int (*fill_vb2_timestamp)(struct vb2_buffer *vb, void *pb);
+	int (*is_last)(struct vb2_buffer *vb);
+};
 
 /**
  * struct vb2_queue - a videobuf queue
  *
- * @type:	queue type (see V4L2_BUF_TYPE_* in linux/videodev2.h
+ * @type:	queue type (see VB2_BUF_TYPE_*)
  * @io_modes:	supported io methods (see vb2_io_modes enum)
  * @fileio_read_once:		report EOF after reading the first buffer
  * @fileio_write_immediately:	queue buffer after each write() call
  * @allow_zero_bytesused:	allow bytesused == 0 to be passed to the driver
  * @lock:	pointer to a mutex that protects the vb2_queue struct. The
- *		driver can set this to a mutex to let the v4l2 core serialize
+ *		driver can set this to a mutex to let the vb2 core serialize
  *		the queuing ioctls. If the driver wants to handle locking
  *		itself, then this should be set to NULL. This lock is not used
  *		by the videobuf2 core API.
@@ -351,10 +366,13 @@ struct v4l2_fh;
  *		drivers to easily associate an owner filehandle with the queue.
  * @ops:	driver-specific callbacks
  * @mem_ops:	memory allocator specific callbacks
+ * @buf_ops:	callbacks to deliver buffer information
+ *		between user-space and kernel-space
  * @drv_priv:	driver private data
  * @buf_struct_size: size of the driver-specific buffer structure;
  *		"0" indicates the driver doesn't want to use a custom buffer
- *		structure type, so sizeof(struct vb2_buffer) will is used
+ *		structure type, so, sizeof(struct vb2_v4l2_buffer) will is used
+ *		in case of v4l2.
  * @timestamp_flags: Timestamp flags; V4L2_BUF_FLAG_TIMESTAMP_* and
  *		V4L2_BUF_FLAG_TSTAMP_SRC_*
  * @gfp_flags:	additional gfp flags used when allocating the buffers.
@@ -385,6 +403,8 @@ struct v4l2_fh;
  * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
  *		buffers. Only set for capture queues if qbuf has not yet been
  *		called since poll() needs to return POLLERR in that situation.
+ * @is_multiplanar: set if buffer type is multiplanar
+ * @is_output:	set if buffer type is output
  * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
  *		last decoded buffer was already dequeued. Set for capture queues
  *		when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
@@ -399,10 +419,12 @@ struct vb2_queue {
 	unsigned			allow_zero_bytesused:1;
 
 	struct mutex			*lock;
-	struct v4l2_fh			*owner;
+	void				*owner;
 
 	const struct vb2_ops		*ops;
 	const struct vb2_mem_ops	*mem_ops;
+	const struct vb2_buf_ops	*buf_ops;
+
 	void				*drv_priv;
 	unsigned int			buf_struct_size;
 	u32				timestamp_flags;
@@ -412,7 +434,7 @@ struct vb2_queue {
 	/* private: internal use only */
 	struct mutex			mmap_lock;
 	unsigned int			memory;
-	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
+	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
 	unsigned int			num_buffers;
 
 	struct list_head		queued_list;
@@ -423,13 +445,15 @@ struct vb2_queue {
 	spinlock_t			done_lock;
 	wait_queue_head_t		done_wq;
 
-	void				*alloc_ctx[VIDEO_MAX_PLANES];
-	unsigned int			plane_sizes[VIDEO_MAX_PLANES];
+	void				*alloc_ctx[VB2_MAX_PLANES];
+	unsigned int			plane_sizes[VB2_MAX_PLANES];
 
 	unsigned int			streaming:1;
 	unsigned int			start_streaming_called:1;
 	unsigned int			error:1;
 	unsigned int			waiting_for_buffers:1;
+	unsigned int			is_multiplanar:1;
+	unsigned int			is_output:1;
 	unsigned int			last_buffer_dequeued:1;
 
 	struct vb2_fileio_data		*fileio;
@@ -455,25 +479,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
 void vb2_discard_done(struct vb2_queue *q);
 int vb2_wait_for_all_buffers(struct vb2_queue *q);
 
-int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
-int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
-
-int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
-int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
-
-int __must_check vb2_queue_init(struct vb2_queue *q);
-
-void vb2_queue_release(struct vb2_queue *q);
 void vb2_queue_error(struct vb2_queue *q);
-
-int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
-int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
-int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
-
-int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
-int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
-
-int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
 #ifndef CONFIG_MMU
 unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 				    unsigned long addr,
@@ -481,41 +487,6 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
 				    unsigned long pgoff,
 				    unsigned long flags);
 #endif
-unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
-size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
-		loff_t *ppos, int nonblock);
-size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
-		loff_t *ppos, int nonblock);
-
-/*
- * vb2_thread_fnc - callback function for use with vb2_thread
- *
- * This is called whenever a buffer is dequeued in the thread.
- */
-typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
-
-/**
- * vb2_thread_start() - start a thread for the given queue.
- * @q:		videobuf queue
- * @fnc:	callback function
- * @priv:	priv pointer passed to the callback function
- * @thread_name:the name of the thread. This will be prefixed with "vb2-".
- *
- * This starts a thread that will queue and dequeue until an error occurs
- * or @vb2_thread_stop is called.
- *
- * This function should not be used for anything else but the videobuf2-dvb
- * support. If you think you have another good use-case for this, then please
- * contact the linux-media mailinglist first.
- */
-int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
-		     const char *thread_name);
-
-/**
- * vb2_thread_stop() - stop the thread for the given queue.
- * @q:		videobuf queue
- */
-int vb2_thread_stop(struct vb2_queue *q);
 
 /**
  * vb2_is_streaming() - return streaming status of the queue
@@ -527,23 +498,6 @@ static inline bool vb2_is_streaming(struct vb2_queue *q)
 }
 
 /**
- * vb2_fileio_is_active() - return true if fileio is active.
- * @q:		videobuf queue
- *
- * This returns true if read() or write() is used to stream the data
- * as opposed to stream I/O. This is almost never an important distinction,
- * except in rare cases. One such case is that using read() or write() to
- * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
- * is no way you can pass the field information of each buffer to/from
- * userspace. A driver that supports this field format should check for
- * this in the queue_setup op and reject it if this function returns true.
- */
-static inline bool vb2_fileio_is_active(struct vb2_queue *q)
-{
-	return q->fileio;
-}
-
-/**
  * vb2_is_busy() - return busy status of the queue
  * @q:		videobuf queue
  *
@@ -620,47 +574,4 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q)
 	q->last_buffer_dequeued = false;
 }
 
-/*
- * The following functions are not part of the vb2 core API, but are simple
- * helper functions that you can use in your struct v4l2_file_operations,
- * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock
- * or video_device->lock is set, and they will set and test vb2_queue->owner
- * to check if the calling filehandle is permitted to do the queuing operation.
- */
-
-/* struct v4l2_ioctl_ops helpers */
-
-int vb2_ioctl_reqbufs(struct file *file, void *priv,
-			  struct v4l2_requestbuffers *p);
-int vb2_ioctl_create_bufs(struct file *file, void *priv,
-			  struct v4l2_create_buffers *p);
-int vb2_ioctl_prepare_buf(struct file *file, void *priv,
-			  struct v4l2_buffer *p);
-int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
-int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
-int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
-int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
-int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
-int vb2_ioctl_expbuf(struct file *file, void *priv,
-	struct v4l2_exportbuffer *p);
-
-/* struct v4l2_file_operations helpers */
-
-int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
-int vb2_fop_release(struct file *file);
-int _vb2_fop_release(struct file *file, struct mutex *lock);
-ssize_t vb2_fop_write(struct file *file, const char __user *buf,
-		size_t count, loff_t *ppos);
-ssize_t vb2_fop_read(struct file *file, char __user *buf,
-		size_t count, loff_t *ppos);
-unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
-#ifndef CONFIG_MMU
-unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
-		unsigned long len, unsigned long pgoff, unsigned long flags);
-#endif
-
-/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
-
-void vb2_ops_wait_prepare(struct vb2_queue *vq);
-void vb2_ops_wait_finish(struct vb2_queue *vq);
 #endif /* _MEDIA_VIDEOBUF2_CORE_H */
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index fc2dbe9..790cb7a 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -40,4 +40,120 @@ struct vb2_v4l2_buffer {
 #define to_vb2_v4l2_buffer(vb) \
 	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
 
+
+int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
+
+int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
+int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
+
+int __must_check vb2_queue_init(struct vb2_queue *q);
+
+void vb2_queue_release(struct vb2_queue *q);
+
+int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
+int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
+int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
+
+int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
+int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
+int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
+unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
+size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+		loff_t *ppos, int nonblock);
+size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
+		loff_t *ppos, int nonblock);
+
+/*
+ * vb2_thread_fnc - callback function for use with vb2_thread
+ *
+ * This is called whenever a buffer is dequeued in the thread.
+ */
+typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
+
+/**
+ * vb2_thread_start() - start a thread for the given queue.
+ * @q:		videobuf queue
+ * @fnc:	callback function
+ * @priv:	priv pointer passed to the callback function
+ * @thread_name:the name of the thread. This will be prefixed with "vb2-".
+ *
+ * This starts a thread that will queue and dequeue until an error occurs
+ * or @vb2_thread_stop is called.
+ *
+ * This function should not be used for anything else but the videobuf2-dvb
+ * support. If you think you have another good use-case for this, then please
+ * contact the linux-media mailinglist first.
+ */
+int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
+		     const char *thread_name);
+
+/**
+ * vb2_thread_stop() - stop the thread for the given queue.
+ * @q:		videobuf queue
+ */
+int vb2_thread_stop(struct vb2_queue *q);
+
+/**
+ * vb2_fileio_is_active() - return true if fileio is active.
+ * @q:		videobuf queue
+ *
+ * This returns true if read() or write() is used to stream the data
+ * as opposed to stream I/O. This is almost never an important distinction,
+ * except in rare cases. One such case is that using read() or write() to
+ * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
+ * is no way you can pass the field information of each buffer to/from
+ * userspace. A driver that supports this field format should check for
+ * this in the queue_setup op and reject it if this function returns true.
+ */
+static inline bool vb2_fileio_is_active(struct vb2_queue *q)
+{
+	return q->fileio;
+}
+
+/*
+ * The following functions are not part of the vb2 core API, but are simple
+ * helper functions that you can use in your struct v4l2_file_operations,
+ * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize
+ * if vb2_queue->lock or video_device->lock is set, and they will set
+ * and test vb2_queue->owner to check if the calling filehandle is permitted
+ * to do the queuing operation.
+ */
+
+/* struct v4l2_ioctl_ops helpers */
+
+int vb2_ioctl_reqbufs(struct file *file, void *priv,
+			  struct v4l2_requestbuffers *p);
+int vb2_ioctl_create_bufs(struct file *file, void *priv,
+			  struct v4l2_create_buffers *p);
+int vb2_ioctl_prepare_buf(struct file *file, void *priv,
+			  struct v4l2_buffer *p);
+int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
+int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
+int vb2_ioctl_expbuf(struct file *file, void *priv,
+	struct v4l2_exportbuffer *p);
+
+/* struct v4l2_file_operations helpers */
+
+int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
+int vb2_fop_release(struct file *file);
+int _vb2_fop_release(struct file *file, struct mutex *lock);
+ssize_t vb2_fop_write(struct file *file, const char __user *buf,
+		size_t count, loff_t *ppos);
+ssize_t vb2_fop_read(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos);
+unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
+#ifndef CONFIG_MMU
+unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
+		unsigned long len, unsigned long pgoff, unsigned long flags);
+#endif
+
+/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
+
+void vb2_ops_wait_prepare(struct vb2_queue *vq);
+void vb2_ops_wait_finish(struct vb2_queue *vq);
+
 #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
index b015b38..f31b258 100644
--- a/include/trace/events/v4l2.h
+++ b/include/trace/events/v4l2.h
@@ -5,6 +5,7 @@
 #define _TRACE_V4L2_H
 
 #include <linux/tracepoint.h>
+#include <media/videobuf2-v4l2.h>
 
 /* Enums require being exported to userspace, for user tool parsing */
 #undef EM
@@ -203,7 +204,8 @@ DECLARE_EVENT_CLASS(vb2_event_class,
 
 	TP_fast_assign(
 		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-		__entry->minor = q->owner ? q->owner->vdev->minor : -1;
+		struct v4l2_fh *owner = (struct v4l2_fh *) q->owner;
+		__entry->minor = owner ? owner->vdev->minor : -1;
 		__entry->queued_count = q->queued_count;
 		__entry->owned_by_drv_count =
 			atomic_read(&q->owned_by_drv_count);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 1/5] media: videobuf2: Replace videobuf2-core with videobuf2-v4l2
  2015-08-26 11:59 ` [RFC PATCH v3 1/5] media: videobuf2: Replace videobuf2-core with videobuf2-v4l2 Junghak Sung
@ 2015-08-27  8:51   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2015-08-27  8:51 UTC (permalink / raw)
  To: Junghak Sung
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Em Wed, 26 Aug 2015 20:59:28 +0900
Junghak Sung <jh1009.sung@samsung.com> escreveu:

> Make videobuf2-v4l2 as a wrapper of videobuf2-core for v4l2-use.
> And replace videobuf2-core.h with videobuf2-v4l2.h.
> This renaming change should be accompanied by the modifications
> of all device drivers that include videobuf2-core.h.
> It can be done with just running this shell script.
> 
> replace()
> {
> str1=$1
> str2=$2
> dir=$3
> for file in $(find $dir -name *.h -o -name *.c -o -name Makefile)
> do
>     echo $file
>     sed "s/$str1/$str2/g" $file > $file.out
>     mv $file.out $file
> done
> }
> 
> replace "videobuf2-core" "videobuf2-v4l2" "include/media/"
> replace "videobuf2-core" "videobuf2-v4l2" "drivers/media/"
> replace "videobuf2-core" "videobuf2-v4l2" "drivers/usb/gadget/"

Looks OK for me.

> 
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
> ---
>  drivers/media/pci/solo6x10/solo6x10.h              |    2 +-
>  drivers/media/platform/coda/coda-bit.c             |    2 +-
>  drivers/media/platform/coda/coda-common.c          |    2 +-
>  drivers/media/platform/coda/coda.h                 |    2 +-
>  drivers/media/platform/coda/trace.h                |    2 +-
>  drivers/media/platform/exynos-gsc/gsc-core.h       |    2 +-
>  drivers/media/platform/exynos4-is/fimc-capture.c   |    2 +-
>  drivers/media/platform/exynos4-is/fimc-core.c      |    2 +-
>  drivers/media/platform/exynos4-is/fimc-core.h      |    2 +-
>  drivers/media/platform/exynos4-is/fimc-is.h        |    2 +-
>  drivers/media/platform/exynos4-is/fimc-isp-video.c |    2 +-
>  drivers/media/platform/exynos4-is/fimc-isp-video.h |    2 +-
>  drivers/media/platform/exynos4-is/fimc-isp.h       |    2 +-
>  drivers/media/platform/exynos4-is/fimc-lite.c      |    2 +-
>  drivers/media/platform/exynos4-is/fimc-lite.h      |    2 +-
>  drivers/media/platform/exynos4-is/fimc-m2m.c       |    2 +-
>  drivers/media/platform/marvell-ccic/mcam-core.h    |    2 +-
>  drivers/media/platform/omap3isp/ispvideo.h         |    2 +-
>  drivers/media/platform/rcar_jpu.c                  |    2 +-
>  drivers/media/platform/s3c-camif/camif-capture.c   |    2 +-
>  drivers/media/platform/s3c-camif/camif-core.c      |    2 +-
>  drivers/media/platform/s3c-camif/camif-core.h      |    2 +-
>  drivers/media/platform/s5p-g2d/g2d.c               |    2 +-
>  drivers/media/platform/s5p-jpeg/jpeg-core.c        |    2 +-
>  drivers/media/platform/s5p-mfc/s5p_mfc.c           |    2 +-
>  drivers/media/platform/s5p-mfc/s5p_mfc_common.h    |    2 +-
>  drivers/media/platform/s5p-mfc/s5p_mfc_dec.c       |    2 +-
>  drivers/media/platform/s5p-mfc/s5p_mfc_enc.c       |    2 +-
>  drivers/media/platform/s5p-tv/mixer.h              |    2 +-
>  drivers/media/platform/soc_camera/mx2_camera.c     |    2 +-
>  drivers/media/platform/soc_camera/soc_camera.c     |    2 +-
>  drivers/media/platform/ti-vpe/vpe.c                |    2 +-
>  drivers/media/platform/vivid/vivid-core.h          |    2 +-
>  drivers/media/platform/vsp1/vsp1_video.c           |    2 +-
>  drivers/media/platform/vsp1/vsp1_video.h           |    2 +-
>  drivers/media/platform/xilinx/xilinx-dma.c         |    2 +-
>  drivers/media/platform/xilinx/xilinx-dma.h         |    2 +-
>  drivers/media/usb/go7007/go7007-priv.h             |    2 +-
>  drivers/media/usb/stk1160/stk1160.h                |    2 +-
>  drivers/media/usb/usbtv/usbtv-video.c              |    2 +-
>  drivers/media/usb/uvc/uvcvideo.h                   |    2 +-
>  drivers/media/v4l2-core/Makefile                   |    2 +-
>  drivers/media/v4l2-core/v4l2-ioctl.c               |    2 +-
>  drivers/media/v4l2-core/v4l2-mem2mem.c             |    2 +-
>  drivers/media/v4l2-core/v4l2-trace.c               |    2 +-
>  drivers/media/v4l2-core/videobuf2-core.c           |   10 +++----
>  drivers/media/v4l2-core/videobuf2-v4l2.c           |   31 ++++++++++++++++++++
>  drivers/usb/gadget/function/uvc_queue.h            |    2 +-
>  include/media/soc_camera.h                         |    2 +-
>  include/media/v4l2-mem2mem.h                       |    2 +-
>  include/media/videobuf2-core.h                     |    3 +-
>  include/media/videobuf2-dvb.h                      |    2 +-
>  include/media/videobuf2-v4l2.h                     |   17 +++++++++++
>  53 files changed, 103 insertions(+), 56 deletions(-)
>  create mode 100644 drivers/media/v4l2-core/videobuf2-v4l2.c
>  create mode 100644 include/media/videobuf2-v4l2.h
> 
> diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
> index 27423d7..5cc9e9d 100644
> --- a/drivers/media/pci/solo6x10/solo6x10.h
> +++ b/drivers/media/pci/solo6x10/solo6x10.h
> @@ -35,7 +35,7 @@
>  #include <media/v4l2-dev.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ctrls.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  #include "solo6x10-regs.h"
>  
> diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
> index fd7819d..cd41d49 100644
> --- a/drivers/media/platform/coda/coda-bit.c
> +++ b/drivers/media/platform/coda/coda-bit.c
> @@ -25,7 +25,7 @@
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-fh.h>
>  #include <media/v4l2-mem2mem.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  #include <media/videobuf2-vmalloc.h>
>  
> diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
> index 04310cd..6e0c9be 100644
> --- a/drivers/media/platform/coda/coda-common.c
> +++ b/drivers/media/platform/coda/coda-common.c
> @@ -36,7 +36,7 @@
>  #include <media/v4l2-event.h>
>  #include <media/v4l2-ioctl.h>
>  #include <media/v4l2-mem2mem.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  #include <media/videobuf2-vmalloc.h>
>  
> diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
> index 59b2af9..feb9671 100644
> --- a/drivers/media/platform/coda/coda.h
> +++ b/drivers/media/platform/coda/coda.h
> @@ -24,7 +24,7 @@
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-fh.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  #include "coda_regs.h"
>  
> diff --git a/drivers/media/platform/coda/trace.h b/drivers/media/platform/coda/trace.h
> index d9099a0..9db6a66 100644
> --- a/drivers/media/platform/coda/trace.h
> +++ b/drivers/media/platform/coda/trace.h
> @@ -5,7 +5,7 @@
>  #define __CODA_TRACE_H__
>  
>  #include <linux/tracepoint.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  #include "coda.h"
>  
> diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
> index fa572aa..769ff50 100644
> --- a/drivers/media/platform/exynos-gsc/gsc-core.h
> +++ b/drivers/media/platform/exynos-gsc/gsc-core.h
> @@ -19,7 +19,7 @@
>  #include <linux/videodev2.h>
>  #include <linux/io.h>
>  #include <linux/pm_runtime.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-mem2mem.h>
> diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
> index cfebf29..d0ceae3 100644
> --- a/drivers/media/platform/exynos4-is/fimc-capture.c
> +++ b/drivers/media/platform/exynos4-is/fimc-capture.c
> @@ -24,7 +24,7 @@
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ioctl.h>
>  #include <media/v4l2-mem2mem.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "common.h"
> diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
> index 1101c41..cef2a7f 100644
> --- a/drivers/media/platform/exynos4-is/fimc-core.c
> +++ b/drivers/media/platform/exynos4-is/fimc-core.c
> @@ -27,7 +27,7 @@
>  #include <linux/slab.h>
>  #include <linux/clk.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "fimc-core.h"
> diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h
> index 7328f08..ccb5d91 100644
> --- a/drivers/media/platform/exynos4-is/fimc-core.h
> +++ b/drivers/media/platform/exynos4-is/fimc-core.h
> @@ -22,7 +22,7 @@
>  #include <linux/sizes.h>
>  
>  #include <media/media-entity.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-mem2mem.h>
> diff --git a/drivers/media/platform/exynos4-is/fimc-is.h b/drivers/media/platform/exynos4-is/fimc-is.h
> index e0be691..386eb49 100644
> --- a/drivers/media/platform/exynos4-is/fimc-is.h
> +++ b/drivers/media/platform/exynos4-is/fimc-is.h
> @@ -22,7 +22,7 @@
>  #include <linux/sizes.h>
>  #include <linux/spinlock.h>
>  #include <linux/types.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/v4l2-ctrls.h>
>  
>  #include "fimc-isp.h"
> diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
> index 76b6b4d..195f9b5 100644
> --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
> +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
> @@ -28,7 +28,7 @@
>  
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  #include <media/exynos-fimc.h>
>  
> diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.h b/drivers/media/platform/exynos4-is/fimc-isp-video.h
> index 98c6626..f79a1b3 100644
> --- a/drivers/media/platform/exynos4-is/fimc-isp-video.h
> +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.h
> @@ -11,7 +11,7 @@
>  #ifndef FIMC_ISP_VIDEO__
>  #define FIMC_ISP_VIDEO__
>  
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include "fimc-isp.h"
>  
>  #ifdef CONFIG_VIDEO_EXYNOS4_ISP_DMA_CAPTURE
> diff --git a/drivers/media/platform/exynos4-is/fimc-isp.h b/drivers/media/platform/exynos4-is/fimc-isp.h
> index b99be09..ad9908b 100644
> --- a/drivers/media/platform/exynos4-is/fimc-isp.h
> +++ b/drivers/media/platform/exynos4-is/fimc-isp.h
> @@ -21,7 +21,7 @@
>  #include <linux/videodev2.h>
>  
>  #include <media/media-entity.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-mediabus.h>
>  #include <media/exynos-fimc.h>
> diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
> index ca6261a..7e37c9a 100644
> --- a/drivers/media/platform/exynos4-is/fimc-lite.c
> +++ b/drivers/media/platform/exynos4-is/fimc-lite.c
> @@ -28,7 +28,7 @@
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ioctl.h>
>  #include <media/v4l2-mem2mem.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  #include <media/exynos-fimc.h>
>  
> diff --git a/drivers/media/platform/exynos4-is/fimc-lite.h b/drivers/media/platform/exynos4-is/fimc-lite.h
> index ea19dc7..7e4c708 100644
> --- a/drivers/media/platform/exynos4-is/fimc-lite.h
> +++ b/drivers/media/platform/exynos4-is/fimc-lite.h
> @@ -19,7 +19,7 @@
>  #include <linux/videodev2.h>
>  
>  #include <media/media-entity.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-mediabus.h>
> diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
> index 0ad1b6f..9c27335 100644
> --- a/drivers/media/platform/exynos4-is/fimc-m2m.c
> +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
> @@ -24,7 +24,7 @@
>  #include <linux/slab.h>
>  #include <linux/clk.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "common.h"
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
> index 97167f6..35cd9e5 100644
> --- a/drivers/media/platform/marvell-ccic/mcam-core.h
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.h
> @@ -10,7 +10,7 @@
>  #include <media/v4l2-common.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-dev.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  /*
>   * Create our own symbols for the supported buffer modes, but, for now,
> diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
> index 4071dd7..31c2445 100644
> --- a/drivers/media/platform/omap3isp/ispvideo.h
> +++ b/drivers/media/platform/omap3isp/ispvideo.h
> @@ -20,7 +20,7 @@
>  #include <media/media-entity.h>
>  #include <media/v4l2-dev.h>
>  #include <media/v4l2-fh.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  #define ISP_VIDEO_DRIVER_NAME		"ispvideo"
>  #define ISP_VIDEO_DRIVER_VERSION	"0.0.2"
> diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c
> index 2973f07..18e62d0 100644
> --- a/drivers/media/platform/rcar_jpu.c
> +++ b/drivers/media/platform/rcar_jpu.c
> @@ -37,7 +37,7 @@
>  #include <media/v4l2-fh.h>
>  #include <media/v4l2-mem2mem.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  
> diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
> index 76e6289..bb01eaa 100644
> --- a/drivers/media/platform/s3c-camif/camif-capture.c
> +++ b/drivers/media/platform/s3c-camif/camif-capture.c
> @@ -34,7 +34,7 @@
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-event.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "camif-core.h"
> diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
> index f47b332..1ba9bb0 100644
> --- a/drivers/media/platform/s3c-camif/camif-core.c
> +++ b/drivers/media/platform/s3c-camif/camif-core.c
> @@ -32,7 +32,7 @@
>  #include <media/media-device.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "camif-core.h"
> diff --git a/drivers/media/platform/s3c-camif/camif-core.h b/drivers/media/platform/s3c-camif/camif-core.h
> index 35d2fcd..8ef6f26 100644
> --- a/drivers/media/platform/s3c-camif/camif-core.h
> +++ b/drivers/media/platform/s3c-camif/camif-core.h
> @@ -25,7 +25,7 @@
>  #include <media/v4l2-dev.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-mediabus.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/s3c_camif.h>
>  
>  #define S3C_CAMIF_DRIVER_NAME	"s3c-camif"
> diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
> index 421a7c3..81483da 100644
> --- a/drivers/media/platform/s5p-g2d/g2d.c
> +++ b/drivers/media/platform/s5p-g2d/g2d.c
> @@ -23,7 +23,7 @@
>  #include <media/v4l2-mem2mem.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "g2d.h"
> diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
> index 9690f9d..5b1861b 100644
> --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
> +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
> @@ -26,7 +26,7 @@
>  #include <linux/string.h>
>  #include <media/v4l2-mem2mem.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "jpeg-core.h"
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
> index 8de61dc..b3758b8 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
> @@ -22,7 +22,7 @@
>  #include <media/v4l2-event.h>
>  #include <linux/workqueue.h>
>  #include <linux/of.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_ctrl.h"
>  #include "s5p_mfc_debug.h"
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> index 24262bb..10884a7 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
> @@ -21,7 +21,7 @@
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include "regs-mfc.h"
>  #include "regs-mfc-v8.h"
>  
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> index aebe4fd..2fd59e7 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> @@ -22,7 +22,7 @@
>  #include <linux/workqueue.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-event.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_ctrl.h"
>  #include "s5p_mfc_debug.h"
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> index 2e57e9f..e42014c 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> @@ -23,7 +23,7 @@
>  #include <media/v4l2-event.h>
>  #include <linux/workqueue.h>
>  #include <media/v4l2-ctrls.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_ctrl.h"
>  #include "s5p_mfc_debug.h"
> diff --git a/drivers/media/platform/s5p-tv/mixer.h b/drivers/media/platform/s5p-tv/mixer.h
> index fb2acc5..855b723 100644
> --- a/drivers/media/platform/s5p-tv/mixer.h
> +++ b/drivers/media/platform/s5p-tv/mixer.h
> @@ -24,7 +24,7 @@
>  #include <linux/spinlock.h>
>  #include <linux/wait.h>
>  #include <media/v4l2-device.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  #include "regs-mixer.h"
>  
> diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
> index ea4c423..6e41335 100644
> --- a/drivers/media/platform/soc_camera/mx2_camera.c
> +++ b/drivers/media/platform/soc_camera/mx2_camera.c
> @@ -32,7 +32,7 @@
>  
>  #include <media/v4l2-common.h>
>  #include <media/v4l2-dev.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  #include <media/soc_camera.h>
>  #include <media/soc_mediabus.h>
> diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
> index 9087fed..3a18df7 100644
> --- a/drivers/media/platform/soc_camera/soc_camera.c
> +++ b/drivers/media/platform/soc_camera/soc_camera.c
> @@ -38,7 +38,7 @@
>  #include <media/v4l2-dev.h>
>  #include <media/v4l2-of.h>
>  #include <media/videobuf-core.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  /* Default to VGA resolution */
>  #define DEFAULT_WIDTH	640
> diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
> index c44760b..d82c2f2 100644
> --- a/drivers/media/platform/ti-vpe/vpe.c
> +++ b/drivers/media/platform/ti-vpe/vpe.c
> @@ -40,7 +40,7 @@
>  #include <media/v4l2-event.h>
>  #include <media/v4l2-ioctl.h>
>  #include <media/v4l2-mem2mem.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "vpdma.h"
> diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
> index c72349c..5f1b1da 100644
> --- a/drivers/media/platform/vivid/vivid-core.h
> +++ b/drivers/media/platform/vivid/vivid-core.h
> @@ -21,7 +21,7 @@
>  #define _VIVID_CORE_H_
>  
>  #include <linux/fb.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-dev.h>
>  #include <media/v4l2-ctrls.h>
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
> index 3c124c1..dfd45c7 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -24,7 +24,7 @@
>  #include <media/v4l2-fh.h>
>  #include <media/v4l2-ioctl.h>
>  #include <media/v4l2-subdev.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "vsp1.h"
> diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
> index 0887a4d..d808301 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.h
> +++ b/drivers/media/platform/vsp1/vsp1_video.h
> @@ -18,7 +18,7 @@
>  #include <linux/wait.h>
>  
>  #include <media/media-entity.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  struct vsp1_video;
>  
> diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
> index e779c93..d9dcd4b 100644
> --- a/drivers/media/platform/xilinx/xilinx-dma.c
> +++ b/drivers/media/platform/xilinx/xilinx-dma.c
> @@ -22,7 +22,7 @@
>  #include <media/v4l2-dev.h>
>  #include <media/v4l2-fh.h>
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/videobuf2-dma-contig.h>
>  
>  #include "xilinx-dma.h"
> diff --git a/drivers/media/platform/xilinx/xilinx-dma.h b/drivers/media/platform/xilinx/xilinx-dma.h
> index a540111..7a1621a 100644
> --- a/drivers/media/platform/xilinx/xilinx-dma.h
> +++ b/drivers/media/platform/xilinx/xilinx-dma.h
> @@ -22,7 +22,7 @@
>  
>  #include <media/media-entity.h>
>  #include <media/v4l2-dev.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  struct dma_chan;
>  struct xvip_composite_device;
> diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h
> index 2251c3f..9e83bbf 100644
> --- a/drivers/media/usb/go7007/go7007-priv.h
> +++ b/drivers/media/usb/go7007/go7007-priv.h
> @@ -20,7 +20,7 @@
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-fh.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  struct go7007;
>  
> diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h
> index 72cc8e8..047131b 100644
> --- a/drivers/media/usb/stk1160/stk1160.h
> +++ b/drivers/media/usb/stk1160/stk1160.h
> @@ -23,7 +23,7 @@
>  #include <linux/i2c.h>
>  #include <sound/core.h>
>  #include <sound/ac97_codec.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ctrls.h>
>  
> diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
> index 08fb0f2..a46766c 100644
> --- a/drivers/media/usb/usbtv/usbtv-video.c
> +++ b/drivers/media/usb/usbtv/usbtv-video.c
> @@ -29,7 +29,7 @@
>   */
>  
>  #include <media/v4l2-ioctl.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  #include "usbtv.h"
>  
> diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
> index 816dd1a..53e6484 100644
> --- a/drivers/media/usb/uvc/uvcvideo.h
> +++ b/drivers/media/usb/uvc/uvcvideo.h
> @@ -15,7 +15,7 @@
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-event.h>
>  #include <media/v4l2-fh.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  /* --------------------------------------------------------------------------
>   * UVC constants
> diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
> index d1dd440..ad07401 100644
> --- a/drivers/media/v4l2-core/Makefile
> +++ b/drivers/media/v4l2-core/Makefile
> @@ -33,7 +33,7 @@ obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
>  obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
>  obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
>  
> -obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o
> +obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o videobuf2-v4l2.o
>  obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
>  obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o
>  obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o
> diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
> index 4a384fc..5dc6908 100644
> --- a/drivers/media/v4l2-core/v4l2-ioctl.c
> +++ b/drivers/media/v4l2-core/v4l2-ioctl.c
> @@ -26,7 +26,7 @@
>  #include <media/v4l2-fh.h>
>  #include <media/v4l2-event.h>
>  #include <media/v4l2-device.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  #include <trace/events/v4l2.h>
>  
> diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
> index ec3ad4e..38703bd 100644
> --- a/drivers/media/v4l2-core/v4l2-mem2mem.c
> +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
> @@ -17,7 +17,7 @@
>  #include <linux/sched.h>
>  #include <linux/slab.h>
>  
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/v4l2-mem2mem.h>
>  #include <media/v4l2-dev.h>
>  #include <media/v4l2-fh.h>
> diff --git a/drivers/media/v4l2-core/v4l2-trace.c b/drivers/media/v4l2-core/v4l2-trace.c
> index ae10b02..4004814 100644
> --- a/drivers/media/v4l2-core/v4l2-trace.c
> +++ b/drivers/media/v4l2-core/v4l2-trace.c
> @@ -1,6 +1,6 @@
>  #include <media/v4l2-common.h>
>  #include <media/v4l2-fh.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  #define CREATE_TRACE_POINTS
>  #include <trace/events/v4l2.h>
> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> index b866a6b..ab00ea0 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> @@ -1,5 +1,5 @@
>  /*
> - * videobuf2-core.c - V4L2 driver helper framework
> + * videobuf2-core.c - video buffer 2 core framework
>   *
>   * Copyright (C) 2010 Samsung Electronics
>   *
> @@ -28,7 +28,7 @@
>  #include <media/v4l2-fh.h>
>  #include <media/v4l2-event.h>
>  #include <media/v4l2-common.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  #include <trace/events/v4l2.h>
>  
> @@ -1810,7 +1810,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
>  	/*
>  	 * If you see this warning, then the driver isn't cleaning up properly
>  	 * after a failed start_streaming(). See the start_streaming()
> -	 * documentation in videobuf2-core.h for more information how buffers
> +	 * documentation in videobuf2-v4l2.h for more information how buffers
>  	 * should be returned to vb2 in start_streaming().
>  	 */
>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
> @@ -2197,7 +2197,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	/*
>  	 * If you see this warning, then the driver isn't cleaning up properly
>  	 * in stop_streaming(). See the stop_streaming() documentation in
> -	 * videobuf2-core.h for more information how buffers should be returned
> +	 * videobuf2-v4l2.h for more information how buffers should be returned
>  	 * to vb2 in stop_streaming().
>  	 */
>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
> @@ -2731,7 +2731,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
>   * responsible of clearing it's content and setting initial values for some
>   * required entries before calling this function.
>   * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
> - * to the struct vb2_queue description in include/media/videobuf2-core.h
> + * to the struct vb2_queue description in include/media/videobuf2-v4l2.h
>   * for more information.
>   */
>  int vb2_queue_init(struct vb2_queue *q)
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> new file mode 100644
> index 0000000..2f2b738
> --- /dev/null
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -0,0 +1,31 @@
> +/*
> + * videobuf2-v4l2.c - V4L2 driver helper framework
> + *
> + * Copyright (C) 2010 Samsung Electronics
> + *
> + * Author: Pawel Osciak <pawel@osciak.com>
> + *	   Marek Szyprowski <m.szyprowski@samsung.com>
> + *
> + * The vb2_thread implementation was based on code from videobuf-dvb.c:
> + *	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mm.h>
> +#include <linux/poll.h>
> +#include <linux/slab.h>
> +#include <linux/sched.h>
> +#include <linux/freezer.h>
> +#include <linux/kthread.h>
> +
> +#include <media/videobuf2-v4l2.h>
> +
> +MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
> +MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h
> index 01ca9ea..0ffe498 100644
> --- a/drivers/usb/gadget/function/uvc_queue.h
> +++ b/drivers/usb/gadget/function/uvc_queue.h
> @@ -6,7 +6,7 @@
>  #include <linux/kernel.h>
>  #include <linux/poll.h>
>  #include <linux/videodev2.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  /* Maximum frame size in bytes, for sanity checking. */
>  #define UVC_MAX_FRAME_SIZE	(16*1024*1024)
> diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
> index 2f6261f..97aa133 100644
> --- a/include/media/soc_camera.h
> +++ b/include/media/soc_camera.h
> @@ -18,7 +18,7 @@
>  #include <linux/pm.h>
>  #include <linux/videodev2.h>
>  #include <media/videobuf-core.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  #include <media/v4l2-async.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/v4l2-device.h>
> diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
> index 8849aab..5c60da9 100644
> --- a/include/media/v4l2-mem2mem.h
> +++ b/include/media/v4l2-mem2mem.h
> @@ -17,7 +17,7 @@
>  #ifndef _MEDIA_V4L2_MEM2MEM_H
>  #define _MEDIA_V4L2_MEM2MEM_H
>  
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  /**
>   * struct v4l2_m2m_ops - mem-to-mem device driver callbacks
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index 4f7f7ae..155991e 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -1,5 +1,5 @@
>  /*
> - * videobuf2-core.h - V4L2 driver helper framework
> + * videobuf2-core.h - Video Buffer 2 Core Framework
>   *
>   * Copyright (C) 2010 Samsung Electronics
>   *
> @@ -661,5 +661,4 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>  
>  void vb2_ops_wait_prepare(struct vb2_queue *vq);
>  void vb2_ops_wait_finish(struct vb2_queue *vq);
> -
>  #endif /* _MEDIA_VIDEOBUF2_CORE_H */
> diff --git a/include/media/videobuf2-dvb.h b/include/media/videobuf2-dvb.h
> index 8f61456..bef9127 100644
> --- a/include/media/videobuf2-dvb.h
> +++ b/include/media/videobuf2-dvb.h
> @@ -6,7 +6,7 @@
>  #include <dvb_demux.h>
>  #include <dvb_net.h>
>  #include <dvb_frontend.h>
> -#include <media/videobuf2-core.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  struct vb2_dvb {
>  	/* filling that the job of the driver */
> diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
> new file mode 100644
> index 0000000..d4a4d9a
> --- /dev/null
> +++ b/include/media/videobuf2-v4l2.h
> @@ -0,0 +1,17 @@
> +/*
> + * videobuf2-v4l2.h - V4L2 driver helper framework
> + *
> + * Copyright (C) 2010 Samsung Electronics
> + *
> + * Author: Pawel Osciak <pawel@osciak.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation.
> + */
> +#ifndef _MEDIA_VIDEOBUF2_V4L2_H
> +#define _MEDIA_VIDEOBUF2_V4L2_H
> +
> +#include <media/videobuf2-core.h>
> +
> +#endif /* _MEDIA_VIDEOBUF2_V4L2_H */

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer
  2015-08-26 11:59 ` [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer Junghak Sung
@ 2015-08-27 10:28   ` Mauro Carvalho Chehab
  2015-08-28  1:26     ` Junghak Sung
  2015-08-28 13:31   ` Hans Verkuil
  1 sibling, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2015-08-27 10:28 UTC (permalink / raw)
  To: Junghak Sung
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Em Wed, 26 Aug 2015 20:59:29 +0900
Junghak Sung <jh1009.sung@samsung.com> escreveu:

> Remove v4l2-specific stuff from struct vb2_buffer and add member variables
> related with buffer management.
> 
> struct vb2_plane {
>         <snip>
>         /* plane information */
>         unsigned int            bytesused;
>         unsigned int            length;
>         union {
>                 unsigned int    offset;
>                 unsigned long   userptr;
>                 int             fd;
>         } m;
>         unsigned int            data_offset;
> }
> 
> struct vb2_buffer {
>         <snip>
>         /* buffer information */
>         unsigned int            num_planes;
>         unsigned int            index;
>         unsigned int            type;
>         unsigned int            memory;
> 
>         struct vb2_plane        planes[VIDEO_MAX_PLANES];
>         <snip>
> };
> 
> And create struct vb2_v4l2_buffer as container buffer for v4l2 use.
> 
> struct vb2_v4l2_buffer {
>         struct vb2_buffer       vb2_buf;
> 
>         __u32                   flags;
>         __u32                   field;
>         struct timeval          timestamp;
>         struct v4l2_timecode    timecode;
>         __u32                   sequence;
> };

The comments seemed a little hard for me to read, but the changes
look ok.

I made some comments mostly regarding to documentation. See below.

> This patch includes only changes inside of videobuf2. So, it is required to
> modify all device drivers which use videobuf2.

So, in practice, we need to fold both patches 2 and 3 when merging upstream,
to avoid breaking git bisectability.

> 
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
> ---
>  drivers/media/v4l2-core/videobuf2-core.c |  324 +++++++++++++++++-------------
>  include/media/videobuf2-core.h           |   50 ++---
>  include/media/videobuf2-v4l2.h           |   26 +++
>  3 files changed, 236 insertions(+), 164 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> index ab00ea0..9266d50 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> @@ -35,10 +35,10 @@
>  static int debug;
>  module_param(debug, int, 0644);
>  
> -#define dprintk(level, fmt, arg...)					      \
> -	do {								      \
> -		if (debug >= level)					      \
> -			pr_info("vb2: %s: " fmt, __func__, ## arg); \
> +#define dprintk(level, fmt, arg...)					\
> +	do {								\
> +		if (debug >= level)					\
> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
>  	} while (0)
>  
>  #ifdef CONFIG_VIDEO_ADV_DEBUG
> @@ -53,7 +53,7 @@ module_param(debug, int, 0644);
>  
>  #define log_memop(vb, op)						\
>  	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
> -		(vb)->vb2_queue, (vb)->v4l2_buf.index, #op,		\
> +		(vb)->vb2_queue, (vb)->index, #op,			\
>  		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
>  
>  #define call_memop(vb, op, args...)					\
> @@ -115,7 +115,7 @@ module_param(debug, int, 0644);
>  
>  #define log_vb_qop(vb, op, args...)					\
>  	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
> -		(vb)->vb2_queue, (vb)->v4l2_buf.index, #op,		\
> +		(vb)->vb2_queue, (vb)->index, #op,			\
>  		(vb)->vb2_queue->ops->op ? "" : " (nop)")
>  
>  #define call_vb_qop(vb, op, args...)					\
> @@ -205,13 +205,13 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
>  		unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]);
>  
>  		mem_priv = call_ptr_memop(vb, alloc, q->alloc_ctx[plane],
> -				      size, dma_dir, q->gfp_flags);
> +					size, dma_dir, q->gfp_flags);
>  		if (IS_ERR_OR_NULL(mem_priv))
>  			goto free;
>  
>  		/* Associate allocator private data with this plane */
>  		vb->planes[plane].mem_priv = mem_priv;
> -		vb->v4l2_planes[plane].length = q->plane_sizes[plane];
> +		vb->planes[plane].length = q->plane_sizes[plane];
>  	}
>  
>  	return 0;
> @@ -235,8 +235,7 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb)
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		call_void_memop(vb, put, vb->planes[plane].mem_priv);
>  		vb->planes[plane].mem_priv = NULL;
> -		dprintk(3, "freed plane %d of buffer %d\n", plane,
> -			vb->v4l2_buf.index);
> +		dprintk(3, "freed plane %d of buffer %d\n", plane, vb->index);
>  	}
>  }
>  
> @@ -269,7 +268,9 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p)
>  
>  	call_void_memop(vb, detach_dmabuf, p->mem_priv);
>  	dma_buf_put(p->dbuf);
> -	memset(p, 0, sizeof(*p));
> +	p->mem_priv = NULL;
> +	p->dbuf = NULL;
> +	p->dbuf_mapped = 0;
>  }
>  
>  /**
> @@ -299,7 +300,7 @@ static void __setup_lengths(struct vb2_queue *q, unsigned int n)
>  			continue;
>  
>  		for (plane = 0; plane < vb->num_planes; ++plane)
> -			vb->v4l2_planes[plane].length = q->plane_sizes[plane];
> +			vb->planes[plane].length = q->plane_sizes[plane];
>  	}
>  }
>  
> @@ -314,10 +315,10 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>  	unsigned long off;
>  
>  	if (q->num_buffers) {
> -		struct v4l2_plane *p;
> +		struct vb2_plane *p;
>  		vb = q->bufs[q->num_buffers - 1];
> -		p = &vb->v4l2_planes[vb->num_planes - 1];
> -		off = PAGE_ALIGN(p->m.mem_offset + p->length);
> +		p = &vb->planes[vb->num_planes - 1];
> +		off = PAGE_ALIGN(p->m.offset + p->length);
>  	} else {
>  		off = 0;
>  	}
> @@ -328,12 +329,12 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>  			continue;
>  
>  		for (plane = 0; plane < vb->num_planes; ++plane) {
> -			vb->v4l2_planes[plane].m.mem_offset = off;
> +			vb->planes[plane].m.offset = off;
>  
>  			dprintk(3, "buffer %d, plane %d offset 0x%08lx\n",
>  					buffer, plane, off);
>  
> -			off += vb->v4l2_planes[plane].length;
> +			off += vb->planes[plane].length;
>  			off = PAGE_ALIGN(off);
>  		}
>  	}
> @@ -347,7 +348,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>   * Returns the number of buffers successfully allocated.
>   */
>  static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
> -			     unsigned int num_buffers, unsigned int num_planes)
> +			unsigned int num_buffers, unsigned int num_planes)
>  {
>  	unsigned int buffer;
>  	struct vb2_buffer *vb;
> @@ -361,16 +362,12 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>  			break;
>  		}
>  
> -		/* Length stores number of planes for multiplanar buffers */
> -		if (V4L2_TYPE_IS_MULTIPLANAR(q->type))
> -			vb->v4l2_buf.length = num_planes;
> -
>  		vb->state = VB2_BUF_STATE_DEQUEUED;
>  		vb->vb2_queue = q;
>  		vb->num_planes = num_planes;
> -		vb->v4l2_buf.index = q->num_buffers + buffer;
> -		vb->v4l2_buf.type = q->type;
> -		vb->v4l2_buf.memory = memory;
> +		vb->index = q->num_buffers + buffer;
> +		vb->type = q->type;
> +		vb->memory = memory;
>  
>  		/* Allocate video buffer memory for the MMAP type */
>  		if (memory == V4L2_MEMORY_MMAP) {
> @@ -418,7 +415,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>  	struct vb2_buffer *vb;
>  
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
> -	     ++buffer) {
> +			++buffer) {
>  		vb = q->bufs[buffer];
>  		if (!vb)
>  			continue;
> @@ -451,7 +448,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  	 * just return -EAGAIN.
>  	 */
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
> -	     ++buffer) {
> +			++buffer) {
>  		if (q->bufs[buffer] == NULL)
>  			continue;
>  		if (q->bufs[buffer]->state == VB2_BUF_STATE_PREPARING) {
> @@ -462,7 +459,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  
>  	/* Call driver-provided cleanup function for each buffer, if provided */
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
> -	     ++buffer) {
> +			++buffer) {
>  		struct vb2_buffer *vb = q->bufs[buffer];
>  
>  		if (vb && vb->planes[0].mem_priv)
> @@ -536,7 +533,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  
>  	/* Free videobuf buffers */
>  	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
> -	     ++buffer) {
> +			++buffer) {
>  		kfree(q->bufs[buffer]);
>  		q->bufs[buffer] = NULL;
>  	}
> @@ -590,23 +587,22 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>  		for (plane = 0; plane < vb->num_planes; ++plane) {
>  			length = (b->memory == V4L2_MEMORY_USERPTR ||
> -				  b->memory == V4L2_MEMORY_DMABUF)
> -			       ? b->m.planes[plane].length
> -			       : vb->v4l2_planes[plane].length;
> +				b->memory == V4L2_MEMORY_DMABUF)
> +				? b->m.planes[plane].length
> +				: vb->planes[plane].length;
>  			bytesused = b->m.planes[plane].bytesused
> -				  ? b->m.planes[plane].bytesused : length;
> +				? b->m.planes[plane].bytesused : length;
>  
>  			if (b->m.planes[plane].bytesused > length)
>  				return -EINVAL;
>  
>  			if (b->m.planes[plane].data_offset > 0 &&
> -			    b->m.planes[plane].data_offset >= bytesused)
> +				b->m.planes[plane].data_offset >= bytesused)
>  				return -EINVAL;
>  		}
>  	} else {
>  		length = (b->memory == V4L2_MEMORY_USERPTR)
> -		       ? b->length : vb->v4l2_planes[0].length;
> -		bytesused = b->bytesused ? b->bytesused : length;
> +			? b->length : vb->planes[0].length;
>  
>  		if (b->bytesused > length)
>  			return -EINVAL;
> @@ -656,12 +652,21 @@ static bool __buffers_in_use(struct vb2_queue *q)
>   */
>  static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>  {
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>  	struct vb2_queue *q = vb->vb2_queue;
> +	unsigned int plane;
>  
>  	/* Copy back data such as timestamp, flags, etc. */
> -	memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
> -	b->reserved2 = vb->v4l2_buf.reserved2;
> -	b->reserved = vb->v4l2_buf.reserved;
> +	b->index = vb->index;
> +	b->type = vb->type;
> +	b->memory = vb->memory;
> +	b->bytesused = 0;
> +
> +	b->flags = vbuf->flags;
> +	b->field = vbuf->field;
> +	b->timestamp = vbuf->timestamp;
> +	b->timecode = vbuf->timecode;
> +	b->sequence = vbuf->sequence;
>  
>  	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>  		/*
> @@ -669,21 +674,33 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>  		 * for it. The caller has already verified memory and size.
>  		 */
>  		b->length = vb->num_planes;
> -		memcpy(b->m.planes, vb->v4l2_planes,
> -			b->length * sizeof(struct v4l2_plane));
> +		for (plane = 0; plane < vb->num_planes; ++plane) {
> +			struct v4l2_plane *pdst = &b->m.planes[plane];
> +			struct vb2_plane *psrc = &vb->planes[plane];
> +
> +			pdst->bytesused = psrc->bytesused;
> +			pdst->length = psrc->length;
> +			if (q->memory == V4L2_MEMORY_MMAP)
> +				pdst->m.mem_offset = psrc->m.offset;
> +			else if (q->memory == V4L2_MEMORY_USERPTR)
> +				pdst->m.userptr = psrc->m.userptr;
> +			else if (q->memory == V4L2_MEMORY_DMABUF)
> +				pdst->m.fd = psrc->m.fd;
> +			pdst->data_offset = psrc->data_offset;
> +		}
>  	} else {
>  		/*
>  		 * We use length and offset in v4l2_planes array even for
>  		 * single-planar buffers, but userspace does not.
>  		 */
> -		b->length = vb->v4l2_planes[0].length;
> -		b->bytesused = vb->v4l2_planes[0].bytesused;
> +		b->length = vb->planes[0].length;
> +		b->bytesused = vb->planes[0].bytesused;
>  		if (q->memory == V4L2_MEMORY_MMAP)
> -			b->m.offset = vb->v4l2_planes[0].m.mem_offset;
> +			b->m.offset = vb->planes[0].m.offset;
>  		else if (q->memory == V4L2_MEMORY_USERPTR)
> -			b->m.userptr = vb->v4l2_planes[0].m.userptr;
> +			b->m.userptr = vb->planes[0].m.userptr;
>  		else if (q->memory == V4L2_MEMORY_DMABUF)
> -			b->m.fd = vb->v4l2_planes[0].m.fd;
> +			b->m.fd = vb->planes[0].m.fd;
>  	}
>  
>  	/*
> @@ -692,7 +709,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>  	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>  	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>  	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> -	    V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>  		/*
>  		 * For non-COPY timestamps, drop timestamp source bits
>  		 * and obtain the timestamp source from the queue.
> @@ -767,7 +784,7 @@ EXPORT_SYMBOL(vb2_querybuf);
>  static int __verify_userptr_ops(struct vb2_queue *q)
>  {
>  	if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
> -	    !q->mem_ops->put_userptr)
> +			!q->mem_ops->put_userptr)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -780,7 +797,7 @@ static int __verify_userptr_ops(struct vb2_queue *q)
>  static int __verify_mmap_ops(struct vb2_queue *q)
>  {
>  	if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
> -	    !q->mem_ops->put || !q->mem_ops->mmap)
> +			!q->mem_ops->put || !q->mem_ops->mmap)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -793,8 +810,8 @@ static int __verify_mmap_ops(struct vb2_queue *q)
>  static int __verify_dmabuf_ops(struct vb2_queue *q)
>  {
>  	if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
> -	    !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
> -	    !q->mem_ops->unmap_dmabuf)
> +		!q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
> +		!q->mem_ops->unmap_dmabuf)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -808,7 +825,7 @@ static int __verify_memory_type(struct vb2_queue *q,
>  		enum v4l2_memory memory, enum v4l2_buf_type type)
>  {
>  	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
> -	    memory != V4L2_MEMORY_DMABUF) {
> +			memory != V4L2_MEMORY_DMABUF) {
>  		dprintk(1, "unsupported memory type\n");
>  		return -EINVAL;
>  	}
> @@ -927,7 +944,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  	 * Driver also sets the size and allocator context for each plane.
>  	 */
>  	ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
> -		       q->plane_sizes, q->alloc_ctx);
> +			q->plane_sizes, q->alloc_ctx);
>  	if (ret)
>  		return ret;
>  
> @@ -952,7 +969,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  		num_buffers = allocated_buffers;
>  
>  		ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
> +				&num_planes, q->plane_sizes, q->alloc_ctx);
>  
>  		if (!ret && allocated_buffers < num_buffers)
>  			ret = -ENOMEM;
> @@ -1040,7 +1057,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  	 * buffer and their sizes are acceptable
>  	 */
>  	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> -		       &num_planes, q->plane_sizes, q->alloc_ctx);
> +			&num_planes, q->plane_sizes, q->alloc_ctx);
>  	if (ret)
>  		return ret;
>  
> @@ -1063,7 +1080,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  		 * queue driver has set up
>  		 */
>  		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
> +				&num_planes, q->plane_sizes, q->alloc_ctx);
>  
>  		if (!ret && allocated_buffers < num_buffers)
>  			ret = -ENOMEM;
> @@ -1183,8 +1200,8 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
>  		return;
>  
>  	if (WARN_ON(state != VB2_BUF_STATE_DONE &&
> -		    state != VB2_BUF_STATE_ERROR &&
> -		    state != VB2_BUF_STATE_QUEUED))
> +		state != VB2_BUF_STATE_ERROR &&
> +		state != VB2_BUF_STATE_QUEUED))
>  		state = VB2_BUF_STATE_ERROR;
>  
>  #ifdef CONFIG_VIDEO_ADV_DEBUG
> @@ -1195,7 +1212,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
>  	vb->cnt_buf_done++;
>  #endif
>  	dprintk(4, "done processing on buffer %d, state: %d\n",
> -			vb->v4l2_buf.index, state);
> +			vb->index, state);
>  
>  	/* sync buffers */
>  	for (plane = 0; plane < vb->num_planes; ++plane)
> @@ -1268,25 +1285,26 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>   * v4l2_buffer by the userspace. The caller has already verified that struct
>   * v4l2_buffer has a valid number of planes.
>   */
> -static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
> -				struct v4l2_plane *v4l2_planes)
> +static void __fill_vb2_buffer(struct vb2_buffer *vb,
> +		const struct v4l2_buffer *b, struct vb2_plane *planes)
>  {
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>  	unsigned int plane;
>  
>  	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>  		if (b->memory == V4L2_MEMORY_USERPTR) {
>  			for (plane = 0; plane < vb->num_planes; ++plane) {
> -				v4l2_planes[plane].m.userptr =
> +				planes[plane].m.userptr =
>  					b->m.planes[plane].m.userptr;
> -				v4l2_planes[plane].length =
> +				planes[plane].length =
>  					b->m.planes[plane].length;
>  			}
>  		}
>  		if (b->memory == V4L2_MEMORY_DMABUF) {
>  			for (plane = 0; plane < vb->num_planes; ++plane) {
> -				v4l2_planes[plane].m.fd =
> +				planes[plane].m.fd =
>  					b->m.planes[plane].m.fd;
> -				v4l2_planes[plane].length =
> +				planes[plane].length =
>  					b->m.planes[plane].length;
>  			}
>  		}
> @@ -1310,7 +1328,7 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>  			 * applications working.
>  			 */
>  			for (plane = 0; plane < vb->num_planes; ++plane) {
> -				struct v4l2_plane *pdst = &v4l2_planes[plane];
> +				struct vb2_plane *pdst = &planes[plane];
>  				struct v4l2_plane *psrc = &b->m.planes[plane];
>  
>  				if (psrc->bytesused == 0)
> @@ -1340,13 +1358,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>  		 * old userspace applications working.
>  		 */
>  		if (b->memory == V4L2_MEMORY_USERPTR) {
> -			v4l2_planes[0].m.userptr = b->m.userptr;
> -			v4l2_planes[0].length = b->length;
> +			planes[0].m.userptr = b->m.userptr;
> +			planes[0].length = b->length;
>  		}
>  
>  		if (b->memory == V4L2_MEMORY_DMABUF) {
> -			v4l2_planes[0].m.fd = b->m.fd;
> -			v4l2_planes[0].length = b->length;
> +			planes[0].m.fd = b->m.fd;
> +			planes[0].length = b->length;
>  		}
>  
>  		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> @@ -1354,25 +1372,26 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>  				vb2_warn_zero_bytesused(vb);
>  
>  			if (vb->vb2_queue->allow_zero_bytesused)
> -				v4l2_planes[0].bytesused = b->bytesused;
> +				planes[0].bytesused = b->bytesused;
>  			else
> -				v4l2_planes[0].bytesused = b->bytesused ?
> -					b->bytesused : v4l2_planes[0].length;
> +				planes[0].bytesused = b->bytesused ?
> +					b->bytesused : planes[0].length;
>  		} else
> -			v4l2_planes[0].bytesused = 0;
> +			planes[0].bytesused = 0;
>  
>  	}
>  
>  	/* Zero flags that the vb2 core handles */
> -	vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> +	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
>  	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> -	    V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
> +			!V4L2_TYPE_IS_OUTPUT(b->type)) {
>  		/*
>  		 * Non-COPY timestamps and non-OUTPUT queues will get
>  		 * their timestamp and timestamp source flags from the
>  		 * queue.
>  		 */
> -		vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> +		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>  	}
>  
>  	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> @@ -1382,11 +1401,11 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>  		 * The 'field' is valid metadata for this output buffer
>  		 * and so that needs to be copied here.
>  		 */
> -		vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TIMECODE;
> -		vb->v4l2_buf.field = b->field;
> +		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
> +		vbuf->field = b->field;
>  	} else {
>  		/* Zero any output buffer flags as this is a capture buffer */
> -		vb->v4l2_buf.flags &= ~V4L2_BUFFER_OUT_FLAGS;
> +		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
>  	}
>  }
>  
> @@ -1395,7 +1414,7 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>   */
>  static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  {
> -	__fill_vb2_buffer(vb, b, vb->v4l2_planes);
> +	__fill_vb2_buffer(vb, b, vb->planes);
>  	return call_vb_qop(vb, buf_prepare, vb);
>  }
>  
> @@ -1404,7 +1423,7 @@ static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>   */
>  static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  {
> -	struct v4l2_plane planes[VIDEO_MAX_PLANES];
> +	struct vb2_plane planes[VIDEO_MAX_PLANES];
>  	struct vb2_queue *q = vb->vb2_queue;
>  	void *mem_priv;
>  	unsigned int plane;
> @@ -1419,9 +1438,9 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		/* Skip the plane if already verified */
> -		if (vb->v4l2_planes[plane].m.userptr &&
> -		    vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
> -		    && vb->v4l2_planes[plane].length == planes[plane].length)
> +		if (vb->planes[plane].m.userptr &&
> +			vb->planes[plane].m.userptr == planes[plane].m.userptr
> +			&& vb->planes[plane].length == planes[plane].length)
>  			continue;
>  
>  		dprintk(3, "userspace address for plane %d changed, "
> @@ -1447,12 +1466,15 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  		}
>  
>  		vb->planes[plane].mem_priv = NULL;
> -		memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
> +		vb->planes[plane].bytesused = 0;
> +		vb->planes[plane].length = 0;
> +		vb->planes[plane].m.userptr = 0;
> +		vb->planes[plane].data_offset = 0;
>  
>  		/* Acquire each plane's memory */
>  		mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane],
> -				      planes[plane].m.userptr,
> -				      planes[plane].length, dma_dir);
> +					planes[plane].m.userptr,
> +					planes[plane].length, dma_dir);
>  		if (IS_ERR_OR_NULL(mem_priv)) {
>  			dprintk(1, "failed acquiring userspace "
>  						"memory for plane %d\n", plane);
> @@ -1466,8 +1488,12 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  	 * Now that everything is in order, copy relevant information
>  	 * provided by userspace.
>  	 */
> -	for (plane = 0; plane < vb->num_planes; ++plane)
> -		vb->v4l2_planes[plane] = planes[plane];
> +	for (plane = 0; plane < vb->num_planes; ++plane) {
> +		vb->planes[plane].bytesused = planes[plane].bytesused;
> +		vb->planes[plane].length = planes[plane].length;
> +		vb->planes[plane].m.userptr = planes[plane].m.userptr;
> +		vb->planes[plane].data_offset = planes[plane].data_offset;
> +	}
>  
>  	if (reacquired) {
>  		/*
> @@ -1494,10 +1520,11 @@ err:
>  	/* In case of errors, release planes that were already acquired */
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		if (vb->planes[plane].mem_priv)
> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
> +			call_void_memop(vb, put_userptr,
> +				vb->planes[plane].mem_priv);
>  		vb->planes[plane].mem_priv = NULL;
> -		vb->v4l2_planes[plane].m.userptr = 0;
> -		vb->v4l2_planes[plane].length = 0;
> +		vb->planes[plane].m.userptr = 0;
> +		vb->planes[plane].length = 0;
>  	}
>  
>  	return ret;
> @@ -1508,7 +1535,7 @@ err:
>   */
>  static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  {
> -	struct v4l2_plane planes[VIDEO_MAX_PLANES];
> +	struct vb2_plane planes[VIDEO_MAX_PLANES];
>  	struct vb2_queue *q = vb->vb2_queue;
>  	void *mem_priv;
>  	unsigned int plane;
> @@ -1544,7 +1571,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  
>  		/* Skip the plane if already verified */
>  		if (dbuf == vb->planes[plane].dbuf &&
> -		    vb->v4l2_planes[plane].length == planes[plane].length) {
> +			vb->planes[plane].length == planes[plane].length) {
>  			dma_buf_put(dbuf);
>  			continue;
>  		}
> @@ -1558,11 +1585,15 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  
>  		/* Release previously acquired memory if present */
>  		__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
> -		memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
> +		vb->planes[plane].bytesused = 0;
> +		vb->planes[plane].length = 0;
> +		vb->planes[plane].m.fd = 0;
> +		vb->planes[plane].data_offset = 0;
>  
>  		/* Acquire each plane's memory */
> -		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
> -			dbuf, planes[plane].length, dma_dir);
> +		mem_priv = call_ptr_memop(vb, attach_dmabuf,
> +			q->alloc_ctx[plane], dbuf, planes[plane].length,
> +			dma_dir);
>  		if (IS_ERR(mem_priv)) {
>  			dprintk(1, "failed to attach dmabuf\n");
>  			ret = PTR_ERR(mem_priv);
> @@ -1592,8 +1623,12 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  	 * Now that everything is in order, copy relevant information
>  	 * provided by userspace.
>  	 */
> -	for (plane = 0; plane < vb->num_planes; ++plane)
> -		vb->v4l2_planes[plane] = planes[plane];
> +	for (plane = 0; plane < vb->num_planes; ++plane) {
> +		vb->planes[plane].bytesused = planes[plane].bytesused;
> +		vb->planes[plane].length = planes[plane].length;
> +		vb->planes[plane].m.fd = planes[plane].m.userptr;
> +		vb->planes[plane].data_offset = planes[plane].data_offset;
> +	}
>  
>  	if (reacquired) {
>  		/*
> @@ -1644,6 +1679,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
>  
>  static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  {
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>  	struct vb2_queue *q = vb->vb2_queue;
>  	int ret;
>  
> @@ -1672,9 +1708,9 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  	}
>  
>  	vb->state = VB2_BUF_STATE_PREPARING;
> -	vb->v4l2_buf.timestamp.tv_sec = 0;
> -	vb->v4l2_buf.timestamp.tv_usec = 0;
> -	vb->v4l2_buf.sequence = 0;
> +	vbuf->timestamp.tv_sec = 0;
> +	vbuf->timestamp.tv_usec = 0;
> +	vbuf->sequence = 0;
>  
>  	switch (q->memory) {
>  	case V4L2_MEMORY_MMAP:
> @@ -1701,7 +1737,7 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  }
>  
>  static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
> -				    const char *opname)
> +					const char *opname)
>  {
>  	if (b->type != q->type) {
>  		dprintk(1, "%s: invalid buffer type\n", opname);
> @@ -1768,7 +1804,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
>  		/* Fill buffer information for the userspace */
>  		__fill_v4l2_buffer(vb, b);
>  
> -		dprintk(1, "prepare of buffer %d succeeded\n", vb->v4l2_buf.index);
> +		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
>  	}
>  	return ret;
>  }
> @@ -1800,7 +1836,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
>  	/* Tell the driver to start streaming */
>  	q->start_streaming_called = 1;
>  	ret = call_qop(q, start_streaming, q,
> -		       atomic_read(&q->owned_by_drv_count));
> +			atomic_read(&q->owned_by_drv_count));
>  	if (!ret)
>  		return 0;
>  
> @@ -1810,7 +1846,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
>  	/*
>  	 * If you see this warning, then the driver isn't cleaning up properly
>  	 * after a failed start_streaming(). See the start_streaming()
> -	 * documentation in videobuf2-v4l2.h for more information how buffers
> +	 * documentation in videobuf2-core.h for more information how buffers
>  	 * should be returned to vb2 in start_streaming().
>  	 */
>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
> @@ -1841,11 +1877,13 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  {
>  	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
>  	struct vb2_buffer *vb;
> +	struct vb2_v4l2_buffer *vbuf;
>  
>  	if (ret)
>  		return ret;
>  
>  	vb = q->bufs[b->index];
> +	vbuf = to_vb2_v4l2_buffer(vb);
>  
>  	switch (vb->state) {
>  	case VB2_BUF_STATE_DEQUEUED:
> @@ -1877,11 +1915,11 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  		 * and the timecode field and flag if needed.
>  		 */
>  		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> -		    V4L2_BUF_FLAG_TIMESTAMP_COPY)
> -			vb->v4l2_buf.timestamp = b->timestamp;
> -		vb->v4l2_buf.flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> +				V4L2_BUF_FLAG_TIMESTAMP_COPY)
> +			vbuf->timestamp = b->timestamp;
> +		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
>  		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> -			vb->v4l2_buf.timecode = b->timecode;
> +			vbuf->timecode = b->timecode;
>  	}
>  
>  	trace_vb2_qbuf(q, vb);
> @@ -1903,13 +1941,13 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  	 * then we can finally call start_streaming().
>  	 */
>  	if (q->streaming && !q->start_streaming_called &&
> -	    q->queued_count >= q->min_buffers_needed) {
> +			q->queued_count >= q->min_buffers_needed) {
>  		ret = vb2_start_streaming(q);
>  		if (ret)
>  			return ret;
>  	}
>  
> -	dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
> +	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
>  	return 0;
>  }
>  
> @@ -2099,9 +2137,11 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
>  		}
>  }
>  
> -static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
> +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> +		bool nonblocking)
>  {
>  	struct vb2_buffer *vb = NULL;
> +	struct vb2_v4l2_buffer *vbuf = NULL;
>  	int ret;
>  
>  	if (b->type != q->type) {
> @@ -2134,14 +2174,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool n
>  
>  	trace_vb2_dqbuf(q, vb);
>  
> +	vbuf = to_vb2_v4l2_buffer(vb);
>  	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
> -	    vb->v4l2_buf.flags & V4L2_BUF_FLAG_LAST)
> +			vbuf->flags & V4L2_BUF_FLAG_LAST)
>  		q->last_buffer_dequeued = true;
>  	/* go back to dequeued state */
>  	__vb2_dqbuf(vb);
>  
>  	dprintk(1, "dqbuf of buffer %d, with state %d\n",
> -			vb->v4l2_buf.index, vb->state);
> +			vb->index, vb->state);
>  
>  	return 0;
>  }
> @@ -2197,7 +2238,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	/*
>  	 * If you see this warning, then the driver isn't cleaning up properly
>  	 * in stop_streaming(). See the stop_streaming() documentation in
> -	 * videobuf2-v4l2.h for more information how buffers should be returned
> +	 * videobuf2-core.h for more information how buffers should be returned
>  	 * to vb2 in stop_streaming().
>  	 */
>  	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
> @@ -2399,7 +2440,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>  		vb = q->bufs[buffer];
>  
>  		for (plane = 0; plane < vb->num_planes; ++plane) {
> -			if (vb->v4l2_planes[plane].m.mem_offset == off) {
> +			if (vb->planes[plane].m.offset == off) {
>  				*_buffer = buffer;
>  				*_plane = plane;
>  				return 0;
> @@ -2557,7 +2598,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  	 * The buffer length was page_aligned at __vb2_buf_mem_alloc(),
>  	 * so, we need to do the same here.
>  	 */
> -	length = PAGE_ALIGN(vb->v4l2_planes[plane].length);
> +	length = PAGE_ALIGN(vb->planes[plane].length);
>  	if (length < (vma->vm_end - vma->vm_start)) {
>  		dprintk(1,
>  			"MMAP invalid, as it would overflow buffer length\n");
> @@ -2577,10 +2618,10 @@ EXPORT_SYMBOL_GPL(vb2_mmap);
>  
>  #ifndef CONFIG_MMU
>  unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
> -				    unsigned long addr,
> -				    unsigned long len,
> -				    unsigned long pgoff,
> -				    unsigned long flags)
> +					unsigned long addr,
> +					unsigned long len,
> +					unsigned long pgoff,
> +					unsigned long flags)
>  {
>  	unsigned long off = pgoff << PAGE_SHIFT;
>  	struct vb2_buffer *vb;
> @@ -2731,7 +2772,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
>   * responsible of clearing it's content and setting initial values for some
>   * required entries before calling this function.
>   * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
> - * to the struct vb2_queue description in include/media/videobuf2-v4l2.h
> + * to the struct vb2_queue description in include/media/videobuf2-core.h
>   * for more information.
>   */
>  int vb2_queue_init(struct vb2_queue *q)
> @@ -2739,16 +2780,16 @@ int vb2_queue_init(struct vb2_queue *q)
>  	/*
>  	 * Sanity check
>  	 */
> -	if (WARN_ON(!q)			  ||
> -	    WARN_ON(!q->ops)		  ||
> -	    WARN_ON(!q->mem_ops)	  ||
> -	    WARN_ON(!q->type)		  ||
> -	    WARN_ON(!q->io_modes)	  ||
> -	    WARN_ON(!q->ops->queue_setup) ||
> -	    WARN_ON(!q->ops->buf_queue)   ||
> -	    WARN_ON(q->timestamp_flags &
> -		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> -		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
> +	if (WARN_ON(!q)				||
> +		WARN_ON(!q->ops)		||
> +		WARN_ON(!q->mem_ops)		||
> +		WARN_ON(!q->type)		||
> +		WARN_ON(!q->io_modes)		||
> +		WARN_ON(!q->ops->queue_setup)	||
> +		WARN_ON(!q->ops->buf_queue)	||
> +		WARN_ON(q->timestamp_flags &
> +			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> +			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
>  		return -EINVAL;
>  
>  	/* Warn that the driver should choose an appropriate timestamp type */
> @@ -2852,7 +2893,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>  	 * Sanity check
>  	 */
>  	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
> -		    (!read && !(q->io_modes & VB2_WRITE))))
> +			(!read && !(q->io_modes & VB2_WRITE))))
>  		return -EINVAL;
>  
>  	/*
> @@ -3063,9 +3104,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>  		buf->queued = 0;
>  		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>  				 : vb2_plane_size(q->bufs[index], 0);
> -		/* Compensate for data_offset on read in the multiplanar case. */
> +		/*
> +		 * Compensate for data_offset on read
> +		 * in the multiplanar case
> +		 */
>  		if (is_multiplanar && read &&
> -		    fileio->b.m.planes[0].data_offset < buf->size) {
> +			fileio->b.m.planes[0].data_offset < buf->size) {
>  			buf->pos = fileio->b.m.planes[0].data_offset;
>  			buf->size -= buf->pos;
>  		}
> @@ -3257,7 +3301,7 @@ static int vb2_thread(void *data)
>   * contact the linux-media mailinglist first.
>   */
>  int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> -		     const char *thread_name)
> +			const char *thread_name)
>  {
>  	struct vb2_threadio_data *threadio;
>  	int ret = 0;
> @@ -3491,7 +3535,7 @@ ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>  	if (vb2_queue_is_busy(vdev, file))
>  		goto exit;
>  	err = vb2_write(vdev->queue, buf, count, ppos,
> -		       file->f_flags & O_NONBLOCK);
> +			file->f_flags & O_NONBLOCK);
>  	if (vdev->queue->fileio)
>  		vdev->queue->owner = file->private_data;
>  exit:
> @@ -3515,7 +3559,7 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf,
>  	if (vb2_queue_is_busy(vdev, file))
>  		goto exit;
>  	err = vb2_read(vdev->queue, buf, count, ppos,
> -		       file->f_flags & O_NONBLOCK);
> +			file->f_flags & O_NONBLOCK);
>  	if (vdev->queue->fileio)
>  		vdev->queue->owner = file->private_data;
>  exit:
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index 155991e..8787a6c 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -115,6 +115,16 @@ struct vb2_plane {
>  	void			*mem_priv;
>  	struct dma_buf		*dbuf;
>  	unsigned int		dbuf_mapped;
> +
> +	/* plane information */
> +	unsigned int		bytesused;
> +	unsigned int		length;
> +	union {
> +		unsigned int	offset;
> +		unsigned long	userptr;
> +		int		fd;
> +	} m;
> +	unsigned int		data_offset;
>  };

Nitpick: it would be good to add a documentation for struct vb2_plane,
describing what each field means on this struct. Granted, this could
be added after this patch series. 

Btw, I don't see much reason to have the:
	/* plane information */
comment here, as this struct is all about plane information, right?
Or, maybe you wanted, instead, to comment that those fields should
have what's there at struct v4l2_plane? That would make sense ;)
So, I would change this comment to something like:

	/*
	 * Should contain enough plane information to contain the
	 * fields needed to fill struct v4l2_plane at videodev2.h
	 */


>  
>  /**
> @@ -161,41 +171,33 @@ struct vb2_queue;
>  
>  /**
>   * struct vb2_buffer - represents a video buffer
> - * @v4l2_buf:		struct v4l2_buffer associated with this buffer; can
> - *			be read by the driver and relevant entries can be
> - *			changed by the driver in case of CAPTURE types
> - *			(such as timestamp)
> - * @v4l2_planes:	struct v4l2_planes associated with this buffer; can
> - *			be read by the driver and relevant entries can be
> - *			changed by the driver in case of CAPTURE types
> - *			(such as bytesused); NOTE that even for single-planar
> - *			types, the v4l2_planes[0] struct should be used
> - *			instead of v4l2_buf for filling bytesused - drivers
> - *			should use the vb2_set_plane_payload() function for that
>   * @vb2_queue:		the queue to which this driver belongs
> - * @num_planes:		number of planes in the buffer
> - *			on an internal driver queue
>   * @state:		current buffer state; do not change
>   * @queued_entry:	entry on the queued buffers list, which holds all
>   *			buffers queued from userspace
>   * @done_entry:		entry on the list that stores all buffers ready to
>   *			be dequeued to userspace
> + * @index:		id number of the buffer
> + * @type:		buffer type
> + * @memory:		the method, in which the actual data is passed
> + * @num_planes:		number of planes in the buffer
> + *			on an internal driver queue
>   * @planes:		private per-plane information; do not change
>   */
>  struct vb2_buffer {
> -	struct v4l2_buffer	v4l2_buf;
> -	struct v4l2_plane	v4l2_planes[VIDEO_MAX_PLANES];
> -
>  	struct vb2_queue	*vb2_queue;
>  
> -	unsigned int		num_planes;
> -
> -/* Private: internal use only */
> +	/* Private: internal use only */
>  	enum vb2_buffer_state	state;
>  
>  	struct list_head	queued_entry;
>  	struct list_head	done_entry;
>  
> +	/* buffer information */
> +	unsigned int		index;
> +	unsigned int		type;
> +	unsigned int		memory;
> +	unsigned int		num_planes;

Nitpick: Those comments that follow Documentation/kernel-doc-nano-HOWTO.txt 
are used to produce DocBook data, on both html and manpages formats. 
As documented there, DocBook discards documentation for all fields after a
/*private: ...*/ comment.

In other words, we need to take care of putting things after /*private:*/
only when we're 100% sure that such fields are not meant to be filled/used
by the callers, and will be used only internally, and don't deserve any
documentation for the kABI.

As you're adding documentation for those fields, and num_planes were 
documented before your series, I suspect that this is not what you want.
So, please move them to be before the private: comment.

Btw, if your patches are based on top of the current patchwork tree
e. g. if it has this patch:
	http://git.linuxtv.org/cgit.cgi/media_tree.git/commit/?id=d071c833a0d30e7aae0ea565d92ef83c79106d6f

Then you can make the Kernel to handle all those kernel-doc-nano 
comments with:

	make cleandocs && make DOCBOOKS=device-drivers.xml htmldocs 

It will produce some html pages like:
	http://linuxtv.org/downloads/v4l-dvb-internals/device-drivers/mediadev.html

With can be useful to check if the documentation tags are properly placed.

>  	struct vb2_plane	planes[VIDEO_MAX_PLANES];
>  
>  #ifdef CONFIG_VIDEO_ADV_DEBUG
> @@ -390,7 +392,7 @@ struct v4l2_fh;
>   * @threadio:	thread io internal data, used only if thread is active
>   */
>  struct vb2_queue {
> -	enum v4l2_buf_type		type;
> +	unsigned int			type;
>  	unsigned int			io_modes;
>  	unsigned			fileio_read_once:1;
>  	unsigned			fileio_write_immediately:1;
> @@ -409,7 +411,7 @@ struct vb2_queue {
>  
>  	/* private: internal use only */
>  	struct mutex			mmap_lock;
> -	enum v4l2_memory		memory;
> +	unsigned int			memory;

Will the vb2-core use type/memory fields or just vb2-v4l2? As you
removed the enum, I suspect you won't be relying on having the videodev2.h
header included here, right.

If so, then the meaning of the type/memory fields are private to the
caller of the VB2-core  (e. .g. the meaning are private to vb2-v4l2 and
vb2-dvb). So, you should be changing the description of those fields
at the doc-nano to:
...
 * @type: private type whose content is defined by the vb2-core caller.
 *        For example, for V4L2, it should match the V4L2_BUF_TYPE_*
 *	  in include/uapi/linux/videodev2.h
...

to let it clear.

>  	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
>  	unsigned int			num_buffers;
>  
> @@ -571,7 +573,7 @@ static inline void vb2_set_plane_payload(struct vb2_buffer *vb,
>  				 unsigned int plane_no, unsigned long size)
>  {
>  	if (plane_no < vb->num_planes)
> -		vb->v4l2_planes[plane_no].bytesused = size;
> +		vb->planes[plane_no].bytesused = size;
>  }
>  
>  /**
> @@ -583,7 +585,7 @@ static inline unsigned long vb2_get_plane_payload(struct vb2_buffer *vb,
>  				 unsigned int plane_no)
>  {
>  	if (plane_no < vb->num_planes)
> -		return vb->v4l2_planes[plane_no].bytesused;
> +		return vb->planes[plane_no].bytesused;
>  	return 0;
>  }
>  
> @@ -596,7 +598,7 @@ static inline unsigned long
>  vb2_plane_size(struct vb2_buffer *vb, unsigned int plane_no)
>  {
>  	if (plane_no < vb->num_planes)
> -		return vb->v4l2_planes[plane_no].length;
> +		return vb->planes[plane_no].length;
>  	return 0;
>  }
>  
> diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
> index d4a4d9a..fc2dbe9 100644
> --- a/include/media/videobuf2-v4l2.h
> +++ b/include/media/videobuf2-v4l2.h
> @@ -12,6 +12,32 @@
>  #ifndef _MEDIA_VIDEOBUF2_V4L2_H
>  #define _MEDIA_VIDEOBUF2_V4L2_H
>  
> +#include <linux/videodev2.h>
>  #include <media/videobuf2-core.h>
>  
> +/**
> + * struct vb2_v4l2_buffer - video buffer information for v4l2
> + * @vb2_buf:	video buffer 2
> + * @flags:	buffer informational flags
> + * @field:	enum v4l2_field; field order of the image in the buffer
> + * @timestamp:	frame timestamp
> + * @timecode:	frame timecode
> + * @sequence:	sequence count of this frame
> + */
> +struct vb2_v4l2_buffer {
> +	struct vb2_buffer	vb2_buf;
> +
> +	__u32			flags;
> +	__u32			field;
> +	struct timeval		timestamp;
> +	struct v4l2_timecode	timecode;
> +	__u32			sequence;
> +};
> +
> +/**
> + * to_vb2_v4l2_buffer() - cast struct vb2_buffer * to struct vb2_v4l2_buffer *
> + */
> +#define to_vb2_v4l2_buffer(vb) \
> +	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
> +
>  #endif /* _MEDIA_VIDEOBUF2_V4L2_H */

Regards,
Mauro


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 3/5] media: videobuf2: Modify all device drivers
  2015-08-26 11:59 ` [RFC PATCH v3 3/5] media: videobuf2: Modify all device drivers Junghak Sung
@ 2015-08-27 10:33   ` Mauro Carvalho Chehab
  2015-08-28  2:19     ` Junghak Sung
  0 siblings, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2015-08-27 10:33 UTC (permalink / raw)
  To: Junghak Sung
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Em Wed, 26 Aug 2015 20:59:30 +0900
Junghak Sung <jh1009.sung@samsung.com> escreveu:

> Modify all device drivers related with previous change that restructures
> vb2_buffer for common use.
> Actually, not all device drivers, yet. So, it required to modifiy more file
> to complete this patch.

I was expecting to be able to compile everything after applying both
patches 2 and 3, but compilation failed:

In file included from drivers/media/platform/am437x/am437x-vpfe.c:41:0:
drivers/media/platform/am437x/am437x-vpfe.h:107:25: error: field 'vb' has incomplete type
  struct vb2_v4l2_buffer vb;
                         ^
drivers/media/platform/am437x/am437x-vpfe.c: In function 'to_vpfe_buffer':
drivers/media/platform/am437x/am437x-vpfe.c:312:72: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
drivers/media/platform/am437x/am437x-vpfe.c: In function 'vpfe_buffer_prepare':
drivers/media/platform/am437x/am437x-vpfe.c:1952:4: error: 'struct vb2_buffer' has no member named 'v4l2_buf'
  vb->v4l2_buf.field = vpfe->fmt.fmt.pix.field;
    ^
drivers/media/platform/am437x/am437x-vpfe.c: In function 'to_vpfe_buffer':
drivers/media/platform/am437x/am437x-vpfe.c:313:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
scripts/Makefile.build:258: recipe for target 'drivers/media/platform/am437x/am437x-vpfe.o' failed
make[3]: *** [drivers/media/platform/am437x/am437x-vpfe.o] Error 1
scripts/Makefile.build:403: recipe for target 'drivers/media/platform/am437x' failed
make[2]: *** [drivers/media/platform/am437x] Error 2
scripts/Makefile.build:403: recipe for target 'drivers/media/platform' failed
make[1]: *** [drivers/media/platform] Error 2
make[1]: *** Waiting for unfinished jobs....
In file included from drivers/media/pci/cobalt/cobalt-driver.c:30:0:
drivers/media/pci/cobalt/cobalt-driver.h:209:25: error: field 'vb' has incomplete type
  struct vb2_v4l2_buffer vb;
                         ^
drivers/media/pci/cobalt/cobalt-driver.h: In function 'to_cobalt_buffer':
drivers/media/pci/cobalt/cobalt-driver.h:215:70: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
scripts/Makefile.build:258: recipe for target 'drivers/media/pci/cobalt/cobalt-driver.o' failed
make[3]: *** [drivers/media/pci/cobalt/cobalt-driver.o] Error 1
scripts/Makefile.build:403: recipe for target 'drivers/media/pci/cobalt' failed
make[2]: *** [drivers/media/pci/cobalt] Error 2
scripts/Makefile.build:403: recipe for target 'drivers/media/pci' failed
make[1]: *** [drivers/media/pci] Error 2
drivers/media/dvb-frontends/rtl2832_sdr.c:110:25: error: field 'vb' has incomplete type
  struct vb2_v4l2_buffer vb;   /* common v4l buffer stuff -- must be first */
                         ^
drivers/media/dvb-frontends/rtl2832_sdr.c: In function 'rtl2832_sdr_buf_queue':
drivers/media/dvb-frontends/rtl2832_sdr.c:523:73: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
drivers/media/dvb-frontends/rtl2832_sdr.c:523:73: note: (near initialization for 'buf')
scripts/Makefile.build:258: recipe for target 'drivers/media/dvb-frontends/rtl2832_sdr.o' failed
make[2]: *** [drivers/media/dvb-frontends/rtl2832_sdr.o] Error 1
scripts/Makefile.build:403: recipe for target 'drivers/media/dvb-frontends' failed
make[1]: *** [drivers/media/dvb-frontends] Error 2
Makefile:1380: recipe for target '_module_drivers/media' failed
make: *** [_module_drivers/media] Error 2


So, obviously there's something wrong there. Please fix.

I'll skip this patch from my review.

Thanks!
Mauro

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 4/5] media: videobuf2: Change queue_setup argument
  2015-08-26 11:59 ` [RFC PATCH v3 4/5] media: videobuf2: Change queue_setup argument Junghak Sung
@ 2015-08-27 10:45   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2015-08-27 10:45 UTC (permalink / raw)
  To: Junghak Sung
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Em Wed, 26 Aug 2015 20:59:31 +0900
Junghak Sung <jh1009.sung@samsung.com> escreveu:

> Replace struct v4l2_format * with void * to make queue_setup()
> for common use.
> And then, modify all device drivers related with this change.
> 
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
> ---
>  drivers/input/touchscreen/sur40.c                  |    3 ++-
>  drivers/media/dvb-frontends/rtl2832_sdr.c          |    2 +-
>  drivers/media/pci/cobalt/cobalt-v4l2.c             |    3 ++-
>  drivers/media/pci/cx23885/cx23885-417.c            |    2 +-
>  drivers/media/pci/cx23885/cx23885-dvb.c            |    2 +-
>  drivers/media/pci/cx23885/cx23885-vbi.c            |    2 +-
>  drivers/media/pci/cx23885/cx23885-video.c          |    2 +-
>  drivers/media/pci/cx25821/cx25821-video.c          |    3 ++-
>  drivers/media/pci/cx88/cx88-blackbird.c            |    2 +-
>  drivers/media/pci/cx88/cx88-dvb.c                  |    2 +-
>  drivers/media/pci/cx88/cx88-vbi.c                  |    2 +-
>  drivers/media/pci/cx88/cx88-video.c                |    2 +-
>  drivers/media/pci/dt3155/dt3155.c                  |    3 ++-
>  drivers/media/pci/netup_unidvb/netup_unidvb_core.c |    2 +-
>  drivers/media/pci/saa7134/saa7134-ts.c             |    2 +-
>  drivers/media/pci/saa7134/saa7134-vbi.c            |    2 +-
>  drivers/media/pci/saa7134/saa7134-video.c          |    2 +-
>  drivers/media/pci/saa7134/saa7134.h                |    2 +-
>  drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c     |    2 +-
>  drivers/media/pci/solo6x10/solo6x10-v4l2.c         |    2 +-
>  drivers/media/pci/sta2x11/sta2x11_vip.c            |    2 +-
>  drivers/media/pci/tw68/tw68-video.c                |    3 ++-
>  drivers/media/platform/am437x/am437x-vpfe.c        |    3 ++-
>  drivers/media/platform/blackfin/bfin_capture.c     |    3 ++-
>  drivers/media/platform/coda/coda-common.c          |    2 +-
>  drivers/media/platform/davinci/vpbe_display.c      |    3 ++-
>  drivers/media/platform/davinci/vpif_capture.c      |    3 ++-
>  drivers/media/platform/davinci/vpif_display.c      |    3 ++-
>  drivers/media/platform/exynos-gsc/gsc-m2m.c        |    2 +-
>  drivers/media/platform/exynos4-is/fimc-capture.c   |    3 ++-
>  drivers/media/platform/exynos4-is/fimc-isp-video.c |    3 ++-
>  drivers/media/platform/exynos4-is/fimc-lite.c      |    3 ++-
>  drivers/media/platform/exynos4-is/fimc-m2m.c       |    2 +-
>  drivers/media/platform/m2m-deinterlace.c           |    2 +-
>  drivers/media/platform/marvell-ccic/mcam-core.c    |    3 ++-
>  drivers/media/platform/mx2_emmaprp.c               |    2 +-
>  drivers/media/platform/omap3isp/ispvideo.c         |    2 +-
>  drivers/media/platform/rcar_jpu.c                  |    3 ++-
>  drivers/media/platform/s3c-camif/camif-capture.c   |    3 ++-
>  drivers/media/platform/s5p-g2d/g2d.c               |    2 +-
>  drivers/media/platform/s5p-jpeg/jpeg-core.c        |    2 +-
>  drivers/media/platform/s5p-mfc/s5p_mfc_dec.c       |    2 +-
>  drivers/media/platform/s5p-mfc/s5p_mfc_enc.c       |    2 +-
>  drivers/media/platform/s5p-tv/mixer_video.c        |    2 +-
>  drivers/media/platform/sh_veu.c                    |    3 ++-
>  drivers/media/platform/sh_vou.c                    |    3 ++-
>  drivers/media/platform/soc_camera/atmel-isi.c      |    2 +-
>  drivers/media/platform/soc_camera/mx2_camera.c     |    3 ++-
>  drivers/media/platform/soc_camera/mx3_camera.c     |    3 ++-
>  drivers/media/platform/soc_camera/rcar_vin.c       |    3 ++-
>  .../platform/soc_camera/sh_mobile_ceu_camera.c     |    6 ++++--
>  drivers/media/platform/sti/bdisp/bdisp-v4l2.c      |    3 ++-
>  drivers/media/platform/ti-vpe/vpe.c                |    2 +-
>  drivers/media/platform/vim2m.c                     |    3 ++-
>  drivers/media/platform/vivid/vivid-sdr-cap.c       |    2 +-
>  drivers/media/platform/vivid/vivid-vbi-cap.c       |    2 +-
>  drivers/media/platform/vivid/vivid-vbi-out.c       |    2 +-
>  drivers/media/platform/vivid/vivid-vid-cap.c       |    3 ++-
>  drivers/media/platform/vivid/vivid-vid-out.c       |    3 ++-
>  drivers/media/platform/vsp1/vsp1_video.c           |    3 ++-
>  drivers/media/platform/xilinx/xilinx-dma.c         |    3 ++-
>  drivers/media/usb/airspy/airspy.c                  |    2 +-
>  drivers/media/usb/au0828/au0828-vbi.c              |    3 ++-
>  drivers/media/usb/au0828/au0828-video.c            |    3 ++-
>  drivers/media/usb/em28xx/em28xx-vbi.c              |    3 ++-
>  drivers/media/usb/em28xx/em28xx-video.c            |    3 ++-
>  drivers/media/usb/go7007/go7007-v4l2.c             |    2 +-
>  drivers/media/usb/hackrf/hackrf.c                  |    2 +-
>  drivers/media/usb/msi2500/msi2500.c                |    2 +-
>  drivers/media/usb/pwc/pwc-if.c                     |    2 +-
>  drivers/media/usb/s2255/s2255drv.c                 |    2 +-
>  drivers/media/usb/stk1160/stk1160-v4l.c            |    2 +-
>  drivers/media/usb/usbtv/usbtv-video.c              |    3 ++-
>  drivers/media/usb/uvc/uvc_queue.c                  |    3 ++-
>  drivers/staging/media/davinci_vpfe/vpfe_video.c    |    2 +-
>  drivers/staging/media/omap4iss/iss_video.c         |    2 +-
>  drivers/usb/gadget/function/uvc_queue.c            |    2 +-
>  include/media/videobuf2-core.h                     |    2 +-
>  78 files changed, 114 insertions(+), 79 deletions(-)
> 
> diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
> index 8d0b6f0..767ddc8 100644
> --- a/drivers/input/touchscreen/sur40.c
> +++ b/drivers/input/touchscreen/sur40.c
> @@ -643,10 +643,11 @@ static void sur40_disconnect(struct usb_interface *interface)
>   * minimum number: many DMA engines need a minimum of 2 buffers in the
>   * queue and you need to have another available for userspace processing.
>   */
> -static int sur40_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int sur40_queue_setup(struct vb2_queue *q, const void *parg,
>  		       unsigned int *nbuffers, unsigned int *nplanes,
>  		       unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;

No need to typecast. Just do:

	struct v4l2_format *fmt = parg;

We only use such typecasts when:
	- a warning is generated
	- a static code analyzer like  smatch/spatch complains;
	- in the cases that the pointers belong to different memory
	  domains (like __user pointers).

The same comment here applies to the similar changes below.

Regards,
Mauro

>  	struct sur40_state *sur40 = vb2_get_drv_priv(q);
>  
>  	if (q->num_buffers + *nbuffers < 3)
> diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
> index 3501215..7d884c5 100644
> --- a/drivers/media/dvb-frontends/rtl2832_sdr.c
> +++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
> @@ -488,7 +488,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
>  
>  /* Videobuf2 operations */
>  static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
> -		const struct v4l2_format *fmt, unsigned int *nbuffers,
> +		const void *parg, unsigned int *nbuffers,
>  		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
>  {
>  	struct rtl2832_sdr_dev *dev = vb2_get_drv_priv(vq);
> diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c b/drivers/media/pci/cobalt/cobalt-v4l2.c
> index e72480a..0c083b3 100644
> --- a/drivers/media/pci/cobalt/cobalt-v4l2.c
> +++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
> @@ -44,10 +44,11 @@ static const struct v4l2_dv_timings cea1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
>  /* vb2 DMA streaming ops */
>  
>  static int cobalt_queue_setup(struct vb2_queue *q,
> -			const struct v4l2_format *fmt,
> +			const void *parg,
>  			unsigned int *num_buffers, unsigned int *num_planes,
>  			unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct cobalt_stream *s = q->drv_priv;
>  	unsigned size = s->stride * s->height;
>  
> diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
> index 316a322..88a3afb 100644
> --- a/drivers/media/pci/cx23885/cx23885-417.c
> +++ b/drivers/media/pci/cx23885/cx23885-417.c
> @@ -1138,7 +1138,7 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
>  
>  /* ------------------------------------------------------------------ */
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
> index 09ad512..c4307ad 100644
> --- a/drivers/media/pci/cx23885/cx23885-dvb.c
> +++ b/drivers/media/pci/cx23885/cx23885-dvb.c
> @@ -92,7 +92,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
>  
>  /* ------------------------------------------------------------------ */
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
> index 6c9bb03..cf3cb13 100644
> --- a/drivers/media/pci/cx23885/cx23885-vbi.c
> +++ b/drivers/media/pci/cx23885/cx23885-vbi.c
> @@ -121,7 +121,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev    *dev,
>  
>  /* ------------------------------------------------------------------ */
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
> index b6a193d..71a80e2 100644
> --- a/drivers/media/pci/cx23885/cx23885-video.c
> +++ b/drivers/media/pci/cx23885/cx23885-video.c
> @@ -315,7 +315,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev,
>  	return 0;
>  }
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
> index f1deb8f..69ee134 100644
> --- a/drivers/media/pci/cx25821/cx25821-video.c
> +++ b/drivers/media/pci/cx25821/cx25821-video.c
> @@ -141,10 +141,11 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
>  	return handled;
>  }
>  
> -static int cx25821_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int cx25821_queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct cx25821_channel *chan = q->drv_priv;
>  	unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3;
>  
> diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
> index 49d0b7c..8b88913 100644
> --- a/drivers/media/pci/cx88/cx88-blackbird.c
> +++ b/drivers/media/pci/cx88/cx88-blackbird.c
> @@ -637,7 +637,7 @@ static int blackbird_stop_codec(struct cx8802_dev *dev)
>  
>  /* ------------------------------------------------------------------ */
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
> index f0923fb..f048350 100644
> --- a/drivers/media/pci/cx88/cx88-dvb.c
> +++ b/drivers/media/pci/cx88/cx88-dvb.c
> @@ -82,7 +82,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
>  
>  /* ------------------------------------------------------------------ */
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
> index 1d65543..007a5ee 100644
> --- a/drivers/media/pci/cx88/cx88-vbi.c
> +++ b/drivers/media/pci/cx88/cx88-vbi.c
> @@ -107,7 +107,7 @@ int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
>  
>  /* ------------------------------------------------------------------ */
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
> index c6a337a..f3b12db 100644
> --- a/drivers/media/pci/cx88/cx88-video.c
> +++ b/drivers/media/pci/cx88/cx88-video.c
> @@ -429,7 +429,7 @@ static int restart_video_queue(struct cx8800_dev    *dev,
>  
>  /* ------------------------------------------------------------------ */
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/dt3155/dt3155.c b/drivers/media/pci/dt3155/dt3155.c
> index f27a858..d041526 100644
> --- a/drivers/media/pci/dt3155/dt3155.c
> +++ b/drivers/media/pci/dt3155/dt3155.c
> @@ -131,11 +131,12 @@ static int wait_i2c_reg(void __iomem *addr)
>  }
>  
>  static int
> -dt3155_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +dt3155_queue_setup(struct vb2_queue *vq, const void *parg,
>  		unsigned int *nbuffers, unsigned int *num_planes,
>  		unsigned int sizes[], void *alloc_ctxs[])
>  
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct dt3155_priv *pd = vb2_get_drv_priv(vq);
>  	unsigned size = pd->width * pd->height;
>  
> diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
> index b012aa65..f0d5a40 100644
> --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
> +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
> @@ -279,7 +279,7 @@ static irqreturn_t netup_unidvb_isr(int irq, void *dev_id)
>  }
>  
>  static int netup_unidvb_queue_setup(struct vb2_queue *vq,
> -				    const struct v4l2_format *fmt,
> +				    const void *parg,
>  				    unsigned int *nbuffers,
>  				    unsigned int *nplanes,
>  				    unsigned int sizes[],
> diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
> index b0ef37d..7fb5ee7 100644
> --- a/drivers/media/pci/saa7134/saa7134-ts.c
> +++ b/drivers/media/pci/saa7134/saa7134-ts.c
> @@ -116,7 +116,7 @@ int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2)
>  }
>  EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
>  
> -int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
> index fb1605e..6271b0e 100644
> --- a/drivers/media/pci/saa7134/saa7134-vbi.c
> +++ b/drivers/media/pci/saa7134/saa7134-vbi.c
> @@ -138,7 +138,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
>  				    saa7134_buffer_startpage(buf));
>  }
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
> index 602d53d..518086c 100644
> --- a/drivers/media/pci/saa7134/saa7134-video.c
> +++ b/drivers/media/pci/saa7134/saa7134-video.c
> @@ -904,7 +904,7 @@ static int buffer_prepare(struct vb2_buffer *vb2)
>  				    saa7134_buffer_startpage(buf));
>  }
>  
> -static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
> index 002ba1d8..984e81d 100644
> --- a/drivers/media/pci/saa7134/saa7134.h
> +++ b/drivers/media/pci/saa7134/saa7134.h
> @@ -819,7 +819,7 @@ void saa7134_video_fini(struct saa7134_dev *dev);
>  
>  int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
>  int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
> -int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +int saa7134_ts_queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[]);
>  int saa7134_ts_start_streaming(struct vb2_queue *vq, unsigned int count);
> diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
> index fb71f2f..b79fc6f 100644
> --- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
> +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
> @@ -659,7 +659,7 @@ static int solo_ring_thread(void *data)
>  }
>  
>  static int solo_enc_queue_setup(struct vb2_queue *q,
> -				const struct v4l2_format *fmt,
> +				const void *parg,
>  				unsigned int *num_buffers,
>  				unsigned int *num_planes, unsigned int sizes[],
>  				void *alloc_ctxs[])
> diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2.c b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
> index 63ae8a6..d2c9a83 100644
> --- a/drivers/media/pci/solo6x10/solo6x10-v4l2.c
> +++ b/drivers/media/pci/solo6x10/solo6x10-v4l2.c
> @@ -311,7 +311,7 @@ static void solo_stop_thread(struct solo_dev *solo_dev)
>  	solo_dev->kthread = NULL;
>  }
>  
> -static int solo_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int solo_queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
> index 8fe6ea6..7a8e4b4 100644
> --- a/drivers/media/pci/sta2x11/sta2x11_vip.c
> +++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
> @@ -265,7 +265,7 @@ static void vip_active_buf_next(struct sta2x11_vip *vip)
>  
>  
>  /* Videobuf2 Operations */
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned int *nbuffers, unsigned int *nplanes,
>  		       unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
> index ae06535..85ad311 100644
> --- a/drivers/media/pci/tw68/tw68-video.c
> +++ b/drivers/media/pci/tw68/tw68-video.c
> @@ -376,10 +376,11 @@ static int tw68_buffer_count(unsigned int size, unsigned int count)
>  /* ------------------------------------------------------------- */
>  /* vb2 queue operations                                          */
>  
> -static int tw68_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
> +static int tw68_queue_setup(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct tw68_dev *dev = vb2_get_drv_priv(q);
>  	unsigned tot_bufs = q->num_buffers + *num_buffers;
>  
> diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
> index 85649ca..5ef5a1e 100644
> --- a/drivers/media/platform/am437x/am437x-vpfe.c
> +++ b/drivers/media/platform/am437x/am437x-vpfe.c
> @@ -1907,10 +1907,11 @@ static void vpfe_calculate_offsets(struct vpfe_device *vpfe)
>   * the buffer count and buffer size
>   */
>  static int vpfe_queue_setup(struct vb2_queue *vq,
> -			    const struct v4l2_format *fmt,
> +			    const void *parg,
>  			    unsigned int *nbuffers, unsigned int *nplanes,
>  			    unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct vpfe_device *vpfe = vb2_get_drv_priv(vq);
>  
>  	if (fmt && fmt->fmt.pix.sizeimage < vpfe->fmt.fmt.pix.sizeimage)
> diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
> index 4bb3208..2dc2351 100644
> --- a/drivers/media/platform/blackfin/bfin_capture.c
> +++ b/drivers/media/platform/blackfin/bfin_capture.c
> @@ -202,10 +202,11 @@ static void bcap_free_sensor_formats(struct bcap_device *bcap_dev)
>  }
>  
>  static int bcap_queue_setup(struct vb2_queue *vq,
> -				const struct v4l2_format *fmt,
> +				const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct bcap_device *bcap_dev = vb2_get_drv_priv(vq);
>  
>  	if (fmt && fmt->fmt.pix.sizeimage < bcap_dev->fmt.sizeimage)
> diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
> index 6e0c9be..be63ab9 100644
> --- a/drivers/media/platform/coda/coda-common.c
> +++ b/drivers/media/platform/coda/coda-common.c
> @@ -1132,7 +1132,7 @@ static void set_default_params(struct coda_ctx *ctx)
>   * Queue operations
>   */
>  static int coda_queue_setup(struct vb2_queue *vq,
> -				const struct v4l2_format *fmt,
> +				const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
> index f69cdd7..5798247 100644
> --- a/drivers/media/platform/davinci/vpbe_display.c
> +++ b/drivers/media/platform/davinci/vpbe_display.c
> @@ -228,11 +228,12 @@ static int vpbe_buffer_prepare(struct vb2_buffer *vb)
>   * This function allocates memory for the buffers
>   */
>  static int
> -vpbe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +vpbe_buffer_queue_setup(struct vb2_queue *vq, const void *parg,
>  			unsigned int *nbuffers, unsigned int *nplanes,
>  			unsigned int sizes[], void *alloc_ctxs[])
>  
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	/* Get the file handle object and layer object */
>  	struct vpbe_layer *layer = vb2_get_drv_priv(vq);
>  	struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
> diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
> index d7ddc7d..f8a7338 100644
> --- a/drivers/media/platform/davinci/vpif_capture.c
> +++ b/drivers/media/platform/davinci/vpif_capture.c
> @@ -112,10 +112,11 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
>   * the buffer count and buffer size
>   */
>  static int vpif_buffer_queue_setup(struct vb2_queue *vq,
> -				const struct v4l2_format *fmt,
> +				const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct channel_obj *ch = vb2_get_drv_priv(vq);
>  	struct common_obj *common;
>  
> diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
> index f641bc0..5df9b1e 100644
> --- a/drivers/media/platform/davinci/vpif_display.c
> +++ b/drivers/media/platform/davinci/vpif_display.c
> @@ -107,10 +107,11 @@ static int vpif_buffer_prepare(struct vb2_buffer *vb)
>   * the buffer count and buffer size
>   */
>  static int vpif_buffer_queue_setup(struct vb2_queue *vq,
> -				const struct v4l2_format *fmt,
> +				const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct channel_obj *ch = vb2_get_drv_priv(vq);
>  	struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
>  
> diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
> index d5cffef..d967f17 100644
> --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
> +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
> @@ -212,7 +212,7 @@ put_device:
>  }
>  
>  static int gsc_m2m_queue_setup(struct vb2_queue *vq,
> -			const struct v4l2_format *fmt,
> +			const void *parg,
>  			unsigned int *num_buffers, unsigned int *num_planes,
>  			unsigned int sizes[], void *allocators[])
>  {
> diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
> index 3844d6c..fd545a0 100644
> --- a/drivers/media/platform/exynos4-is/fimc-capture.c
> +++ b/drivers/media/platform/exynos4-is/fimc-capture.c
> @@ -344,10 +344,11 @@ int fimc_capture_resume(struct fimc_dev *fimc)
>  
>  }
>  
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned int *num_buffers, unsigned int *num_planes,
>  		       unsigned int sizes[], void *allocators[])
>  {
> +	struct v4l2_format *pfmt = (struct v4l2_format *)parg;
>  	const struct v4l2_pix_format_mplane *pixm = NULL;
>  	struct fimc_ctx *ctx = vq->drv_priv;
>  	struct fimc_frame *frame = &ctx->d_frame;
> diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c
> index 195f9b5..4b583ed 100644
> --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c
> +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c
> @@ -39,10 +39,11 @@
>  #include "fimc-is-param.h"
>  
>  static int isp_video_capture_queue_setup(struct vb2_queue *vq,
> -			const struct v4l2_format *pfmt,
> +			const void *parg,
>  			unsigned int *num_buffers, unsigned int *num_planes,
>  			unsigned int sizes[], void *allocators[])
>  {
> +	struct v4l2_format *pfmt = (struct v4l2_format *)parg;
>  	struct fimc_isp *isp = vb2_get_drv_priv(vq);
>  	struct v4l2_pix_format_mplane *vid_fmt = &isp->video_capture.pixfmt;
>  	const struct v4l2_pix_format_mplane *pixm = NULL;
> diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
> index 21527cf..fdb4fcf 100644
> --- a/drivers/media/platform/exynos4-is/fimc-lite.c
> +++ b/drivers/media/platform/exynos4-is/fimc-lite.c
> @@ -360,10 +360,11 @@ static void stop_streaming(struct vb2_queue *q)
>  	fimc_lite_stop_capture(fimc, false);
>  }
>  
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned int *num_buffers, unsigned int *num_planes,
>  		       unsigned int sizes[], void *allocators[])
>  {
> +	struct v4l2_format *pfmt = (struct v4l2_format *)parg;
>  	const struct v4l2_pix_format_mplane *pixm = NULL;
>  	struct fimc_lite *fimc = vq->drv_priv;
>  	struct flite_frame *frame = &fimc->out_frame;
> diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
> index 9c27335..bd72ab3 100644
> --- a/drivers/media/platform/exynos4-is/fimc-m2m.c
> +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
> @@ -176,7 +176,7 @@ static void fimc_job_abort(void *priv)
>  	fimc_m2m_shutdown(priv);
>  }
>  
> -static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int fimc_queue_setup(struct vb2_queue *vq, const void *parg,
>  			    unsigned int *num_buffers, unsigned int *num_planes,
>  			    unsigned int sizes[], void *allocators[])
>  {
> diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
> index bdd8f11..29973f9 100644
> --- a/drivers/media/platform/m2m-deinterlace.c
> +++ b/drivers/media/platform/m2m-deinterlace.c
> @@ -798,7 +798,7 @@ struct vb2_dc_conf {
>  };
>  
>  static int deinterlace_queue_setup(struct vb2_queue *vq,
> -				const struct v4l2_format *fmt,
> +				const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
> index 1d95842..fb9615b 100644
> --- a/drivers/media/platform/marvell-ccic/mcam-core.c
> +++ b/drivers/media/platform/marvell-ccic/mcam-core.c
> @@ -1049,10 +1049,11 @@ static int mcam_read_setup(struct mcam_camera *cam)
>   */
>  
>  static int mcam_vb_queue_setup(struct vb2_queue *vq,
> -		const struct v4l2_format *fmt, unsigned int *nbufs,
> +		const void *parg, unsigned int *nbufs,
>  		unsigned int *num_planes, unsigned int sizes[],
>  		void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct mcam_camera *cam = vb2_get_drv_priv(vq);
>  	int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2;
>  
> diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
> index 87314b7..0a4c336 100644
> --- a/drivers/media/platform/mx2_emmaprp.c
> +++ b/drivers/media/platform/mx2_emmaprp.c
> @@ -689,7 +689,7 @@ static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = {
>   * Queue operations
>   */
>  static int emmaprp_queue_setup(struct vb2_queue *vq,
> -				const struct v4l2_format *fmt,
> +				const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
> index 08c9f62..3aa61e8 100644
> --- a/drivers/media/platform/omap3isp/ispvideo.c
> +++ b/drivers/media/platform/omap3isp/ispvideo.c
> @@ -320,7 +320,7 @@ isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
>   */
>  
>  static int isp_video_queue_setup(struct vb2_queue *queue,
> -				 const struct v4l2_format *fmt,
> +				 const void *parg,
>  				 unsigned int *count, unsigned int *num_planes,
>  				 unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c
> index 18e62d0..935eadb 100644
> --- a/drivers/media/platform/rcar_jpu.c
> +++ b/drivers/media/platform/rcar_jpu.c
> @@ -1015,10 +1015,11 @@ error_free:
>   * ============================================================================
>   */
>  static int jpu_queue_setup(struct vb2_queue *vq,
> -			   const struct v4l2_format *fmt,
> +			   const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct jpu_ctx *ctx = vb2_get_drv_priv(vq);
>  	struct jpu_q_data *q_data;
>  	unsigned int i;
> diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
> index dc67c4ec..8573922 100644
> --- a/drivers/media/platform/s3c-camif/camif-capture.c
> +++ b/drivers/media/platform/s3c-camif/camif-capture.c
> @@ -441,10 +441,11 @@ static void stop_streaming(struct vb2_queue *vq)
>  	camif_stop_capture(vp);
>  }
>  
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned int *num_buffers, unsigned int *num_planes,
>  		       unsigned int sizes[], void *allocators[])
>  {
> +	struct v4l2_format *pfmt = (struct v4l2_format *)parg;
>  	const struct v4l2_pix_format *pix = NULL;
>  	struct camif_vp *vp = vb2_get_drv_priv(vq);
>  	struct camif_dev *camif = vp->camif;
> diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
> index 81483da..b11497f 100644
> --- a/drivers/media/platform/s5p-g2d/g2d.c
> +++ b/drivers/media/platform/s5p-g2d/g2d.c
> @@ -101,7 +101,7 @@ static struct g2d_frame *get_frame(struct g2d_ctx *ctx,
>  	}
>  }
>  
> -static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int g2d_queue_setup(struct vb2_queue *vq, const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
> index 5b1861b..b89976e 100644
> --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
> +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
> @@ -2120,7 +2120,7 @@ static struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
>   */
>  
>  static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
> -			   const struct v4l2_format *fmt,
> +			   const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> index 2fd59e7..8443cb3 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
> @@ -883,7 +883,7 @@ static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
>  };
>  
>  static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> -			const struct v4l2_format *fmt, unsigned int *buf_count,
> +			const void *parg, unsigned int *buf_count,
>  			unsigned int *plane_count, unsigned int psize[],
>  			void *allocators[])
>  {
> diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> index e42014c..c94f6d2 100644
> --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
> @@ -1812,7 +1812,7 @@ static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
>  }
>  
>  static int s5p_mfc_queue_setup(struct vb2_queue *vq,
> -			const struct v4l2_format *fmt,
> +			const void *parg,
>  			unsigned int *buf_count, unsigned int *plane_count,
>  			unsigned int psize[], void *allocators[])
>  {
> diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
> index 5347a6c..6117045 100644
> --- a/drivers/media/platform/s5p-tv/mixer_video.c
> +++ b/drivers/media/platform/s5p-tv/mixer_video.c
> @@ -881,7 +881,7 @@ static const struct v4l2_file_operations mxr_fops = {
>  	.unlocked_ioctl = video_ioctl2,
>  };
>  
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  	unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[],
>  	void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
> index 6455cb9..461099e 100644
> --- a/drivers/media/platform/sh_veu.c
> +++ b/drivers/media/platform/sh_veu.c
> @@ -865,10 +865,11 @@ static const struct v4l2_ioctl_ops sh_veu_ioctl_ops = {
>  		/* ========== Queue operations ========== */
>  
>  static int sh_veu_queue_setup(struct vb2_queue *vq,
> -			      const struct v4l2_format *f,
> +			      const void *parg,
>  			      unsigned int *nbuffers, unsigned int *nplanes,
>  			      unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *f = (struct v4l2_format *)parg;
>  	struct sh_veu_dev *veu = vb2_get_drv_priv(vq);
>  	struct sh_veu_vfmt *vfmt;
>  	unsigned int size, count = *nbuffers;
> diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
> index 7014f2e..e624ada 100644
> --- a/drivers/media/platform/sh_vou.c
> +++ b/drivers/media/platform/sh_vou.c
> @@ -241,10 +241,11 @@ static void sh_vou_stream_config(struct sh_vou_device *vou_dev)
>  }
>  
>  /* Locking: caller holds fop_lock mutex */
> -static int sh_vou_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int sh_vou_queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned int *nbuffers, unsigned int *nplanes,
>  		       unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq);
>  	struct v4l2_pix_format *pix = &vou_dev->pix;
>  	int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8;
> diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
> index 6b312a4..f604114 100644
> --- a/drivers/media/platform/soc_camera/atmel-isi.c
> +++ b/drivers/media/platform/soc_camera/atmel-isi.c
> @@ -235,7 +235,7 @@ static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset)
>  /* ------------------------------------------------------------------
>  	Videobuf operations
>     ------------------------------------------------------------------*/
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
> index f4398bb..e07e1ec 100644
> --- a/drivers/media/platform/soc_camera/mx2_camera.c
> +++ b/drivers/media/platform/soc_camera/mx2_camera.c
> @@ -469,10 +469,11 @@ static void mx2_camera_clock_stop(struct soc_camera_host *ici)
>   *  Videobuf operations
>   */
>  static int mx2_videobuf_setup(struct vb2_queue *vq,
> -			const struct v4l2_format *fmt,
> +			const void *parg,
>  			unsigned int *count, unsigned int *num_planes,
>  			unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
>  	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>  	struct mx2_camera_dev *pcdev = ici->priv;
> diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
> index dcd7dc1..16ad897 100644
> --- a/drivers/media/platform/soc_camera/mx3_camera.c
> +++ b/drivers/media/platform/soc_camera/mx3_camera.c
> @@ -185,10 +185,11 @@ static void mx3_cam_dma_done(void *arg)
>   * Calculate the __buffer__ (not data) size and number of buffers.
>   */
>  static int mx3_videobuf_setup(struct vb2_queue *vq,
> -			const struct v4l2_format *fmt,
> +			const void *parg,
>  			unsigned int *count, unsigned int *num_planes,
>  			unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
>  	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>  	struct mx3_camera_dev *mx3_cam = ici->priv;
> diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
> index cd45fa9..b983361 100644
> --- a/drivers/media/platform/soc_camera/rcar_vin.c
> +++ b/drivers/media/platform/soc_camera/rcar_vin.c
> @@ -527,11 +527,12 @@ struct rcar_vin_cam {
>   * required
>   */
>  static int rcar_vin_videobuf_setup(struct vb2_queue *vq,
> -				   const struct v4l2_format *fmt,
> +				   const void *parg,
>  				   unsigned int *count,
>  				   unsigned int *num_planes,
>  				   unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
>  	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>  	struct rcar_vin_priv *priv = ici->priv;
> diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
> index 161b614..ac68c55 100644
> --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
> +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
> @@ -210,11 +210,13 @@ static int sh_mobile_ceu_soft_reset(struct sh_mobile_ceu_dev *pcdev)
>   *		  for the current frame format if required
>   */
>  static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
> -			const struct v4l2_format *fmt,
> +			const void *parg,
>  			unsigned int *count, unsigned int *num_planes,
>  			unsigned int sizes[], void *alloc_ctxs[])
>  {
> -	struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
> +	struct soc_camera_device *icd = container_of(vq,
> +			struct soc_camera_device, vb2_vidq);
>  	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
>  	struct sh_mobile_ceu_dev *pcdev = ici->priv;
>  
> diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
> index df61355..5bb3354 100644
> --- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
> +++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
> @@ -438,10 +438,11 @@ static void bdisp_ctrls_delete(struct bdisp_ctx *ctx)
>  }
>  
>  static int bdisp_queue_setup(struct vb2_queue *vq,
> -			     const struct v4l2_format *fmt,
> +			     const void *parg,
>  			     unsigned int *nb_buf, unsigned int *nb_planes,
>  			     unsigned int sizes[], void *allocators[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct bdisp_ctx *ctx = vb2_get_drv_priv(vq);
>  	struct bdisp_frame *frame = ctx_get_frame(ctx, vq->type);
>  
> diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
> index d82c2f2..22f820c 100644
> --- a/drivers/media/platform/ti-vpe/vpe.c
> +++ b/drivers/media/platform/ti-vpe/vpe.c
> @@ -1798,7 +1798,7 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = {
>   * Queue operations
>   */
>  static int vpe_queue_setup(struct vb2_queue *vq,
> -			   const struct v4l2_format *fmt,
> +			   const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
> index 295fde5..fad0ac9 100644
> --- a/drivers/media/platform/vim2m.c
> +++ b/drivers/media/platform/vim2m.c
> @@ -710,10 +710,11 @@ static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
>   */
>  
>  static int vim2m_queue_setup(struct vb2_queue *vq,
> -				const struct v4l2_format *fmt,
> +				const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct vim2m_ctx *ctx = vb2_get_drv_priv(vq);
>  	struct vim2m_q_data *q_data;
>  	unsigned int size, count = *nbuffers;
> diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
> index bae5b8a..a5ff809 100644
> --- a/drivers/media/platform/vivid/vivid-sdr-cap.c
> +++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
> @@ -210,7 +210,7 @@ static int vivid_thread_sdr_cap(void *data)
>  	return 0;
>  }
>  
> -static int sdr_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int sdr_cap_queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned *nbuffers, unsigned *nplanes,
>  		       unsigned sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
> index 73e9c0b..83aee19 100644
> --- a/drivers/media/platform/vivid/vivid-vbi-cap.c
> +++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
> @@ -135,7 +135,7 @@ void vivid_sliced_vbi_cap_process(struct vivid_dev *dev, struct vivid_buffer *bu
>  	buf->vb.timestamp.tv_sec += dev->time_wrap_offset;
>  }
>  
> -static int vbi_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int vbi_cap_queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned *nbuffers, unsigned *nplanes,
>  		       unsigned sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c
> index 1333f96..055cef6 100644
> --- a/drivers/media/platform/vivid/vivid-vbi-out.c
> +++ b/drivers/media/platform/vivid/vivid-vbi-out.c
> @@ -27,7 +27,7 @@
>  #include "vivid-vbi-out.h"
>  #include "vivid-vbi-cap.h"
>  
> -static int vbi_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int vbi_out_queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned *nbuffers, unsigned *nplanes,
>  		       unsigned sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
> index 4572709..79fc026 100644
> --- a/drivers/media/platform/vivid/vivid-vid-cap.c
> +++ b/drivers/media/platform/vivid/vivid-vid-cap.c
> @@ -95,10 +95,11 @@ static const struct v4l2_discrete_probe webcam_probe = {
>  	VIVID_WEBCAM_SIZES
>  };
>  
> -static int vid_cap_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int vid_cap_queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned *nbuffers, unsigned *nplanes,
>  		       unsigned sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct vivid_dev *dev = vb2_get_drv_priv(vq);
>  	unsigned buffers = tpg_g_buffers(&dev->tpg);
>  	unsigned h = dev->fmt_cap_rect.height;
> diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
> index 73c8f97..fe9a72d 100644
> --- a/drivers/media/platform/vivid/vivid-vid-out.c
> +++ b/drivers/media/platform/vivid/vivid-vid-out.c
> @@ -31,10 +31,11 @@
>  #include "vivid-kthread-out.h"
>  #include "vivid-vid-out.h"
>  
> -static int vid_out_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int vid_out_queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned *nbuffers, unsigned *nplanes,
>  		       unsigned sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct vivid_dev *dev = vb2_get_drv_priv(vq);
>  	const struct vivid_fmt *vfmt = dev->fmt_out;
>  	unsigned planes = vfmt->buffers;
> diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
> index 5837bc1..a1d8892 100644
> --- a/drivers/media/platform/vsp1/vsp1_video.c
> +++ b/drivers/media/platform/vsp1/vsp1_video.c
> @@ -787,10 +787,11 @@ void vsp1_pipelines_resume(struct vsp1_device *vsp1)
>   */
>  
>  static int
> -vsp1_video_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +vsp1_video_queue_setup(struct vb2_queue *vq, const void *parg,
>  		     unsigned int *nbuffers, unsigned int *nplanes,
>  		     unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct vsp1_video *video = vb2_get_drv_priv(vq);
>  	const struct v4l2_pix_format_mplane *format;
>  	struct v4l2_pix_format_mplane pix_mp;
> diff --git a/drivers/media/platform/xilinx/xilinx-dma.c b/drivers/media/platform/xilinx/xilinx-dma.c
> index 3b6112e..bd9c29b 100644
> --- a/drivers/media/platform/xilinx/xilinx-dma.c
> +++ b/drivers/media/platform/xilinx/xilinx-dma.c
> @@ -309,10 +309,11 @@ static void xvip_dma_complete(void *param)
>  }
>  
>  static int
> -xvip_dma_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +xvip_dma_queue_setup(struct vb2_queue *vq, const void *parg,
>  		     unsigned int *nbuffers, unsigned int *nplanes,
>  		     unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct xvip_dma *dma = vb2_get_drv_priv(vq);
>  
>  	/* Make sure the image size is large enough. */
> diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
> index bc45104..e346619 100644
> --- a/drivers/media/usb/airspy/airspy.c
> +++ b/drivers/media/usb/airspy/airspy.c
> @@ -486,7 +486,7 @@ static void airspy_disconnect(struct usb_interface *intf)
>  
>  /* Videobuf2 operations */
>  static int airspy_queue_setup(struct vb2_queue *vq,
> -		const struct v4l2_format *fmt, unsigned int *nbuffers,
> +		const void *parg, unsigned int *nbuffers,
>  		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
>  {
>  	struct airspy *s = vb2_get_drv_priv(vq);
> diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c
> index 44d1d46..d4ae272 100644
> --- a/drivers/media/usb/au0828/au0828-vbi.c
> +++ b/drivers/media/usb/au0828/au0828-vbi.c
> @@ -30,10 +30,11 @@
>  
>  /* ------------------------------------------------------------------ */
>  
> -static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int vbi_queue_setup(struct vb2_queue *vq, const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct au0828_dev *dev = vb2_get_drv_priv(vq);
>  	unsigned long img_size = dev->vbi_width * dev->vbi_height * 2;
>  	unsigned long size;
> diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
> index 065b9c8..6b6e772 100644
> --- a/drivers/media/usb/au0828/au0828-video.c
> +++ b/drivers/media/usb/au0828/au0828-video.c
> @@ -638,10 +638,11 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
>  	return rc;
>  }
>  
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned int *nbuffers, unsigned int *nplanes,
>  		       unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct au0828_dev *dev = vb2_get_drv_priv(vq);
>  	unsigned long img_size = dev->height * dev->bytesperline;
>  	unsigned long size;
> diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
> index a4d7f41..db76cf1 100644
> --- a/drivers/media/usb/em28xx/em28xx-vbi.c
> +++ b/drivers/media/usb/em28xx/em28xx-vbi.c
> @@ -31,10 +31,11 @@
>  
>  /* ------------------------------------------------------------------ */
>  
> -static int vbi_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int vbi_queue_setup(struct vb2_queue *vq, const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct em28xx *dev = vb2_get_drv_priv(vq);
>  	struct em28xx_v4l2 *v4l2 = dev->v4l2;
>  	unsigned long size;
> diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
> index 5b6fdd2..a7f034c 100644
> --- a/drivers/media/usb/em28xx/em28xx-video.c
> +++ b/drivers/media/usb/em28xx/em28xx-video.c
> @@ -871,10 +871,11 @@ static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type)
>  	Videobuf2 operations
>     ------------------------------------------------------------------*/
>  
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned int *nbuffers, unsigned int *nplanes,
>  		       unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct em28xx *dev = vb2_get_drv_priv(vq);
>  	struct em28xx_v4l2 *v4l2 = dev->v4l2;
>  	unsigned long size;
> diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
> index 63d87a2..f3d187d 100644
> --- a/drivers/media/usb/go7007/go7007-v4l2.c
> +++ b/drivers/media/usb/go7007/go7007-v4l2.c
> @@ -369,7 +369,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
>  }
>  
>  static int go7007_queue_setup(struct vb2_queue *q,
> -		const struct v4l2_format *fmt,
> +		const void *parg,
>  		unsigned int *num_buffers, unsigned int *num_planes,
>  		unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
> index e932f0b..458514d 100644
> --- a/drivers/media/usb/hackrf/hackrf.c
> +++ b/drivers/media/usb/hackrf/hackrf.c
> @@ -464,7 +464,7 @@ static void hackrf_disconnect(struct usb_interface *intf)
>  
>  /* Videobuf2 operations */
>  static int hackrf_queue_setup(struct vb2_queue *vq,
> -		const struct v4l2_format *fmt, unsigned int *nbuffers,
> +		const void *parg, unsigned int *nbuffers,
>  		unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
>  {
>  	struct hackrf_dev *dev = vb2_get_drv_priv(vq);
> diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c
> index 6ba87d0..9345a84 100644
> --- a/drivers/media/usb/msi2500/msi2500.c
> +++ b/drivers/media/usb/msi2500/msi2500.c
> @@ -614,7 +614,7 @@ static int msi2500_querycap(struct file *file, void *fh,
>  
>  /* Videobuf2 operations */
>  static int msi2500_queue_setup(struct vb2_queue *vq,
> -			       const struct v4l2_format *fmt,
> +			       const void *parg,
>  			       unsigned int *nbuffers,
>  			       unsigned int *nplanes, unsigned int sizes[],
>  			       void *alloc_ctxs[])
> diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
> index a33ce99..30d0957 100644
> --- a/drivers/media/usb/pwc/pwc-if.c
> +++ b/drivers/media/usb/pwc/pwc-if.c
> @@ -571,7 +571,7 @@ static void pwc_video_release(struct v4l2_device *v)
>  /***************************************************************************/
>  /* Videobuf2 operations */
>  
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
> index 32b5115..e7acb12 100644
> --- a/drivers/media/usb/s2255/s2255drv.c
> +++ b/drivers/media/usb/s2255/s2255drv.c
> @@ -660,7 +660,7 @@ static void s2255_fillbuff(struct s2255_vc *vc,
>     Videobuf operations
>     ------------------------------------------------------------------*/
>  
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  		       unsigned int *nbuffers, unsigned int *nplanes,
>  		       unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
> index 10e35e6..0bd34f1 100644
> --- a/drivers/media/usb/stk1160/stk1160-v4l.c
> +++ b/drivers/media/usb/stk1160/stk1160-v4l.c
> @@ -664,7 +664,7 @@ static const struct v4l2_ioctl_ops stk1160_ioctl_ops = {
>  /*
>   * Videobuf2 operations
>   */
> -static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt,
> +static int queue_setup(struct vb2_queue *vq, const void *parg,
>  				unsigned int *nbuffers, unsigned int *nplanes,
>  				unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
> index ce5d502..9116289 100644
> --- a/drivers/media/usb/usbtv/usbtv-video.c
> +++ b/drivers/media/usb/usbtv/usbtv-video.c
> @@ -599,9 +599,10 @@ static struct v4l2_file_operations usbtv_fops = {
>  };
>  
>  static int usbtv_queue_setup(struct vb2_queue *vq,
> -	const struct v4l2_format *fmt, unsigned int *nbuffers,
> +	const void *parg, unsigned int *nbuffers,
>  	unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct usbtv *usbtv = vb2_get_drv_priv(vq);
>  	unsigned size = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
>  
> diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
> index b49bcab..bccb2da 100644
> --- a/drivers/media/usb/uvc/uvc_queue.c
> +++ b/drivers/media/usb/uvc/uvc_queue.c
> @@ -69,10 +69,11 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue,
>   * videobuf2 queue operations
>   */
>  
> -static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> +	struct v4l2_format *fmt = (struct v4l2_format *)parg;
>  	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
>  	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
>  
> diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
> index 87048a1..c7de69b 100644
> --- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
> +++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
> @@ -1078,7 +1078,7 @@ vpfe_g_dv_timings(struct file *file, void *fh,
>   * the buffer nbuffers and buffer size
>   */
>  static int
> -vpfe_buffer_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +vpfe_buffer_queue_setup(struct vb2_queue *vq, const void *parg,
>  			unsigned int *nbuffers, unsigned int *nplanes,
>  			unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
> index 40405d8..1cb307a 100644
> --- a/drivers/staging/media/omap4iss/iss_video.c
> +++ b/drivers/staging/media/omap4iss/iss_video.c
> @@ -288,7 +288,7 @@ iss_video_check_format(struct iss_video *video, struct iss_video_fh *vfh)
>   */
>  
>  static int iss_video_queue_setup(struct vb2_queue *vq,
> -				 const struct v4l2_format *fmt,
> +				 const void *parg,
>  				 unsigned int *count, unsigned int *num_planes,
>  				 unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
> index 3628938..51d4a17 100644
> --- a/drivers/usb/gadget/function/uvc_queue.c
> +++ b/drivers/usb/gadget/function/uvc_queue.c
> @@ -41,7 +41,7 @@
>   * videobuf2 queue operations
>   */
>  
> -static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
> +static int uvc_queue_setup(struct vb2_queue *vq, const void *parg,
>  			   unsigned int *nbuffers, unsigned int *nplanes,
>  			   unsigned int sizes[], void *alloc_ctxs[])
>  {
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index 8787a6c..09d7529 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -312,7 +312,7 @@ struct vb2_buffer {
>   *			pre-queued buffers before calling STREAMON.
>   */
>  struct vb2_ops {
> -	int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
> +	int (*queue_setup)(struct vb2_queue *q, const void *parg,
>  			   unsigned int *num_buffers, unsigned int *num_planes,
>  			   unsigned int sizes[], void *alloc_ctxs[]);
>  

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts
  2015-08-26 11:59 ` [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts Junghak Sung
@ 2015-08-27 11:43   ` Mauro Carvalho Chehab
  2015-08-28  6:50     ` Junghak Sung
  2015-08-28 13:50   ` Hans Verkuil
  1 sibling, 1 reply; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2015-08-27 11:43 UTC (permalink / raw)
  To: Junghak Sung
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Em Wed, 26 Aug 2015 20:59:32 +0900
Junghak Sung <jh1009.sung@samsung.com> escreveu:

> Divide videobuf2-core into core part and v4l2-specific part
> - core part: videobuf2 core related with buffer management & memory
>  allocation
> - v4l2-specific part: v4l2-specific stuff

This patch is really hard to review, as the diff changes are too high to
be useful. I did a patch before this one doing a:
	cp drivers/media/v4l2-core/videobuf2-core.c drivers/media/v4l2-core/videobuf2-v4l2.c

still, to properly be able to review it, we'll need to compile and
do some tests, but, as patch 2 and 3 broke compilation, we can't do
it :(

So, I'll point for the things I found so far. I'll do a better review
on your next submission, after being able to compile all drivers, and
testing it with a few different devices to see how this works.

> 
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
> ---
>  drivers/media/v4l2-core/videobuf2-core.c     | 1933 +++-----------------------
>  drivers/media/v4l2-core/videobuf2-internal.h |  184 +++
>  drivers/media/v4l2-core/videobuf2-v4l2.c     | 1640 ++++++++++++++++++++++
>  include/media/videobuf2-core.h               |  157 +--
>  include/media/videobuf2-v4l2.h               |  116 ++
>  include/trace/events/v4l2.h                  |    4 +-
>  6 files changed, 2154 insertions(+), 1880 deletions(-)
>  create mode 100644 drivers/media/v4l2-core/videobuf2-internal.h
> 
> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> index 9266d50..2cd4241 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> @@ -6,9 +6,6 @@
>   * Author: Pawel Osciak <pawel@osciak.com>
>   *	   Marek Szyprowski <m.szyprowski@samsung.com>
>   *
> - * The vb2_thread implementation was based on code from videobuf-dvb.c:
> - *	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
> - *

Please keep the credits here. The entire videobuf stuff was actually
started with the first implementation done by Gerd.

>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License as published by
>   * the Free Software Foundation.
> @@ -24,164 +21,14 @@
>  #include <linux/freezer.h>
>  #include <linux/kthread.h>
>  
> -#include <media/v4l2-dev.h>
> -#include <media/v4l2-fh.h>
> -#include <media/v4l2-event.h>
> -#include <media/v4l2-common.h>
> -#include <media/videobuf2-v4l2.h>
> +#include <media/videobuf2-core.h>
> +#include "videobuf2-internal.h"
>  
>  #include <trace/events/v4l2.h>
>  
> -static int debug;
> -module_param(debug, int, 0644);
> -
> -#define dprintk(level, fmt, arg...)					\
> -	do {								\
> -		if (debug >= level)					\
> -			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
> -	} while (0)
> -
> -#ifdef CONFIG_VIDEO_ADV_DEBUG
> -
> -/*
> - * If advanced debugging is on, then count how often each op is called
> - * successfully, which can either be per-buffer or per-queue.
> - *
> - * This makes it easy to check that the 'init' and 'cleanup'
> - * (and variations thereof) stay balanced.
> - */
> -
> -#define log_memop(vb, op)						\
> -	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
> -		(vb)->vb2_queue, (vb)->index, #op,			\
> -		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
> -
> -#define call_memop(vb, op, args...)					\
> -({									\
> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
> -	int err;							\
> -									\
> -	log_memop(vb, op);						\
> -	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
> -	if (!err)							\
> -		(vb)->cnt_mem_ ## op++;					\
> -	err;								\
> -})
> -
> -#define call_ptr_memop(vb, op, args...)					\
> -({									\
> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
> -	void *ptr;							\
> -									\
> -	log_memop(vb, op);						\
> -	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
> -	if (!IS_ERR_OR_NULL(ptr))					\
> -		(vb)->cnt_mem_ ## op++;					\
> -	ptr;								\
> -})
> -
> -#define call_void_memop(vb, op, args...)				\
> -({									\
> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
> -									\
> -	log_memop(vb, op);						\
> -	if (_q->mem_ops->op)						\
> -		_q->mem_ops->op(args);					\
> -	(vb)->cnt_mem_ ## op++;						\
> -})
> -
> -#define log_qop(q, op)							\
> -	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
> -		(q)->ops->op ? "" : " (nop)")
> -
> -#define call_qop(q, op, args...)					\
> -({									\
> -	int err;							\
> -									\
> -	log_qop(q, op);							\
> -	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
> -	if (!err)							\
> -		(q)->cnt_ ## op++;					\
> -	err;								\
> -})
> -
> -#define call_void_qop(q, op, args...)					\
> -({									\
> -	log_qop(q, op);							\
> -	if ((q)->ops->op)						\
> -		(q)->ops->op(args);					\
> -	(q)->cnt_ ## op++;						\
> -})
> -
> -#define log_vb_qop(vb, op, args...)					\
> -	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
> -		(vb)->vb2_queue, (vb)->index, #op,			\
> -		(vb)->vb2_queue->ops->op ? "" : " (nop)")
> -
> -#define call_vb_qop(vb, op, args...)					\
> -({									\
> -	int err;							\
> -									\
> -	log_vb_qop(vb, op);						\
> -	err = (vb)->vb2_queue->ops->op ?				\
> -		(vb)->vb2_queue->ops->op(args) : 0;			\
> -	if (!err)							\
> -		(vb)->cnt_ ## op++;					\
> -	err;								\
> -})
> -
> -#define call_void_vb_qop(vb, op, args...)				\
> -({									\
> -	log_vb_qop(vb, op);						\
> -	if ((vb)->vb2_queue->ops->op)					\
> -		(vb)->vb2_queue->ops->op(args);				\
> -	(vb)->cnt_ ## op++;						\
> -})
> -
> -#else
> -
> -#define call_memop(vb, op, args...)					\
> -	((vb)->vb2_queue->mem_ops->op ?					\
> -		(vb)->vb2_queue->mem_ops->op(args) : 0)
> -
> -#define call_ptr_memop(vb, op, args...)					\
> -	((vb)->vb2_queue->mem_ops->op ?					\
> -		(vb)->vb2_queue->mem_ops->op(args) : NULL)
> -
> -#define call_void_memop(vb, op, args...)				\
> -	do {								\
> -		if ((vb)->vb2_queue->mem_ops->op)			\
> -			(vb)->vb2_queue->mem_ops->op(args);		\
> -	} while (0)
> -
> -#define call_qop(q, op, args...)					\
> -	((q)->ops->op ? (q)->ops->op(args) : 0)
> -
> -#define call_void_qop(q, op, args...)					\
> -	do {								\
> -		if ((q)->ops->op)					\
> -			(q)->ops->op(args);				\
> -	} while (0)
> -
> -#define call_vb_qop(vb, op, args...)					\
> -	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
> -
> -#define call_void_vb_qop(vb, op, args...)				\
> -	do {								\
> -		if ((vb)->vb2_queue->ops->op)				\
> -			(vb)->vb2_queue->ops->op(args);			\
> -	} while (0)
> -
> -#endif
> -
> -/* Flags that are set by the vb2 core */
> -#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
> -				 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
> -				 V4L2_BUF_FLAG_PREPARED | \
> -				 V4L2_BUF_FLAG_TIMESTAMP_MASK)
> -/* Output buffer flags that should be passed on to the driver */
> -#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
> -				 V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
> +int vb2_debug;
> +module_param_named(debug, vb2_debug, int, 0644);
> +EXPORT_SYMBOL_GPL(vb2_debug);
>  
>  static void __vb2_queue_cancel(struct vb2_queue *q);
>  static void __enqueue_in_driver(struct vb2_buffer *vb);
> @@ -193,7 +40,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
>  {
>  	struct vb2_queue *q = vb->vb2_queue;
>  	enum dma_data_direction dma_dir =
> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> +			q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>  	void *mem_priv;
>  	int plane;
>  
> @@ -249,7 +96,8 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
>  
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		if (vb->planes[plane].mem_priv)
> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
> +			call_void_memop(vb, put_userptr,
> +					vb->planes[plane].mem_priv);
>  		vb->planes[plane].mem_priv = NULL;
>  	}
>  }
> @@ -347,7 +195,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>   *
>   * Returns the number of buffers successfully allocated.
>   */
> -static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
> +static int __vb2_queue_alloc(struct vb2_queue *q, unsigned int memory,
>  			unsigned int num_buffers, unsigned int num_planes)
>  {
>  	unsigned int buffer;
> @@ -370,7 +218,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>  		vb->memory = memory;
>  
>  		/* Allocate video buffer memory for the MMAP type */
> -		if (memory == V4L2_MEMORY_MMAP) {
> +		if (memory == VB2_MEMORY_MMAP) {

Ok, that answers my implicit question on patch 2/5: you're actually
defining a new enum for VB2.

The right thing to do is to replace the 
	unsigned int			memory;  

at struct vb2_queue by the right type, in order to enforce the type.
The vb2_buffer comment then needs to be changed, as it currently
references the types defined at videodev2.h.

>  			ret = __vb2_buf_mem_alloc(vb);
>  			if (ret) {
>  				dprintk(1, "failed allocating memory for "
> @@ -397,7 +245,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>  	}
>  
>  	__setup_lengths(q, buffer);
> -	if (memory == V4L2_MEMORY_MMAP)
> +	if (memory == VB2_MEMORY_MMAP)
>  		__setup_offsets(q, buffer);
>  
>  	dprintk(1, "allocated %d buffers, %d plane(s) each\n",
> @@ -421,9 +269,9 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>  			continue;
>  
>  		/* Free MMAP buffers or release USERPTR buffers */
> -		if (q->memory == V4L2_MEMORY_MMAP)
> +		if (q->memory == VB2_MEMORY_MMAP)
>  			__vb2_buf_mem_free(vb);
> -		else if (q->memory == V4L2_MEMORY_DMABUF)
> +		else if (q->memory == VB2_MEMORY_DMABUF)
>  			__vb2_buf_dmabuf_put(vb);
>  		else
>  			__vb2_buf_userptr_put(vb);
> @@ -547,75 +395,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  }
>  
>  /**
> - * __verify_planes_array() - verify that the planes array passed in struct
> - * v4l2_buffer from userspace can be safely used
> - */
> -static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> -{
> -	if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
> -		return 0;
> -
> -	/* Is memory for copying plane information present? */
> -	if (NULL == b->m.planes) {
> -		dprintk(1, "multi-planar buffer passed but "
> -			   "planes array not provided\n");
> -		return -EINVAL;
> -	}
> -
> -	if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
> -		dprintk(1, "incorrect planes array length, "
> -			   "expected %d, got %d\n", vb->num_planes, b->length);
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -/**
> - * __verify_length() - Verify that the bytesused value for each plane fits in
> - * the plane length and that the data offset doesn't exceed the bytesused value.
> - */
> -static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> -{
> -	unsigned int length;
> -	unsigned int bytesused;
> -	unsigned int plane;
> -
> -	if (!V4L2_TYPE_IS_OUTPUT(b->type))
> -		return 0;
> -
> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> -		for (plane = 0; plane < vb->num_planes; ++plane) {
> -			length = (b->memory == V4L2_MEMORY_USERPTR ||
> -				b->memory == V4L2_MEMORY_DMABUF)
> -				? b->m.planes[plane].length
> -				: vb->planes[plane].length;
> -			bytesused = b->m.planes[plane].bytesused
> -				? b->m.planes[plane].bytesused : length;
> -
> -			if (b->m.planes[plane].bytesused > length)
> -				return -EINVAL;
> -
> -			if (b->m.planes[plane].data_offset > 0 &&
> -				b->m.planes[plane].data_offset >= bytesused)
> -				return -EINVAL;
> -		}
> -	} else {
> -		length = (b->memory == V4L2_MEMORY_USERPTR)
> -			? b->length : vb->planes[0].length;
> -
> -		if (b->bytesused > length)
> -			return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -/**
> - * __buffer_in_use() - return true if the buffer is in use and
> + * vb2_buffer_in_use() - return true if the buffer is in use and
>   * the queue cannot be freed (by the means of REQBUFS(0)) call
>   */
> -static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>  {
>  	unsigned int plane;
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
> @@ -631,6 +414,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>  	}
>  	return false;
>  }
> +EXPORT_SYMBOL_GPL(vb2_buffer_in_use);
>  
>  /**
>   * __buffers_in_use() - return true if any buffers on the queue are in use and
> @@ -640,142 +424,26 @@ static bool __buffers_in_use(struct vb2_queue *q)
>  {
>  	unsigned int buffer;
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		if (__buffer_in_use(q, q->bufs[buffer]))
> +		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>  			return true;
>  	}
>  	return false;
>  }
>  
>  /**
> - * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
> - * returned to userspace
> - */
> -static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
> -{
> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> -	struct vb2_queue *q = vb->vb2_queue;
> -	unsigned int plane;
> -
> -	/* Copy back data such as timestamp, flags, etc. */
> -	b->index = vb->index;
> -	b->type = vb->type;
> -	b->memory = vb->memory;
> -	b->bytesused = 0;
> -
> -	b->flags = vbuf->flags;
> -	b->field = vbuf->field;
> -	b->timestamp = vbuf->timestamp;
> -	b->timecode = vbuf->timecode;
> -	b->sequence = vbuf->sequence;
> -
> -	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
> -		/*
> -		 * Fill in plane-related data if userspace provided an array
> -		 * for it. The caller has already verified memory and size.
> -		 */
> -		b->length = vb->num_planes;
> -		for (plane = 0; plane < vb->num_planes; ++plane) {
> -			struct v4l2_plane *pdst = &b->m.planes[plane];
> -			struct vb2_plane *psrc = &vb->planes[plane];
> -
> -			pdst->bytesused = psrc->bytesused;
> -			pdst->length = psrc->length;
> -			if (q->memory == V4L2_MEMORY_MMAP)
> -				pdst->m.mem_offset = psrc->m.offset;
> -			else if (q->memory == V4L2_MEMORY_USERPTR)
> -				pdst->m.userptr = psrc->m.userptr;
> -			else if (q->memory == V4L2_MEMORY_DMABUF)
> -				pdst->m.fd = psrc->m.fd;
> -			pdst->data_offset = psrc->data_offset;
> -		}
> -	} else {
> -		/*
> -		 * We use length and offset in v4l2_planes array even for
> -		 * single-planar buffers, but userspace does not.
> -		 */
> -		b->length = vb->planes[0].length;
> -		b->bytesused = vb->planes[0].bytesused;
> -		if (q->memory == V4L2_MEMORY_MMAP)
> -			b->m.offset = vb->planes[0].m.offset;
> -		else if (q->memory == V4L2_MEMORY_USERPTR)
> -			b->m.userptr = vb->planes[0].m.userptr;
> -		else if (q->memory == V4L2_MEMORY_DMABUF)
> -			b->m.fd = vb->planes[0].m.fd;
> -	}
> -
> -	/*
> -	 * Clear any buffer state related flags.
> -	 */
> -	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
> -	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
> -	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> -			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> -		/*
> -		 * For non-COPY timestamps, drop timestamp source bits
> -		 * and obtain the timestamp source from the queue.
> -		 */
> -		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> -		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> -	}
> -
> -	switch (vb->state) {
> -	case VB2_BUF_STATE_QUEUED:
> -	case VB2_BUF_STATE_ACTIVE:
> -		b->flags |= V4L2_BUF_FLAG_QUEUED;
> -		break;
> -	case VB2_BUF_STATE_ERROR:
> -		b->flags |= V4L2_BUF_FLAG_ERROR;
> -		/* fall through */
> -	case VB2_BUF_STATE_DONE:
> -		b->flags |= V4L2_BUF_FLAG_DONE;
> -		break;
> -	case VB2_BUF_STATE_PREPARED:
> -		b->flags |= V4L2_BUF_FLAG_PREPARED;
> -		break;
> -	case VB2_BUF_STATE_PREPARING:
> -	case VB2_BUF_STATE_DEQUEUED:
> -		/* nothing */
> -		break;
> -	}
> -
> -	if (__buffer_in_use(q, vb))
> -		b->flags |= V4L2_BUF_FLAG_MAPPED;
> -}
> -
> -/**
> - * vb2_querybuf() - query video buffer information
> + * vb2_core_querybuf() - query video buffer information
>   * @q:		videobuf queue
> + * @index:	id number of the buffer
>   * @b:		buffer struct passed from userspace to vidioc_querybuf handler
>   *		in driver
> - *
> - * Should be called from vidioc_querybuf ioctl handler in driver.
> - * This function will verify the passed v4l2_buffer structure and fill the
> - * relevant information for the userspace.
> - *
> - * The return values from this function are intended to be directly returned
> - * from vidioc_querybuf handler in driver.
>   */
> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>  {
> -	struct vb2_buffer *vb;
> -	int ret;
> -
> -	if (b->type != q->type) {
> -		dprintk(1, "wrong buffer type\n");
> -		return -EINVAL;
> -	}
> +	call_bufop(q, fill_user_buffer, q->bufs[index], pb);
>  
> -	if (b->index >= q->num_buffers) {
> -		dprintk(1, "buffer index out of range\n");
> -		return -EINVAL;
> -	}
> -	vb = q->bufs[b->index];
> -	ret = __verify_planes_array(vb, b);
> -	if (!ret)
> -		__fill_v4l2_buffer(vb, b);
> -	return ret;
> +	return 0;
>  }
> -EXPORT_SYMBOL(vb2_querybuf);
> +EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>  
>  /**
>   * __verify_userptr_ops() - verify that all memory operations required for
> @@ -818,14 +486,14 @@ static int __verify_dmabuf_ops(struct vb2_queue *q)
>  }
>  
>  /**
> - * __verify_memory_type() - Check whether the memory type and buffer type
> + * vb2_verify_memory_type() - Check whether the memory type and buffer type
>   * passed to a buffer operation are compatible with the queue.
>   */
> -static int __verify_memory_type(struct vb2_queue *q,
> -		enum v4l2_memory memory, enum v4l2_buf_type type)
> +int vb2_verify_memory_type(struct vb2_queue *q,
> +		unsigned int memory, unsigned int type)
>  {
> -	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
> -			memory != V4L2_MEMORY_DMABUF) {
> +	if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
> +		memory != VB2_MEMORY_DMABUF) {
>  		dprintk(1, "unsupported memory type\n");
>  		return -EINVAL;
>  	}
> @@ -839,37 +507,30 @@ static int __verify_memory_type(struct vb2_queue *q,
>  	 * Make sure all the required memory ops for given memory type
>  	 * are available.
>  	 */
> -	if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
> +	if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
>  		dprintk(1, "MMAP for current setup unsupported\n");
>  		return -EINVAL;
>  	}
>  
> -	if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
> +	if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
>  		dprintk(1, "USERPTR for current setup unsupported\n");
>  		return -EINVAL;
>  	}
>  
> -	if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
> +	if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
>  		dprintk(1, "DMABUF for current setup unsupported\n");
>  		return -EINVAL;
>  	}
>  
> -	/*
> -	 * Place the busy tests at the end: -EBUSY can be ignored when
> -	 * create_bufs is called with count == 0, but count == 0 should still
> -	 * do the memory and type validation.
> -	 */
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(vb2_verify_memory_type);
>  
>  /**
> - * __reqbufs() - Initiate streaming
> + * vb2_core_reqbufs() - Initiate streaming
>   * @q:		videobuf2 queue
> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
> + * @memory:
> + * @count:
>   *
>   * Should be called from vidioc_reqbufs ioctl handler of a driver.
>   * This function:
> @@ -889,7 +550,8 @@ static int __verify_memory_type(struct vb2_queue *q,
>   * The return values from this function are intended to be directly returned
>   * from vidioc_reqbufs handler in driver.
>   */
> -static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
> +		unsigned int *count)
>  {
>  	unsigned int num_buffers, allocated_buffers, num_planes = 0;
>  	int ret;
> @@ -899,13 +561,13 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  		return -EBUSY;
>  	}
>  
> -	if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
> +	if (*count == 0 || q->num_buffers != 0 || q->memory != memory) {
>  		/*
>  		 * We already have buffers allocated, so first check if they
>  		 * are not in use and can be freed.
>  		 */
>  		mutex_lock(&q->mmap_lock);
> -		if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) {
> +		if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
>  			mutex_unlock(&q->mmap_lock);
>  			dprintk(1, "memory in use, cannot free\n");
>  			return -EBUSY;
> @@ -926,18 +588,18 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  		 * In case of REQBUFS(0) return immediately without calling
>  		 * driver's queue_setup() callback and allocating resources.
>  		 */
> -		if (req->count == 0)
> +		if (*count == 0)
>  			return 0;
>  	}
>  
>  	/*
>  	 * Make sure the requested values and current defaults are sane.
>  	 */
> -	num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
> +	num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME);
>  	num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed);
>  	memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
>  	memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
> -	q->memory = req->memory;
> +	q->memory = memory;
>  
>  	/*
>  	 * Ask the driver how many buffers and planes per buffer it requires.
> @@ -949,7 +611,8 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  		return ret;
>  
>  	/* Finally, allocate buffers and video memory */
> -	allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
> +	allocated_buffers =
> +		__vb2_queue_alloc(q, memory, num_buffers, num_planes);
>  	if (allocated_buffers == 0) {
>  		dprintk(1, "memory allocation failed\n");
>  		return -ENOMEM;
> @@ -998,28 +661,15 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  	 * Return the number of successfully allocated buffers
>  	 * to the userspace.
>  	 */
> -	req->count = allocated_buffers;
> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
> +	*count = allocated_buffers;
> +	q->waiting_for_buffers = !q->is_output;
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
>  
>  /**
> - * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and
> - * type values.
> - * @q:		videobuf2 queue
> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
> - */
> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> -{
> -	int ret = __verify_memory_type(q, req->memory, req->type);
> -
> -	return ret ? ret : __reqbufs(q, req);
> -}
> -EXPORT_SYMBOL_GPL(vb2_reqbufs);
> -
> -/**
> - * __create_bufs() - Allocate buffers and any required auxiliary structs
> + * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs
>   * @q:		videobuf2 queue
>   * @create:	creation parameters, passed from userspace to vidioc_create_bufs
>   *		handler in driver
> @@ -1033,12 +683,13 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs);
>   * The return values from this function are intended to be directly returned
>   * from vidioc_create_bufs handler in driver.
>   */
> -static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
> +		unsigned int *count, void *parg)
>  {
>  	unsigned int num_planes = 0, num_buffers, allocated_buffers;
>  	int ret;
>  
> -	if (q->num_buffers == VIDEO_MAX_FRAME) {
> +	if (q->num_buffers == VB2_MAX_FRAME) {
>  		dprintk(1, "maximum number of buffers already allocated\n");
>  		return -ENOBUFS;
>  	}
> @@ -1046,23 +697,23 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  	if (!q->num_buffers) {
>  		memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
>  		memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
> -		q->memory = create->memory;
> -		q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
> +		q->memory = memory;
> +		q->waiting_for_buffers = !q->is_output;
>  	}
>  
> -	num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
> +	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
>  
>  	/*
>  	 * Ask the driver, whether the requested number of buffers, planes per
>  	 * buffer and their sizes are acceptable
>  	 */
> -	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> +	ret = call_qop(q, queue_setup, q, parg, &num_buffers,
>  			&num_planes, q->plane_sizes, q->alloc_ctx);
>  	if (ret)
>  		return ret;
>  
>  	/* Finally, allocate buffers and video memory */
> -	allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers,
> +	allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
>  				num_planes);
>  	if (allocated_buffers == 0) {
>  		dprintk(1, "memory allocation failed\n");
> @@ -1079,7 +730,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  		 * q->num_buffers contains the total number of buffers, that the
>  		 * queue driver has set up
>  		 */
> -		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> +		ret = call_qop(q, queue_setup, q, parg, &num_buffers,
>  				&num_planes, q->plane_sizes, q->alloc_ctx);
>  
>  		if (!ret && allocated_buffers < num_buffers)
> @@ -1109,28 +760,11 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  	 * Return the number of successfully allocated buffers
>  	 * to the userspace.
>  	 */
> -	create->count = allocated_buffers;
> +	*count = allocated_buffers;
>  
>  	return 0;
>  }
> -
> -/**
> - * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the
> - * memory and type values.
> - * @q:		videobuf2 queue
> - * @create:	creation parameters, passed from userspace to vidioc_create_bufs
> - *		handler in driver
> - */
> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
> -{
> -	int ret = __verify_memory_type(q, create->memory, create->format.type);
> -
> -	create->index = q->num_buffers;
> -	if (create->count == 0)
> -		return ret != -EBUSY ? ret : 0;
> -	return ret ? ret : __create_bufs(q, create);
> -}
> -EXPORT_SYMBOL_GPL(vb2_create_bufs);
> +EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
>  
>  /**
>   * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
> @@ -1263,7 +897,7 @@ void vb2_discard_done(struct vb2_queue *q)
>  }
>  EXPORT_SYMBOL_GPL(vb2_discard_done);
>  
> -static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>  {
>  	static bool __check_once __read_mostly;
>  
> @@ -1279,162 +913,34 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>  	else
>  		pr_warn_once("use the actual size instead.\n");
>  }
> -
> -/**
> - * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
> - * v4l2_buffer by the userspace. The caller has already verified that struct
> - * v4l2_buffer has a valid number of planes.
> - */
> -static void __fill_vb2_buffer(struct vb2_buffer *vb,
> -		const struct v4l2_buffer *b, struct vb2_plane *planes)
> -{
> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> -	unsigned int plane;
> -
> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> -		if (b->memory == V4L2_MEMORY_USERPTR) {
> -			for (plane = 0; plane < vb->num_planes; ++plane) {
> -				planes[plane].m.userptr =
> -					b->m.planes[plane].m.userptr;
> -				planes[plane].length =
> -					b->m.planes[plane].length;
> -			}
> -		}
> -		if (b->memory == V4L2_MEMORY_DMABUF) {
> -			for (plane = 0; plane < vb->num_planes; ++plane) {
> -				planes[plane].m.fd =
> -					b->m.planes[plane].m.fd;
> -				planes[plane].length =
> -					b->m.planes[plane].length;
> -			}
> -		}
> -
> -		/* Fill in driver-provided information for OUTPUT types */
> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> -			/*
> -			 * Will have to go up to b->length when API starts
> -			 * accepting variable number of planes.
> -			 *
> -			 * If bytesused == 0 for the output buffer, then fall
> -			 * back to the full buffer size. In that case
> -			 * userspace clearly never bothered to set it and
> -			 * it's a safe assumption that they really meant to
> -			 * use the full plane sizes.
> -			 *
> -			 * Some drivers, e.g. old codec drivers, use bytesused == 0
> -			 * as a way to indicate that streaming is finished.
> -			 * In that case, the driver should use the
> -			 * allow_zero_bytesused flag to keep old userspace
> -			 * applications working.
> -			 */
> -			for (plane = 0; plane < vb->num_planes; ++plane) {
> -				struct vb2_plane *pdst = &planes[plane];
> -				struct v4l2_plane *psrc = &b->m.planes[plane];
> -
> -				if (psrc->bytesused == 0)
> -					vb2_warn_zero_bytesused(vb);
> -
> -				if (vb->vb2_queue->allow_zero_bytesused)
> -					pdst->bytesused = psrc->bytesused;
> -				else
> -					pdst->bytesused = psrc->bytesused ?
> -						psrc->bytesused : pdst->length;
> -				pdst->data_offset = psrc->data_offset;
> -			}
> -		}
> -	} else {
> -		/*
> -		 * Single-planar buffers do not use planes array,
> -		 * so fill in relevant v4l2_buffer struct fields instead.
> -		 * In videobuf we use our internal V4l2_planes struct for
> -		 * single-planar buffers as well, for simplicity.
> -		 *
> -		 * If bytesused == 0 for the output buffer, then fall back
> -		 * to the full buffer size as that's a sensible default.
> -		 *
> -		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
> -		 * a way to indicate that streaming is finished. In that case,
> -		 * the driver should use the allow_zero_bytesused flag to keep
> -		 * old userspace applications working.
> -		 */
> -		if (b->memory == V4L2_MEMORY_USERPTR) {
> -			planes[0].m.userptr = b->m.userptr;
> -			planes[0].length = b->length;
> -		}
> -
> -		if (b->memory == V4L2_MEMORY_DMABUF) {
> -			planes[0].m.fd = b->m.fd;
> -			planes[0].length = b->length;
> -		}
> -
> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> -			if (b->bytesused == 0)
> -				vb2_warn_zero_bytesused(vb);
> -
> -			if (vb->vb2_queue->allow_zero_bytesused)
> -				planes[0].bytesused = b->bytesused;
> -			else
> -				planes[0].bytesused = b->bytesused ?
> -					b->bytesused : planes[0].length;
> -		} else
> -			planes[0].bytesused = 0;
> -
> -	}
> -
> -	/* Zero flags that the vb2 core handles */
> -	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> -	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> -			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
> -			!V4L2_TYPE_IS_OUTPUT(b->type)) {
> -		/*
> -		 * Non-COPY timestamps and non-OUTPUT queues will get
> -		 * their timestamp and timestamp source flags from the
> -		 * queue.
> -		 */
> -		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> -	}
> -
> -	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> -		/*
> -		 * For output buffers mask out the timecode flag:
> -		 * this will be handled later in vb2_internal_qbuf().
> -		 * The 'field' is valid metadata for this output buffer
> -		 * and so that needs to be copied here.
> -		 */
> -		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
> -		vbuf->field = b->field;
> -	} else {
> -		/* Zero any output buffer flags as this is a capture buffer */
> -		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
> -	}
> -}
> +EXPORT_SYMBOL_GPL(vb2_warn_zero_bytesused);
>  
>  /**
>   * __qbuf_mmap() - handle qbuf of an MMAP buffer
>   */
> -static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +static int __qbuf_mmap(struct vb2_buffer *vb, void *pb)
>  {
> -	__fill_vb2_buffer(vb, b, vb->planes);
> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, vb->planes);
>  	return call_vb_qop(vb, buf_prepare, vb);
>  }
>  
>  /**
>   * __qbuf_userptr() - handle qbuf of a USERPTR buffer
>   */
> -static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +static int __qbuf_userptr(struct vb2_buffer *vb, void *pb)
>  {
> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
> +	struct vb2_plane planes[VB2_MAX_PLANES];
>  	struct vb2_queue *q = vb->vb2_queue;
>  	void *mem_priv;
>  	unsigned int plane;
>  	int ret;
>  	enum dma_data_direction dma_dir =
> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>  	bool reacquired = vb->planes[0].mem_priv == NULL;
>  
>  	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
>  	/* Copy relevant information provided by the userspace */
> -	__fill_vb2_buffer(vb, b, planes);
> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
>  
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		/* Skip the plane if already verified */
> @@ -1462,7 +968,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  				reacquired = true;
>  				call_void_vb_qop(vb, buf_cleanup, vb);
>  			}
> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
> +			call_void_memop(vb, put_userptr,
> +					vb->planes[plane].mem_priv);
>  		}
>  
>  		vb->planes[plane].mem_priv = NULL;
> @@ -1533,20 +1040,20 @@ err:
>  /**
>   * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
>   */
> -static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +static int __qbuf_dmabuf(struct vb2_buffer *vb, void *pb)
>  {
> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
> +	struct vb2_plane planes[VB2_MAX_PLANES];
>  	struct vb2_queue *q = vb->vb2_queue;
>  	void *mem_priv;
>  	unsigned int plane;
>  	int ret;
>  	enum dma_data_direction dma_dir =
> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>  	bool reacquired = vb->planes[0].mem_priv == NULL;
>  
>  	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
>  	/* Copy relevant information provided by the userspace */
> -	__fill_vb2_buffer(vb, b, planes);
> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
>  
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
> @@ -1591,9 +1098,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  		vb->planes[plane].data_offset = 0;
>  
>  		/* Acquire each plane's memory */
> -		mem_priv = call_ptr_memop(vb, attach_dmabuf,
> -			q->alloc_ctx[plane], dbuf, planes[plane].length,
> -			dma_dir);
> +		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
> +			dbuf, planes[plane].length, dma_dir);
>  		if (IS_ERR(mem_priv)) {
>  			dprintk(1, "failed to attach dmabuf\n");
>  			ret = PTR_ERR(mem_priv);
> @@ -1626,7 +1132,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		vb->planes[plane].bytesused = planes[plane].bytesused;
>  		vb->planes[plane].length = planes[plane].length;
> -		vb->planes[plane].m.fd = planes[plane].m.userptr;
> +		vb->planes[plane].m.fd = planes[plane].m.fd;
>  		vb->planes[plane].data_offset = planes[plane].data_offset;
>  	}
>  
> @@ -1677,52 +1183,27 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
>  	call_void_vb_qop(vb, buf_queue, vb);
>  }
>  
> -static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +static int __buf_prepare(struct vb2_buffer *vb, void *pb)
>  {
> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>  	struct vb2_queue *q = vb->vb2_queue;
>  	int ret;
>  
> -	ret = __verify_length(vb, b);
> -	if (ret < 0) {
> -		dprintk(1, "plane parameters verification failed: %d\n", ret);
> -		return ret;
> -	}
> -	if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) {
> -		/*
> -		 * If the format's field is ALTERNATE, then the buffer's field
> -		 * should be either TOP or BOTTOM, not ALTERNATE since that
> -		 * makes no sense. The driver has to know whether the
> -		 * buffer represents a top or a bottom field in order to
> -		 * program any DMA correctly. Using ALTERNATE is wrong, since
> -		 * that just says that it is either a top or a bottom field,
> -		 * but not which of the two it is.
> -		 */
> -		dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
> -		return -EINVAL;
> -	}
> -
>  	if (q->error) {
>  		dprintk(1, "fatal error occurred on queue\n");
>  		return -EIO;
>  	}
>  
> -	vb->state = VB2_BUF_STATE_PREPARING;
> -	vbuf->timestamp.tv_sec = 0;
> -	vbuf->timestamp.tv_usec = 0;
> -	vbuf->sequence = 0;
> -
>  	switch (q->memory) {
> -	case V4L2_MEMORY_MMAP:
> -		ret = __qbuf_mmap(vb, b);
> +	case VB2_MEMORY_MMAP:
> +		ret = __qbuf_mmap(vb, pb);
>  		break;
> -	case V4L2_MEMORY_USERPTR:
> +	case VB2_MEMORY_USERPTR:
>  		down_read(&current->mm->mmap_sem);
> -		ret = __qbuf_userptr(vb, b);
> +		ret = __qbuf_userptr(vb, pb);
>  		up_read(&current->mm->mmap_sem);
>  		break;
> -	case V4L2_MEMORY_DMABUF:
> -		ret = __qbuf_dmabuf(vb, b);
> +	case VB2_MEMORY_DMABUF:
> +		ret = __qbuf_dmabuf(vb, pb);
>  		break;
>  	default:
>  		WARN(1, "Invalid queue type\n");
> @@ -1736,35 +1217,56 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  	return ret;
>  }
>  
> -static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
> -					const char *opname)
> +int vb2_verify_buffer(struct vb2_queue *q,
> +			unsigned int memory, unsigned int type,
> +			unsigned int index, unsigned int nplanes,
> +			void *pplane, const char *opname)
>  {
> -	if (b->type != q->type) {
> +	if (type != q->type) {
>  		dprintk(1, "%s: invalid buffer type\n", opname);
>  		return -EINVAL;
>  	}
>  
> -	if (b->index >= q->num_buffers) {
> +	if (index >= q->num_buffers) {
>  		dprintk(1, "%s: buffer index out of range\n", opname);
>  		return -EINVAL;
>  	}
>  
> -	if (q->bufs[b->index] == NULL) {
> +	if (q->bufs[index] == NULL) {
>  		/* Should never happen */
>  		dprintk(1, "%s: buffer is NULL\n", opname);
>  		return -EINVAL;
>  	}
>  
> -	if (b->memory != q->memory) {
> +	if (memory != VB2_MEMORY_UNKNOWN && memory != q->memory) {
>  		dprintk(1, "%s: invalid memory type\n", opname);
>  		return -EINVAL;
>  	}
>  
> -	return __verify_planes_array(q->bufs[b->index], b);
> +	if (q->is_multiplanar) {
> +		struct vb2_buffer *vb = q->bufs[index];
> +
> +		/* Is memory for copying plane information present? */
> +		if (NULL == pplane) {
> +			dprintk(1, "%s: multi-planar buffer passed but "
> +				"planes array not provided\n", opname);
> +			return -EINVAL;
> +		}
> +
> +		if (nplanes < vb->num_planes || nplanes > VB2_MAX_PLANES) {
> +			dprintk(1, "%s: incorrect planes array length, "
> +				"expected %d, got %d\n",
> +				opname, vb->num_planes, nplanes);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
>  }
> +EXPORT_SYMBOL_GPL(vb2_verify_buffer);
>  
>  /**
> - * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
> + * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
>   * @q:		videobuf2 queue
>   * @b:		buffer structure passed from userspace to vidioc_prepare_buf
>   *		handler in driver
> @@ -1778,37 +1280,28 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
>   * The return values from this function are intended to be directly returned
>   * from vidioc_prepare_buf handler in driver.
>   */
> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>  {
>  	struct vb2_buffer *vb;
>  	int ret;
>  
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -
> -	ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
> -	if (ret)
> -		return ret;
> -
> -	vb = q->bufs[b->index];
> +	vb = q->bufs[index];
>  	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>  		dprintk(1, "invalid buffer state %d\n",
>  			vb->state);
>  		return -EINVAL;
>  	}
>  
> -	ret = __buf_prepare(vb, b);
> +	ret = __buf_prepare(vb, pb);
>  	if (!ret) {
>  		/* Fill buffer information for the userspace */
> -		__fill_v4l2_buffer(vb, b);
> +		call_bufop(q, fill_user_buffer, vb, pb);
>  
>  		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
>  	}
>  	return ret;
>  }
> -EXPORT_SYMBOL_GPL(vb2_prepare_buf);
> +EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
>  
>  /**
>   * vb2_start_streaming() - Attempt to start streaming.
> @@ -1873,21 +1366,16 @@ static int vb2_start_streaming(struct vb2_queue *q)
>  	return ret;
>  }
>  
> -static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
>  {
> -	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
> +	int ret;
>  	struct vb2_buffer *vb;
> -	struct vb2_v4l2_buffer *vbuf;
> -
> -	if (ret)
> -		return ret;
>  
> -	vb = q->bufs[b->index];
> -	vbuf = to_vb2_v4l2_buffer(vb);
> +	vb = q->bufs[index];
>  
>  	switch (vb->state) {
>  	case VB2_BUF_STATE_DEQUEUED:
> -		ret = __buf_prepare(vb, b);
> +		ret = __buf_prepare(vb, pb);
>  		if (ret)
>  			return ret;
>  		break;
> @@ -1909,18 +1397,9 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  	q->queued_count++;
>  	q->waiting_for_buffers = false;
>  	vb->state = VB2_BUF_STATE_QUEUED;
> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
> -		/*
> -		 * For output buffers copy the timestamp if needed,
> -		 * and the timecode field and flag if needed.
> -		 */
> -		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> -				V4L2_BUF_FLAG_TIMESTAMP_COPY)
> -			vbuf->timestamp = b->timestamp;
> -		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> -		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> -			vbuf->timecode = b->timecode;
> -	}
> +
> +	if (q->is_output)
> +		call_bufop(q, fill_vb2_timestamp, vb, pb);
>  
>  	trace_vb2_qbuf(q, vb);
>  
> @@ -1932,7 +1411,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  		__enqueue_in_driver(vb);
>  
>  	/* Fill buffer information for the userspace */
> -	__fill_v4l2_buffer(vb, b);
> +	call_bufop(q, fill_user_buffer, vb, pb);
>  
>  	/*
>  	 * If streamon has been called, and we haven't yet called
> @@ -1950,34 +1429,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
>  	return 0;
>  }
> -
> -/**
> - * vb2_qbuf() - Queue a buffer from userspace
> - * @q:		videobuf2 queue
> - * @b:		buffer structure passed from userspace to vidioc_qbuf handler
> - *		in driver
> - *
> - * Should be called from vidioc_qbuf ioctl handler of a driver.
> - * This function:
> - * 1) verifies the passed buffer,
> - * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
> - *    which driver-specific buffer initialization can be performed,
> - * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
> - *    callback for processing.
> - *
> - * The return values from this function are intended to be directly returned
> - * from vidioc_qbuf handler in driver.
> - */
> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> -{
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -
> -	return vb2_internal_qbuf(q, b);
> -}
> -EXPORT_SYMBOL_GPL(vb2_qbuf);
> +EXPORT_SYMBOL_GPL(vb2_core_qbuf);
>  
>  /**
>   * __vb2_wait_for_done_vb() - wait for a buffer to become available
> @@ -2061,7 +1513,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
>   * Will sleep if required for nonblocking == false.
>   */
>  static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
> -				struct v4l2_buffer *b, int nonblocking)
> +				int nonblocking)
>  {
>  	unsigned long flags;
>  	int ret;
> @@ -2082,10 +1534,11 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
>  	/*
>  	 * Only remove the buffer from done_list if v4l2_buffer can handle all
>  	 * the planes.
> +	 * ret = __verify_planes_array(*vb, pb);
> +	 * But, actually that's unnecessary since this is checked already
> +	 * before the buffer is queued/prepared. So it can never fails
>  	 */
> -	ret = __verify_planes_array(*vb, b);
> -	if (!ret)
> -		list_del(&(*vb)->done_entry);
> +	list_del(&(*vb)->done_entry);
>  	spin_unlock_irqrestore(&q->done_lock, flags);
>  
>  	return ret;
> @@ -2128,27 +1581,22 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
>  	vb->state = VB2_BUF_STATE_DEQUEUED;
>  
>  	/* unmap DMABUF buffer */
> -	if (q->memory == V4L2_MEMORY_DMABUF)
> +	if (q->memory == VB2_MEMORY_DMABUF)
>  		for (i = 0; i < vb->num_planes; ++i) {
>  			if (!vb->planes[i].dbuf_mapped)
>  				continue;
> -			call_void_memop(vb, unmap_dmabuf, vb->planes[i].mem_priv);
> +			call_void_memop(vb, unmap_dmabuf,
> +					vb->planes[i].mem_priv);
>  			vb->planes[i].dbuf_mapped = 0;
>  		}
>  }
>  
> -static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> -		bool nonblocking)
> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
>  {
>  	struct vb2_buffer *vb = NULL;
> -	struct vb2_v4l2_buffer *vbuf = NULL;
>  	int ret;
>  
> -	if (b->type != q->type) {
> -		dprintk(1, "invalid buffer type\n");
> -		return -EINVAL;
> -	}
> -	ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
> +	ret = __vb2_get_done_vb(q, &vb, nonblocking);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -2167,16 +1615,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>  	call_void_vb_qop(vb, buf_finish, vb);
>  
>  	/* Fill buffer information for the userspace */
> -	__fill_v4l2_buffer(vb, b);
> +	call_bufop(q, fill_user_buffer, vb, pb);
>  	/* Remove from videobuf queue */
>  	list_del(&vb->queued_entry);
>  	q->queued_count--;
>  
>  	trace_vb2_dqbuf(q, vb);
>  
> -	vbuf = to_vb2_v4l2_buffer(vb);
> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
> -			vbuf->flags & V4L2_BUF_FLAG_LAST)
> +	if (!q->is_output &&
> +			call_bufop(q, is_last, vb))
>  		q->last_buffer_dequeued = true;
>  	/* go back to dequeued state */
>  	__vb2_dqbuf(vb);
> @@ -2186,37 +1633,7 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>  
>  	return 0;
>  }
> -
> -/**
> - * vb2_dqbuf() - Dequeue a buffer to the userspace
> - * @q:		videobuf2 queue
> - * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
> - *		in driver
> - * @nonblocking: if true, this call will not sleep waiting for a buffer if no
> - *		 buffers ready for dequeuing are present. Normally the driver
> - *		 would be passing (file->f_flags & O_NONBLOCK) here
> - *
> - * Should be called from vidioc_dqbuf ioctl handler of a driver.
> - * This function:
> - * 1) verifies the passed buffer,
> - * 2) calls buf_finish callback in the driver (if provided), in which
> - *    driver can perform any additional operations that may be required before
> - *    returning the buffer to userspace, such as cache sync,
> - * 3) the buffer struct members are filled with relevant information for
> - *    the userspace.
> - *
> - * The return values from this function are intended to be directly returned
> - * from vidioc_dqbuf handler in driver.
> - */
> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
> -{
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -	return vb2_internal_dqbuf(q, b, nonblocking);
> -}
> -EXPORT_SYMBOL_GPL(vb2_dqbuf);
> +EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
>  
>  /**
>   * __vb2_queue_cancel() - cancel and stop (pause) streaming
> @@ -2286,15 +1703,10 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	}
>  }
>  
> -static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> +int vb2_core_streamon(struct vb2_queue *q)
>  {
>  	int ret;
>  
> -	if (type != q->type) {
> -		dprintk(1, "invalid stream type\n");
> -		return -EINVAL;
> -	}
> -
>  	if (q->streaming) {
>  		dprintk(3, "already streaming\n");
>  		return 0;
> @@ -2328,6 +1740,7 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>  	dprintk(3, "successful\n");
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(vb2_core_streamon);
>  
>  /**
>   * vb2_queue_error() - signal a fatal error on the queue
> @@ -2350,36 +1763,8 @@ void vb2_queue_error(struct vb2_queue *q)
>  }
>  EXPORT_SYMBOL_GPL(vb2_queue_error);
>  
> -/**
> - * vb2_streamon - start streaming
> - * @q:		videobuf2 queue
> - * @type:	type argument passed from userspace to vidioc_streamon handler
> - *
> - * Should be called from vidioc_streamon handler of a driver.
> - * This function:
> - * 1) verifies current state
> - * 2) passes any previously queued buffers to the driver and starts streaming
> - *
> - * The return values from this function are intended to be directly returned
> - * from vidioc_streamon handler in the driver.
> - */
> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> -{
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -	return vb2_internal_streamon(q, type);
> -}
> -EXPORT_SYMBOL_GPL(vb2_streamon);
> -
> -static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> +int vb2_core_streamoff(struct vb2_queue *q)
>  {
> -	if (type != q->type) {
> -		dprintk(1, "invalid stream type\n");
> -		return -EINVAL;
> -	}
> -
>  	/*
>  	 * Cancel will pause streaming and remove all buffers from the driver
>  	 * and videobuf, effectively returning control over them to userspace.
> @@ -2390,37 +1775,13 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>  	 * their normal dequeued state.
>  	 */
>  	__vb2_queue_cancel(q);
> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
> +	q->waiting_for_buffers = !q->is_output;
>  	q->last_buffer_dequeued = false;
>  
>  	dprintk(3, "successful\n");
>  	return 0;
>  }
> -
> -/**
> - * vb2_streamoff - stop streaming
> - * @q:		videobuf2 queue
> - * @type:	type argument passed from userspace to vidioc_streamoff handler
> - *
> - * Should be called from vidioc_streamoff handler of a driver.
> - * This function:
> - * 1) verifies current state,
> - * 2) stop streaming and dequeues any queued buffers, including those previously
> - *    passed to the driver (after waiting for the driver to finish).
> - *
> - * This call can be used for pausing playback.
> - * The return values from this function are intended to be directly returned
> - * from vidioc_streamoff handler in the driver
> - */
> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> -{
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -	return vb2_internal_streamoff(q, type);
> -}
> -EXPORT_SYMBOL_GPL(vb2_streamoff);
> +EXPORT_SYMBOL_GPL(vb2_core_streamoff);
>  
>  /**
>   * __find_plane_by_offset() - find plane associated with the given offset off
> @@ -2452,7 +1813,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>  }
>  
>  /**
> - * vb2_expbuf() - Export a buffer as a file descriptor
> + * vb2_core_expbuf() - Export a buffer as a file descriptor
>   * @q:		videobuf2 queue
>   * @eb:		export buffer structure passed from userspace to vidioc_expbuf
>   *		handler in driver
> @@ -2460,14 +1821,15 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>   * The return values from this function are intended to be directly returned
>   * from vidioc_expbuf handler in driver.
>   */
> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
> +		unsigned int index, unsigned int plane, unsigned int flags)
>  {
>  	struct vb2_buffer *vb = NULL;
>  	struct vb2_plane *vb_plane;
>  	int ret;
>  	struct dma_buf *dbuf;
>  
> -	if (q->memory != V4L2_MEMORY_MMAP) {
> +	if (q->memory != VB2_MEMORY_MMAP) {
>  		dprintk(1, "queue is not currently set up for mmap\n");
>  		return -EINVAL;
>  	}
> @@ -2477,78 +1839,60 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
>  		return -EINVAL;
>  	}
>  
> -	if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
> +	if (flags & ~(O_CLOEXEC | O_ACCMODE)) {
>  		dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n");
>  		return -EINVAL;
>  	}
>  
> -	if (eb->type != q->type) {
> +	if (type != q->type) {
>  		dprintk(1, "invalid buffer type\n");
>  		return -EINVAL;
>  	}
>  
> -	if (eb->index >= q->num_buffers) {
> +	if (index >= q->num_buffers) {
>  		dprintk(1, "buffer index out of range\n");
>  		return -EINVAL;
>  	}
>  
> -	vb = q->bufs[eb->index];
> +	vb = q->bufs[index];
>  
> -	if (eb->plane >= vb->num_planes) {
> +	if (plane >= vb->num_planes) {
>  		dprintk(1, "buffer plane out of range\n");
>  		return -EINVAL;
>  	}
>  
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "expbuf: file io in progress\n");
> -		return -EBUSY;
> -	}
> +	vb_plane = &vb->planes[plane];
>  
> -	vb_plane = &vb->planes[eb->plane];
> -
> -	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
> +	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv,
> +				flags & O_ACCMODE);
>  	if (IS_ERR_OR_NULL(dbuf)) {
>  		dprintk(1, "failed to export buffer %d, plane %d\n",
> -			eb->index, eb->plane);
> +			index, plane);
>  		return -EINVAL;
>  	}
>  
> -	ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
> +	ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
>  	if (ret < 0) {
>  		dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
> -			eb->index, eb->plane, ret);
> +			index, plane, ret);
>  		dma_buf_put(dbuf);
>  		return ret;
>  	}
>  
>  	dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
> -		eb->index, eb->plane, ret);
> -	eb->fd = ret;
> +		index, plane, ret);
> +	*fd = ret;
>  
>  	return 0;
>  }
> -EXPORT_SYMBOL_GPL(vb2_expbuf);
> +EXPORT_SYMBOL_GPL(vb2_core_expbuf);
>  
>  /**
> - * vb2_mmap() - map video buffers into application address space
> + * vb2_core_mmap() - map video buffers into application address space
>   * @q:		videobuf2 queue
>   * @vma:	vma passed to the mmap file operation handler in the driver
> - *
> - * Should be called from mmap file operation handler of a driver.
> - * This function maps one plane of one of the available video buffers to
> - * userspace. To map whole video memory allocated on reqbufs, this function
> - * has to be called once per each plane per each buffer previously allocated.
> - *
> - * When the userspace application calls mmap, it passes to it an offset returned
> - * to it earlier by the means of vidioc_querybuf handler. That offset acts as
> - * a "cookie", which is then used to identify the plane to be mapped.
> - * This function finds a plane with a matching offset and a mapping is performed
> - * by the means of a provided memory operation.
> - *
> - * The return values from this function are intended to be directly returned
> - * from the mmap handler in driver.

Please keep some documentation here. Ok, the function is now more
generic, but still it deserves to be properly documented ;)

>   */
> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  {
>  	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
>  	struct vb2_buffer *vb;
> @@ -2556,7 +1900,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  	int ret;
>  	unsigned long length;
>  
> -	if (q->memory != V4L2_MEMORY_MMAP) {
> +	if (q->memory != VB2_MEMORY_MMAP) {
>  		dprintk(1, "queue is not currently set up for mmap\n");
>  		return -EINVAL;
>  	}
> @@ -2568,7 +1912,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  		dprintk(1, "invalid vma flags, VM_SHARED needed\n");
>  		return -EINVAL;
>  	}
> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
> +	if (q->is_output) {
>  		if (!(vma->vm_flags & VM_WRITE)) {
>  			dprintk(1, "invalid vma flags, VM_WRITE needed\n");
>  			return -EINVAL;
> @@ -2579,10 +1923,6 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  			return -EINVAL;
>  		}
>  	}
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "mmap: file io in progress\n");
> -		return -EBUSY;
> -	}
>  
>  	/*
>  	 * Find the plane corresponding to the offset passed by userspace.
> @@ -2614,7 +1954,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  	dprintk(3, "buffer %d, plane %d successfully mapped\n", buffer, plane);
>  	return 0;
>  }
> -EXPORT_SYMBOL_GPL(vb2_mmap);
> +EXPORT_SYMBOL_GPL(vb2_core_mmap);
>  
>  #ifndef CONFIG_MMU
>  unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
> @@ -2629,7 +1969,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  	void *vaddr;
>  	int ret;
>  
> -	if (q->memory != V4L2_MEMORY_MMAP) {
> +	if (q->memory != VB2_MEMORY_MMAP) {
>  		dprintk(1, "queue is not currently set up for mmap\n");
>  		return -EINVAL;
>  	}
> @@ -2649,123 +1989,8 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
>  #endif
>  
> -static int __vb2_init_fileio(struct vb2_queue *q, int read);
> -static int __vb2_cleanup_fileio(struct vb2_queue *q);
> -
> -/**
> - * vb2_poll() - implements poll userspace operation
> - * @q:		videobuf2 queue
> - * @file:	file argument passed to the poll file operation handler
> - * @wait:	wait argument passed to the poll file operation handler
> - *
> - * This function implements poll file operation handler for a driver.
> - * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
> - * be informed that the file descriptor of a video device is available for
> - * reading.
> - * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
> - * will be reported as available for writing.
> - *
> - * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
> - * pending events.
> - *
> - * The return values from this function are intended to be directly returned
> - * from poll handler in driver.
> - */
> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> -{
> -	struct video_device *vfd = video_devdata(file);
> -	unsigned long req_events = poll_requested_events(wait);
> -	struct vb2_buffer *vb = NULL;
> -	unsigned int res = 0;
> -	unsigned long flags;
> -
> -	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> -		struct v4l2_fh *fh = file->private_data;
> -
> -		if (v4l2_event_pending(fh))
> -			res = POLLPRI;
> -		else if (req_events & POLLPRI)
> -			poll_wait(file, &fh->wait, wait);
> -	}
> -
> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLIN | POLLRDNORM)))
> -		return res;
> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLOUT | POLLWRNORM)))
> -		return res;
> -
> -	/*
> -	 * Start file I/O emulator only if streaming API has not been used yet.
> -	 */
> -	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
> -		if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
> -				(req_events & (POLLIN | POLLRDNORM))) {
> -			if (__vb2_init_fileio(q, 1))
> -				return res | POLLERR;
> -		}
> -		if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
> -				(req_events & (POLLOUT | POLLWRNORM))) {
> -			if (__vb2_init_fileio(q, 0))
> -				return res | POLLERR;
> -			/*
> -			 * Write to OUTPUT queue can be done immediately.
> -			 */
> -			return res | POLLOUT | POLLWRNORM;
> -		}
> -	}
> -
> -	/*
> -	 * There is nothing to wait for if the queue isn't streaming, or if the
> -	 * error flag is set.
> -	 */
> -	if (!vb2_is_streaming(q) || q->error)
> -		return res | POLLERR;
> -	/*
> -	 * For compatibility with vb1: if QBUF hasn't been called yet, then
> -	 * return POLLERR as well. This only affects capture queues, output
> -	 * queues will always initialize waiting_for_buffers to false.
> -	 */
> -	if (q->waiting_for_buffers)
> -		return res | POLLERR;
> -
> -	/*
> -	 * For output streams you can write as long as there are fewer buffers
> -	 * queued than there are buffers available.
> -	 */
> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
> -		return res | POLLOUT | POLLWRNORM;
> -
> -	if (list_empty(&q->done_list)) {
> -		/*
> -		 * If the last buffer was dequeued from a capture queue,
> -		 * return immediately. DQBUF will return -EPIPE.
> -		 */
> -		if (q->last_buffer_dequeued)
> -			return res | POLLIN | POLLRDNORM;
> -
> -		poll_wait(file, &q->done_wq, wait);
> -	}
> -
> -	/*
> -	 * Take first buffer available for dequeuing.
> -	 */
> -	spin_lock_irqsave(&q->done_lock, flags);
> -	if (!list_empty(&q->done_list))
> -		vb = list_first_entry(&q->done_list, struct vb2_buffer,
> -					done_entry);
> -	spin_unlock_irqrestore(&q->done_lock, flags);
> -
> -	if (vb && (vb->state == VB2_BUF_STATE_DONE
> -			|| vb->state == VB2_BUF_STATE_ERROR)) {
> -		return (V4L2_TYPE_IS_OUTPUT(q->type)) ?
> -				res | POLLOUT | POLLWRNORM :
> -				res | POLLIN | POLLRDNORM;
> -	}
> -	return res;
> -}
> -EXPORT_SYMBOL_GPL(vb2_poll);
> -
>  /**
> - * vb2_queue_init() - initialize a videobuf2 queue
> + * vb2_core_queue_init() - initialize a videobuf2 queue
>   * @q:		videobuf2 queue; this structure should be allocated in driver
>   *
>   * The vb2_queue structure should be allocated by the driver. The driver is
> @@ -2775,7 +2000,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
>   * to the struct vb2_queue description in include/media/videobuf2-core.h
>   * for more information.
>   */
> -int vb2_queue_init(struct vb2_queue *q)
> +int vb2_core_queue_init(struct vb2_queue *q)
>  {
>  	/*
>  	 * Sanity check
> @@ -2783,19 +2008,13 @@ int vb2_queue_init(struct vb2_queue *q)
>  	if (WARN_ON(!q)				||
>  		WARN_ON(!q->ops)		||
>  		WARN_ON(!q->mem_ops)		||
> +		WARN_ON(!q->buf_ops)		||
>  		WARN_ON(!q->type)		||
>  		WARN_ON(!q->io_modes)		||
>  		WARN_ON(!q->ops->queue_setup)	||
> -		WARN_ON(!q->ops->buf_queue)	||
> -		WARN_ON(q->timestamp_flags &
> -			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> -			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
> +		WARN_ON(!q->ops->buf_queue))
>  		return -EINVAL;
>  
> -	/* Warn that the driver should choose an appropriate timestamp type */
> -	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> -		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
> -
>  	INIT_LIST_HEAD(&q->queued_list);
>  	INIT_LIST_HEAD(&q->done_list);
>  	spin_lock_init(&q->done_lock);
> @@ -2807,822 +2026,24 @@ int vb2_queue_init(struct vb2_queue *q)
>  
>  	return 0;
>  }
> -EXPORT_SYMBOL_GPL(vb2_queue_init);
> +EXPORT_SYMBOL_GPL(vb2_core_queue_init);
>  
>  /**
> - * vb2_queue_release() - stop streaming, release the queue and free memory
> + * vb2_core_queue_release() - stop streaming, release the queue and free memory
>   * @q:		videobuf2 queue
>   *
>   * This function stops streaming and performs necessary clean ups, including
>   * freeing video buffer memory. The driver is responsible for freeing
>   * the vb2_queue structure itself.
>   */
> -void vb2_queue_release(struct vb2_queue *q)
> +void vb2_core_queue_release(struct vb2_queue *q)
>  {
> -	__vb2_cleanup_fileio(q);
>  	__vb2_queue_cancel(q);
>  	mutex_lock(&q->mmap_lock);
>  	__vb2_queue_free(q, q->num_buffers);
>  	mutex_unlock(&q->mmap_lock);
>  }
> -EXPORT_SYMBOL_GPL(vb2_queue_release);
> -
> -/**
> - * struct vb2_fileio_buf - buffer context used by file io emulator
> - *
> - * vb2 provides a compatibility layer and emulator of file io (read and
> - * write) calls on top of streaming API. This structure is used for
> - * tracking context related to the buffers.
> - */
> -struct vb2_fileio_buf {
> -	void *vaddr;
> -	unsigned int size;
> -	unsigned int pos;
> -	unsigned int queued:1;
> -};
> -
> -/**
> - * struct vb2_fileio_data - queue context used by file io emulator
> - *
> - * @cur_index:	the index of the buffer currently being read from or
> - *		written to. If equal to q->num_buffers then a new buffer
> - *		must be dequeued.
> - * @initial_index: in the read() case all buffers are queued up immediately
> - *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
> - *		buffers. However, in the write() case no buffers are initially
> - *		queued, instead whenever a buffer is full it is queued up by
> - *		__vb2_perform_fileio(). Only once all available buffers have
> - *		been queued up will __vb2_perform_fileio() start to dequeue
> - *		buffers. This means that initially __vb2_perform_fileio()
> - *		needs to know what buffer index to use when it is queuing up
> - *		the buffers for the first time. That initial index is stored
> - *		in this field. Once it is equal to q->num_buffers all
> - *		available buffers have been queued and __vb2_perform_fileio()
> - *		should start the normal dequeue/queue cycle.
> - *
> - * vb2 provides a compatibility layer and emulator of file io (read and
> - * write) calls on top of streaming API. For proper operation it required
> - * this structure to save the driver state between each call of the read
> - * or write function.
> - */
> -struct vb2_fileio_data {
> -	struct v4l2_requestbuffers req;
> -	struct v4l2_plane p;
> -	struct v4l2_buffer b;
> -	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
> -	unsigned int cur_index;
> -	unsigned int initial_index;
> -	unsigned int q_count;
> -	unsigned int dq_count;
> -	unsigned read_once:1;
> -	unsigned write_immediately:1;
> -};
> -
> -/**
> - * __vb2_init_fileio() - initialize file io emulator
> - * @q:		videobuf2 queue
> - * @read:	mode selector (1 means read, 0 means write)
> - */
> -static int __vb2_init_fileio(struct vb2_queue *q, int read)
> -{
> -	struct vb2_fileio_data *fileio;
> -	int i, ret;
> -	unsigned int count = 0;
> -
> -	/*
> -	 * Sanity check
> -	 */
> -	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
> -			(!read && !(q->io_modes & VB2_WRITE))))
> -		return -EINVAL;
> -
> -	/*
> -	 * Check if device supports mapping buffers to kernel virtual space.
> -	 */
> -	if (!q->mem_ops->vaddr)
> -		return -EBUSY;
> -
> -	/*
> -	 * Check if streaming api has not been already activated.
> -	 */
> -	if (q->streaming || q->num_buffers > 0)
> -		return -EBUSY;
> -
> -	/*
> -	 * Start with count 1, driver can increase it in queue_setup()
> -	 */
> -	count = 1;
> -
> -	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
> -		(read) ? "read" : "write", count, q->fileio_read_once,
> -		q->fileio_write_immediately);
> -
> -	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
> -	if (fileio == NULL)
> -		return -ENOMEM;
> -
> -	fileio->read_once = q->fileio_read_once;
> -	fileio->write_immediately = q->fileio_write_immediately;
> -
> -	/*
> -	 * Request buffers and use MMAP type to force driver
> -	 * to allocate buffers by itself.
> -	 */
> -	fileio->req.count = count;
> -	fileio->req.memory = V4L2_MEMORY_MMAP;
> -	fileio->req.type = q->type;
> -	q->fileio = fileio;
> -	ret = __reqbufs(q, &fileio->req);
> -	if (ret)
> -		goto err_kfree;
> -
> -	/*
> -	 * Check if plane_count is correct
> -	 * (multiplane buffers are not supported).
> -	 */
> -	if (q->bufs[0]->num_planes != 1) {
> -		ret = -EBUSY;
> -		goto err_reqbufs;
> -	}
> -
> -	/*
> -	 * Get kernel address of each buffer.
> -	 */
> -	for (i = 0; i < q->num_buffers; i++) {
> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
> -		if (fileio->bufs[i].vaddr == NULL) {
> -			ret = -EINVAL;
> -			goto err_reqbufs;
> -		}
> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
> -	}
> -
> -	/*
> -	 * Read mode requires pre queuing of all buffers.
> -	 */
> -	if (read) {
> -		bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> -
> -		/*
> -		 * Queue all buffers.
> -		 */
> -		for (i = 0; i < q->num_buffers; i++) {
> -			struct v4l2_buffer *b = &fileio->b;
> -
> -			memset(b, 0, sizeof(*b));
> -			b->type = q->type;
> -			if (is_multiplanar) {
> -				memset(&fileio->p, 0, sizeof(fileio->p));
> -				b->m.planes = &fileio->p;
> -				b->length = 1;
> -			}
> -			b->memory = q->memory;
> -			b->index = i;
> -			ret = vb2_internal_qbuf(q, b);
> -			if (ret)
> -				goto err_reqbufs;
> -			fileio->bufs[i].queued = 1;
> -		}
> -		/*
> -		 * All buffers have been queued, so mark that by setting
> -		 * initial_index to q->num_buffers
> -		 */
> -		fileio->initial_index = q->num_buffers;
> -		fileio->cur_index = q->num_buffers;
> -	}
> -
> -	/*
> -	 * Start streaming.
> -	 */
> -	ret = vb2_internal_streamon(q, q->type);
> -	if (ret)
> -		goto err_reqbufs;
> -
> -	return ret;
> -
> -err_reqbufs:
> -	fileio->req.count = 0;
> -	__reqbufs(q, &fileio->req);
> -
> -err_kfree:
> -	q->fileio = NULL;
> -	kfree(fileio);
> -	return ret;
> -}
> -
> -/**
> - * __vb2_cleanup_fileio() - free resourced used by file io emulator
> - * @q:		videobuf2 queue
> - */
> -static int __vb2_cleanup_fileio(struct vb2_queue *q)
> -{
> -	struct vb2_fileio_data *fileio = q->fileio;
> -
> -	if (fileio) {
> -		vb2_internal_streamoff(q, q->type);
> -		q->fileio = NULL;
> -		fileio->req.count = 0;
> -		vb2_reqbufs(q, &fileio->req);
> -		kfree(fileio);
> -		dprintk(3, "file io emulator closed\n");
> -	}
> -	return 0;
> -}
> -
> -/**
> - * __vb2_perform_fileio() - perform a single file io (read or write) operation
> - * @q:		videobuf2 queue
> - * @data:	pointed to target userspace buffer
> - * @count:	number of bytes to read or write
> - * @ppos:	file handle position tracking pointer
> - * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
> - * @read:	access mode selector (1 means read, 0 means write)
> - */
> -static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
> -		loff_t *ppos, int nonblock, int read)
> -{
> -	struct vb2_fileio_data *fileio;
> -	struct vb2_fileio_buf *buf;
> -	bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> -	/*
> -	 * When using write() to write data to an output video node the vb2 core
> -	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
> -	 * else is able to provide this information with the write() operation.
> -	 */
> -	bool set_timestamp = !read &&
> -		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> -		V4L2_BUF_FLAG_TIMESTAMP_COPY;
> -	int ret, index;
> -
> -	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
> -		read ? "read" : "write", (long)*ppos, count,
> -		nonblock ? "non" : "");
> -
> -	if (!data)
> -		return -EINVAL;
> -
> -	/*
> -	 * Initialize emulator on first call.
> -	 */
> -	if (!vb2_fileio_is_active(q)) {
> -		ret = __vb2_init_fileio(q, read);
> -		dprintk(3, "vb2_init_fileio result: %d\n", ret);
> -		if (ret)
> -			return ret;
> -	}
> -	fileio = q->fileio;
> -
> -	/*
> -	 * Check if we need to dequeue the buffer.
> -	 */
> -	index = fileio->cur_index;
> -	if (index >= q->num_buffers) {
> -		/*
> -		 * Call vb2_dqbuf to get buffer back.
> -		 */
> -		memset(&fileio->b, 0, sizeof(fileio->b));
> -		fileio->b.type = q->type;
> -		fileio->b.memory = q->memory;
> -		if (is_multiplanar) {
> -			memset(&fileio->p, 0, sizeof(fileio->p));
> -			fileio->b.m.planes = &fileio->p;
> -			fileio->b.length = 1;
> -		}
> -		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
> -		dprintk(5, "vb2_dqbuf result: %d\n", ret);
> -		if (ret)
> -			return ret;
> -		fileio->dq_count += 1;
> -
> -		fileio->cur_index = index = fileio->b.index;
> -		buf = &fileio->bufs[index];
> -
> -		/*
> -		 * Get number of bytes filled by the driver
> -		 */
> -		buf->pos = 0;
> -		buf->queued = 0;
> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> -				 : vb2_plane_size(q->bufs[index], 0);
> -		/*
> -		 * Compensate for data_offset on read
> -		 * in the multiplanar case
> -		 */
> -		if (is_multiplanar && read &&
> -			fileio->b.m.planes[0].data_offset < buf->size) {
> -			buf->pos = fileio->b.m.planes[0].data_offset;
> -			buf->size -= buf->pos;
> -		}
> -	} else {
> -		buf = &fileio->bufs[index];
> -	}
> -
> -	/*
> -	 * Limit count on last few bytes of the buffer.
> -	 */
> -	if (buf->pos + count > buf->size) {
> -		count = buf->size - buf->pos;
> -		dprintk(5, "reducing read count: %zd\n", count);
> -	}
> -
> -	/*
> -	 * Transfer data to userspace.
> -	 */
> -	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
> -		count, index, buf->pos);
> -	if (read)
> -		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
> -	else
> -		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
> -	if (ret) {
> -		dprintk(3, "error copying data\n");
> -		return -EFAULT;
> -	}
> -
> -	/*
> -	 * Update counters.
> -	 */
> -	buf->pos += count;
> -	*ppos += count;
> -
> -	/*
> -	 * Queue next buffer if required.
> -	 */
> -	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
> -		/*
> -		 * Check if this is the last buffer to read.
> -		 */
> -		if (read && fileio->read_once && fileio->dq_count == 1) {
> -			dprintk(3, "read limit reached\n");
> -			return __vb2_cleanup_fileio(q);
> -		}
> -
> -		/*
> -		 * Call vb2_qbuf and give buffer to the driver.
> -		 */
> -		memset(&fileio->b, 0, sizeof(fileio->b));
> -		fileio->b.type = q->type;
> -		fileio->b.memory = q->memory;
> -		fileio->b.index = index;
> -		fileio->b.bytesused = buf->pos;
> -		if (is_multiplanar) {
> -			memset(&fileio->p, 0, sizeof(fileio->p));
> -			fileio->p.bytesused = buf->pos;
> -			fileio->b.m.planes = &fileio->p;
> -			fileio->b.length = 1;
> -		}
> -		if (set_timestamp)
> -			v4l2_get_timestamp(&fileio->b.timestamp);
> -		ret = vb2_internal_qbuf(q, &fileio->b);
> -		dprintk(5, "vb2_dbuf result: %d\n", ret);
> -		if (ret)
> -			return ret;
> -
> -		/*
> -		 * Buffer has been queued, update the status
> -		 */
> -		buf->pos = 0;
> -		buf->queued = 1;
> -		buf->size = vb2_plane_size(q->bufs[index], 0);
> -		fileio->q_count += 1;
> -		/*
> -		 * If we are queuing up buffers for the first time, then
> -		 * increase initial_index by one.
> -		 */
> -		if (fileio->initial_index < q->num_buffers)
> -			fileio->initial_index++;
> -		/*
> -		 * The next buffer to use is either a buffer that's going to be
> -		 * queued for the first time (initial_index < q->num_buffers)
> -		 * or it is equal to q->num_buffers, meaning that the next
> -		 * time we need to dequeue a buffer since we've now queued up
> -		 * all the 'first time' buffers.
> -		 */
> -		fileio->cur_index = fileio->initial_index;
> -	}
> -
> -	/*
> -	 * Return proper number of bytes processed.
> -	 */
> -	if (ret == 0)
> -		ret = count;
> -	return ret;
> -}
> -
> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> -		loff_t *ppos, int nonblocking)
> -{
> -	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
> -}
> -EXPORT_SYMBOL_GPL(vb2_read);
> -
> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> -		loff_t *ppos, int nonblocking)
> -{
> -	return __vb2_perform_fileio(q, (char __user *) data, count,
> -							ppos, nonblocking, 0);
> -}
> -EXPORT_SYMBOL_GPL(vb2_write);
> -
> -struct vb2_threadio_data {
> -	struct task_struct *thread;
> -	vb2_thread_fnc fnc;
> -	void *priv;
> -	bool stop;
> -};
> -
> -static int vb2_thread(void *data)
> -{
> -	struct vb2_queue *q = data;
> -	struct vb2_threadio_data *threadio = q->threadio;
> -	struct vb2_fileio_data *fileio = q->fileio;
> -	bool set_timestamp = false;
> -	int prequeue = 0;
> -	int index = 0;
> -	int ret = 0;
> -
> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
> -		prequeue = q->num_buffers;
> -		set_timestamp =
> -			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> -			V4L2_BUF_FLAG_TIMESTAMP_COPY;
> -	}
> -
> -	set_freezable();
> -
> -	for (;;) {
> -		struct vb2_buffer *vb;
> -
> -		/*
> -		 * Call vb2_dqbuf to get buffer back.
> -		 */
> -		memset(&fileio->b, 0, sizeof(fileio->b));
> -		fileio->b.type = q->type;
> -		fileio->b.memory = q->memory;
> -		if (prequeue) {
> -			fileio->b.index = index++;
> -			prequeue--;
> -		} else {
> -			call_void_qop(q, wait_finish, q);
> -			if (!threadio->stop)
> -				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
> -			call_void_qop(q, wait_prepare, q);
> -			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
> -		}
> -		if (ret || threadio->stop)
> -			break;
> -		try_to_freeze();
> -
> -		vb = q->bufs[fileio->b.index];
> -		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
> -			if (threadio->fnc(vb, threadio->priv))
> -				break;
> -		call_void_qop(q, wait_finish, q);
> -		if (set_timestamp)
> -			v4l2_get_timestamp(&fileio->b.timestamp);
> -		if (!threadio->stop)
> -			ret = vb2_internal_qbuf(q, &fileio->b);
> -		call_void_qop(q, wait_prepare, q);
> -		if (ret || threadio->stop)
> -			break;
> -	}
> -
> -	/* Hmm, linux becomes *very* unhappy without this ... */
> -	while (!kthread_should_stop()) {
> -		set_current_state(TASK_INTERRUPTIBLE);
> -		schedule();
> -	}
> -	return 0;
> -}
> -
> -/*
> - * This function should not be used for anything else but the videobuf2-dvb
> - * support. If you think you have another good use-case for this, then please
> - * contact the linux-media mailinglist first.
> - */
> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> -			const char *thread_name)
> -{
> -	struct vb2_threadio_data *threadio;
> -	int ret = 0;
> -
> -	if (q->threadio)
> -		return -EBUSY;
> -	if (vb2_is_busy(q))
> -		return -EBUSY;
> -	if (WARN_ON(q->fileio))
> -		return -EBUSY;
> -
> -	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
> -	if (threadio == NULL)
> -		return -ENOMEM;
> -	threadio->fnc = fnc;
> -	threadio->priv = priv;
> -
> -	ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type));
> -	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
> -	if (ret)
> -		goto nomem;
> -	q->threadio = threadio;
> -	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
> -	if (IS_ERR(threadio->thread)) {
> -		ret = PTR_ERR(threadio->thread);
> -		threadio->thread = NULL;
> -		goto nothread;
> -	}
> -	return 0;
> -
> -nothread:
> -	__vb2_cleanup_fileio(q);
> -nomem:
> -	kfree(threadio);
> -	return ret;
> -}
> -EXPORT_SYMBOL_GPL(vb2_thread_start);
> -
> -int vb2_thread_stop(struct vb2_queue *q)
> -{
> -	struct vb2_threadio_data *threadio = q->threadio;
> -	int err;
> -
> -	if (threadio == NULL)
> -		return 0;
> -	threadio->stop = true;
> -	/* Wake up all pending sleeps in the thread */
> -	vb2_queue_error(q);
> -	err = kthread_stop(threadio->thread);
> -	__vb2_cleanup_fileio(q);
> -	threadio->thread = NULL;
> -	kfree(threadio);
> -	q->threadio = NULL;
> -	return err;
> -}
> -EXPORT_SYMBOL_GPL(vb2_thread_stop);
> -
> -/*
> - * The following functions are not part of the vb2 core API, but are helper
> - * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
> - * and struct vb2_ops.
> - * They contain boilerplate code that most if not all drivers have to do
> - * and so they simplify the driver code.
> - */
> -
> -/* The queue is busy if there is a owner and you are not that owner. */
> -static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
> -{
> -	return vdev->queue->owner && vdev->queue->owner != file->private_data;
> -}
> -
> -/* vb2 ioctl helpers */
> -
> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
> -			  struct v4l2_requestbuffers *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	int res = __verify_memory_type(vdev->queue, p->memory, p->type);
> -
> -	if (res)
> -		return res;
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	res = __reqbufs(vdev->queue, p);
> -	/* If count == 0, then the owner has released all buffers and he
> -	   is no longer owner of the queue. Otherwise we have a new owner. */
> -	if (res == 0)
> -		vdev->queue->owner = p->count ? file->private_data : NULL;
> -	return res;
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
> -
> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
> -			  struct v4l2_create_buffers *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	int res = __verify_memory_type(vdev->queue, p->memory, p->format.type);
> -
> -	p->index = vdev->queue->num_buffers;
> -	/* If count == 0, then just check if memory and type are valid.
> -	   Any -EBUSY result from __verify_memory_type can be mapped to 0. */
> -	if (p->count == 0)
> -		return res != -EBUSY ? res : 0;
> -	if (res)
> -		return res;
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	res = __create_bufs(vdev->queue, p);
> -	if (res == 0)
> -		vdev->queue->owner = file->private_data;
> -	return res;
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
> -
> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> -			  struct v4l2_buffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_prepare_buf(vdev->queue, p);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
> -
> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
> -	return vb2_querybuf(vdev->queue, p);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
> -
> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_qbuf(vdev->queue, p);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
> -
> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
> -
> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_streamon(vdev->queue, i);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
> -
> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_streamoff(vdev->queue, i);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
> -
> -int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_expbuf(vdev->queue, p);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
> -
> -/* v4l2_file_operations helpers */
> -
> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	return vb2_mmap(vdev->queue, vma);
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_mmap);
> -
> -int _vb2_fop_release(struct file *file, struct mutex *lock)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (lock)
> -		mutex_lock(lock);
> -	if (file->private_data == vdev->queue->owner) {
> -		vb2_queue_release(vdev->queue);
> -		vdev->queue->owner = NULL;
> -	}
> -	if (lock)
> -		mutex_unlock(lock);
> -	return v4l2_fh_release(file);
> -}
> -EXPORT_SYMBOL_GPL(_vb2_fop_release);
> -
> -int vb2_fop_release(struct file *file)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> -
> -	return _vb2_fop_release(file, lock);
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_release);
> -
> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> -		size_t count, loff_t *ppos)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> -	int err = -EBUSY;
> -
> -	if (!(vdev->queue->io_modes & VB2_WRITE))
> -		return -EINVAL;
> -	if (lock && mutex_lock_interruptible(lock))
> -		return -ERESTARTSYS;
> -	if (vb2_queue_is_busy(vdev, file))
> -		goto exit;
> -	err = vb2_write(vdev->queue, buf, count, ppos,
> -			file->f_flags & O_NONBLOCK);
> -	if (vdev->queue->fileio)
> -		vdev->queue->owner = file->private_data;
> -exit:
> -	if (lock)
> -		mutex_unlock(lock);
> -	return err;
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_write);
> -
> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
> -		size_t count, loff_t *ppos)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> -	int err = -EBUSY;
> -
> -	if (!(vdev->queue->io_modes & VB2_READ))
> -		return -EINVAL;
> -	if (lock && mutex_lock_interruptible(lock))
> -		return -ERESTARTSYS;
> -	if (vb2_queue_is_busy(vdev, file))
> -		goto exit;
> -	err = vb2_read(vdev->queue, buf, count, ppos,
> -			file->f_flags & O_NONBLOCK);
> -	if (vdev->queue->fileio)
> -		vdev->queue->owner = file->private_data;
> -exit:
> -	if (lock)
> -		mutex_unlock(lock);
> -	return err;
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_read);
> -
> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	struct vb2_queue *q = vdev->queue;
> -	struct mutex *lock = q->lock ? q->lock : vdev->lock;
> -	unsigned res;
> -	void *fileio;
> -
> -	/*
> -	 * If this helper doesn't know how to lock, then you shouldn't be using
> -	 * it but you should write your own.
> -	 */
> -	WARN_ON(!lock);
> -
> -	if (lock && mutex_lock_interruptible(lock))
> -		return POLLERR;
> -
> -	fileio = q->fileio;
> -
> -	res = vb2_poll(vdev->queue, file, wait);
> -
> -	/* If fileio was started, then we have a new queue owner. */
> -	if (!fileio && q->fileio)
> -		q->owner = file->private_data;
> -	if (lock)
> -		mutex_unlock(lock);
> -	return res;
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_poll);
> -
> -#ifndef CONFIG_MMU
> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> -		unsigned long len, unsigned long pgoff, unsigned long flags)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
> -#endif
> -
> -/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
> -
> -void vb2_ops_wait_prepare(struct vb2_queue *vq)
> -{
> -	mutex_unlock(vq->lock);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
> -
> -void vb2_ops_wait_finish(struct vb2_queue *vq)
> -{
> -	mutex_lock(vq->lock);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
> +EXPORT_SYMBOL_GPL(vb2_core_queue_release);
>  
>  MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
>  MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
> diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h
> new file mode 100644
> index 0000000..3998ac9
> --- /dev/null
> +++ b/drivers/media/v4l2-core/videobuf2-internal.h
> @@ -0,0 +1,184 @@
> +#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H
> +#define _MEDIA_VIDEOBUF2_INTERNAL_H
> +
> +#include <linux/err.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <media/videobuf2-core.h>
> +
> +extern int vb2_debug;
> +
> +#define dprintk(level, fmt, arg...)					\
> +	do {								\
> +		if (vb2_debug >= level)					\
> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
> +	} while (0)
> +
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> +
> +/*
> + * If advanced debugging is on, then count how often each op is called
> + * successfully, which can either be per-buffer or per-queue.
> + *
> + * This makes it easy to check that the 'init' and 'cleanup'
> + * (and variations thereof) stay balanced.
> + */
> +
> +#define log_memop(vb, op)						\
> +	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
> +		(vb)->vb2_queue, (vb)->index, #op,			\
> +		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
> +
> +#define call_memop(vb, op, args...)					\
> +({									\
> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
> +	int err;							\
> +									\
> +	log_memop(vb, op);						\
> +	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
> +	if (!err)							\
> +		(vb)->cnt_mem_ ## op++;					\
> +	err;								\
> +})
> +
> +#define call_ptr_memop(vb, op, args...)					\
> +({									\
> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
> +	void *ptr;							\
> +									\
> +	log_memop(vb, op);						\
> +	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
> +	if (!IS_ERR_OR_NULL(ptr))					\
> +		(vb)->cnt_mem_ ## op++;					\
> +	ptr;								\
> +})
> +
> +#define call_void_memop(vb, op, args...)				\
> +({									\
> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
> +									\
> +	log_memop(vb, op);						\
> +	if (_q->mem_ops->op)						\
> +		_q->mem_ops->op(args);					\
> +	(vb)->cnt_mem_ ## op++;						\
> +})
> +
> +#define log_qop(q, op)							\
> +	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
> +		(q)->ops->op ? "" : " (nop)")
> +
> +#define call_qop(q, op, args...)					\
> +({									\
> +	int err;							\
> +									\
> +	log_qop(q, op);							\
> +	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
> +	if (!err)							\
> +		(q)->cnt_ ## op++;					\
> +	err;								\
> +})
> +
> +#define call_void_qop(q, op, args...)					\
> +({									\
> +	log_qop(q, op);							\
> +	if ((q)->ops->op)						\
> +		(q)->ops->op(args);					\
> +	(q)->cnt_ ## op++;						\
> +})
> +
> +#define log_vb_qop(vb, op, args...)					\
> +	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
> +		(vb)->vb2_queue, (vb)->index, #op,			\
> +		(vb)->vb2_queue->ops->op ? "" : " (nop)")
> +
> +#define call_vb_qop(vb, op, args...)					\
> +({									\
> +	int err;							\
> +									\
> +	log_vb_qop(vb, op);						\
> +	err = (vb)->vb2_queue->ops->op ?				\
> +		(vb)->vb2_queue->ops->op(args) : 0;			\
> +	if (!err)							\
> +		(vb)->cnt_ ## op++;					\
> +	err;								\
> +})
> +
> +#define call_void_vb_qop(vb, op, args...)				\
> +({									\
> +	log_vb_qop(vb, op);						\
> +	if ((vb)->vb2_queue->ops->op)					\
> +		(vb)->vb2_queue->ops->op(args);				\
> +	(vb)->cnt_ ## op++;						\
> +})
> +
> +#else
> +
> +#define call_memop(vb, op, args...)					\
> +	((vb)->vb2_queue->mem_ops->op ?					\
> +		(vb)->vb2_queue->mem_ops->op(args) : 0)
> +
> +#define call_ptr_memop(vb, op, args...)					\
> +	((vb)->vb2_queue->mem_ops->op ?					\
> +		(vb)->vb2_queue->mem_ops->op(args) : NULL)
> +
> +#define call_void_memop(vb, op, args...)				\
> +	do {								\
> +		if ((vb)->vb2_queue->mem_ops->op)			\
> +			(vb)->vb2_queue->mem_ops->op(args);		\
> +	} while (0)
> +
> +#define call_qop(q, op, args...)					\
> +	((q)->ops->op ? (q)->ops->op(args) : 0)
> +
> +#define call_void_qop(q, op, args...)					\
> +	do {								\
> +		if ((q)->ops->op)					\
> +			(q)->ops->op(args);				\
> +	} while (0)
> +
> +#define call_vb_qop(vb, op, args...)					\
> +	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
> +
> +#define call_void_vb_qop(vb, op, args...)				\
> +	do {								\
> +		if ((vb)->vb2_queue->ops->op)				\
> +			(vb)->vb2_queue->ops->op(args);			\
> +	} while (0)
> +
> +#endif
> +
> +#define call_bufop(q, op, args...)					\
> +({									\
> +	int ret = 0;							\
> +	if (q && q->buf_ops && q->buf_ops->op)				\
> +		ret = q->buf_ops->op(args);				\
> +	ret;								\
> +})
> +
> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
> +int vb2_verify_memory_type(struct vb2_queue *q,
> +		unsigned int memory, unsigned int type);
> +int vb2_verify_buffer(struct vb2_queue *q,
> +			unsigned int memory, unsigned int type,
> +			unsigned int index, unsigned int nplanes,
> +			void *pplane, const char *opname);
> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb);
> +
> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb);
> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
> +		unsigned int *count);
> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
> +		unsigned int *count, void *parg);
> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb);
> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblock);
> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
> +		unsigned int index, unsigned int plane, unsigned int flags);
> +int vb2_core_streamon(struct vb2_queue *q);
> +int vb2_core_streamoff(struct vb2_queue *q);
> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
> +
> +int __must_check vb2_core_queue_init(struct vb2_queue *q);
> +void vb2_core_queue_release(struct vb2_queue *q);
> +
> +#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> index 2f2b738..9fc6bef 100644
> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -24,8 +24,1648 @@
>  #include <linux/freezer.h>
>  #include <linux/kthread.h>
>  
> +#include <media/v4l2-dev.h>
> +#include <media/v4l2-fh.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-common.h>
>  #include <media/videobuf2-v4l2.h>
>  
> +#include "videobuf2-internal.h"
> +
> +/* Flags that are set by the vb2 core */
> +#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | \
> +				V4L2_BUF_FLAG_QUEUED | \
> +				V4L2_BUF_FLAG_DONE | \
> +				V4L2_BUF_FLAG_ERROR | \
> +				V4L2_BUF_FLAG_PREPARED | \
> +				V4L2_BUF_FLAG_TIMESTAMP_MASK)
> +
> +/* Output buffer flags that should be passed on to the driver */
> +#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | \
> +				V4L2_BUF_FLAG_BFRAME | \
> +				V4L2_BUF_FLAG_KEYFRAME | \
> +				V4L2_BUF_FLAG_TIMECODE)
> +
> +/**
> + * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
> + * returned to userspace
> + */
> +static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
> +{
> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;

As commented before, avoid doing typecasts if not required.

> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct vb2_queue *q = vb->vb2_queue;
> +	unsigned int plane;
> +
> +	/* Copy back data such as timestamp, flags, etc. */
> +	b->index = vb->index;
> +	b->type = vb->type;
> +	b->memory = vb->memory;
> +	b->bytesused = 0;
> +
> +	b->flags = vbuf->flags;
> +	b->field = vbuf->field;
> +	b->timestamp = vbuf->timestamp;
> +	b->timecode = vbuf->timecode;
> +	b->sequence = vbuf->sequence;
> +
> +	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
> +		/*
> +		 * Fill in plane-related data if userspace provided an array
> +		 * for it. The caller has already verified memory and size.
> +		 */
> +		b->length = vb->num_planes;
> +		for (plane = 0; plane < vb->num_planes; ++plane) {
> +			struct v4l2_plane *pdst = &b->m.planes[plane];
> +			struct vb2_plane *psrc = &vb->planes[plane];
> +
> +			pdst->bytesused = psrc->bytesused;
> +			pdst->length = psrc->length;
> +			if (q->memory == V4L2_MEMORY_MMAP)
> +				pdst->m.mem_offset = psrc->m.offset;
> +			else if (q->memory == V4L2_MEMORY_USERPTR)
> +				pdst->m.userptr = psrc->m.userptr;
> +			else if (q->memory == V4L2_MEMORY_DMABUF)
> +				pdst->m.fd = psrc->m.fd;
> +			pdst->data_offset = psrc->data_offset;
> +		}
> +	} else {
> +		/*
> +		 * We use length and offset in v4l2_planes array even for
> +		 * single-planar buffers, but userspace does not.
> +		 */
> +		b->length = vb->planes[0].length;
> +		b->bytesused = vb->planes[0].bytesused;
> +		if (q->memory == V4L2_MEMORY_MMAP)
> +			b->m.offset = vb->planes[0].m.offset;
> +		else if (q->memory == V4L2_MEMORY_USERPTR)
> +			b->m.userptr = vb->planes[0].m.userptr;
> +		else if (q->memory == V4L2_MEMORY_DMABUF)
> +			b->m.fd = vb->planes[0].m.fd;
> +	}
> +
> +	/*
> +	 * Clear any buffer state related flags.
> +	 */
> +	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
> +	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> +		/*
> +		 * For non-COPY timestamps, drop timestamp source bits
> +		 * and obtain the timestamp source from the queue.
> +		 */
> +		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> +		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> +	}
> +
> +	switch (vb->state) {
> +	case VB2_BUF_STATE_QUEUED:
> +	case VB2_BUF_STATE_ACTIVE:
> +		b->flags |= V4L2_BUF_FLAG_QUEUED;
> +		break;
> +	case VB2_BUF_STATE_ERROR:
> +		b->flags |= V4L2_BUF_FLAG_ERROR;
> +		/* fall through */
> +	case VB2_BUF_STATE_DONE:
> +		b->flags |= V4L2_BUF_FLAG_DONE;
> +		break;
> +	case VB2_BUF_STATE_PREPARED:
> +		b->flags |= V4L2_BUF_FLAG_PREPARED;
> +		break;
> +	case VB2_BUF_STATE_PREPARING:
> +	case VB2_BUF_STATE_DEQUEUED:
> +		/* nothing */
> +		break;
> +	}
> +
> +	if (vb2_buffer_in_use(q, vb))
> +		b->flags |= V4L2_BUF_FLAG_MAPPED;
> +
> +	return 0;
> +}
> +
> +/**
> + * __verify_length() - Verify that the bytesused value for each plane fits in
> + * the plane length and that the data offset doesn't exceed the bytesused value.
> + */
> +static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +{
> +	unsigned int length;
> +	unsigned int bytesused;
> +	unsigned int plane;
> +
> +	if (!V4L2_TYPE_IS_OUTPUT(b->type))
> +		return 0;
> +
> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> +		for (plane = 0; plane < vb->num_planes; ++plane) {
> +			length = (b->memory == V4L2_MEMORY_USERPTR ||
> +				b->memory == V4L2_MEMORY_DMABUF)
> +				? b->m.planes[plane].length
> +				: vb->planes[plane].length;
> +			bytesused = b->m.planes[plane].bytesused
> +				? b->m.planes[plane].bytesused : length;
> +
> +			if (b->m.planes[plane].bytesused > length)
> +				return -EINVAL;
> +
> +			if (b->m.planes[plane].data_offset > 0 &&
> +				b->m.planes[plane].data_offset >= bytesused)
> +				return -EINVAL;
> +		}
> +	} else {
> +		length = (b->memory == V4L2_MEMORY_USERPTR)
> +			? b->length : vb->planes[0].length;
> +
> +		if (b->bytesused > length)
> +			return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
> + * v4l2_buffer by the userspace. It also verifies that struct
> + * v4l2_buffer has a valid number of planes.
> + */
> +static int __fill_vb2_buffer(struct vb2_buffer *vb, void *pb,
> +				struct vb2_plane *planes)
> +{
> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	unsigned int plane;
> +	int ret;
> +
> +	ret = __verify_length(vb, b);
> +	if (ret < 0) {
> +		dprintk(1, "plane parameters verification failed: %d\n", ret);
> +		return ret;
> +	}
> +	vb->state = VB2_BUF_STATE_PREPARING;
> +	vbuf->timestamp.tv_sec = 0;
> +	vbuf->timestamp.tv_usec = 0;
> +	vbuf->sequence = 0;
> +
> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> +		if (b->memory == V4L2_MEMORY_USERPTR) {
> +			for (plane = 0; plane < vb->num_planes; ++plane) {
> +				planes[plane].m.userptr =
> +					b->m.planes[plane].m.userptr;
> +				planes[plane].length =
> +					b->m.planes[plane].length;
> +			}
> +		}
> +		if (b->memory == V4L2_MEMORY_DMABUF) {
> +			for (plane = 0; plane < vb->num_planes; ++plane) {
> +				planes[plane].m.fd =
> +					b->m.planes[plane].m.fd;
> +				planes[plane].length =
> +					b->m.planes[plane].length;
> +			}
> +		}
> +
> +		/* Fill in driver-provided information for OUTPUT types */
> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> +			/*
> +			 * Will have to go up to b->length when API starts
> +			 * accepting variable number of planes.
> +			 *
> +			 * If bytesused == 0 for the output buffer, then fall
> +			 * back to the full buffer size. In that case
> +			 * userspace clearly never bothered to set it and
> +			 * it's a safe assumption that they really meant to
> +			 * use the full plane sizes.
> +			 *
> +			 * Some drivers, e.g. old codec drivers, use bytesused == 0
> +			 * as a way to indicate that streaming is finished.
> +			 * In that case, the driver should use the
> +			 * allow_zero_bytesused flag to keep old userspace
> +			 * applications working.
> +			 */
> +			for (plane = 0; plane < vb->num_planes; ++plane) {
> +				struct vb2_plane *pdst = &planes[plane];
> +				struct v4l2_plane *psrc = &b->m.planes[plane];
> +
> +				if (psrc->bytesused == 0)
> +					vb2_warn_zero_bytesused(vb);
> +
> +				if (vb->vb2_queue->allow_zero_bytesused)
> +					pdst->bytesused = psrc->bytesused;
> +				else
> +					pdst->bytesused = psrc->bytesused ?
> +						psrc->bytesused : pdst->length;
> +				pdst->data_offset = psrc->data_offset;
> +			}
> +		}
> +	} else {
> +		/*
> +		 * Single-planar buffers do not use planes array,
> +		 * so fill in relevant v4l2_buffer struct fields instead.
> +		 * In videobuf we use our internal V4l2_planes struct for
> +		 * single-planar buffers as well, for simplicity.
> +		 *
> +		 * If bytesused == 0 for the output buffer, then fall back
> +		 * to the full buffer size as that's a sensible default.
> +		 *
> +		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
> +		 * a way to indicate that streaming is finished. In that case,
> +		 * the driver should use the allow_zero_bytesused flag to keep
> +		 * old userspace applications working.
> +		 */
> +		if (b->memory == V4L2_MEMORY_USERPTR) {
> +			planes[0].m.userptr = b->m.userptr;
> +			planes[0].length = b->length;
> +		}
> +
> +		if (b->memory == V4L2_MEMORY_DMABUF) {
> +			planes[0].m.fd = b->m.fd;
> +			planes[0].length = b->length;
> +		}
> +
> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> +			if (b->bytesused == 0)
> +				vb2_warn_zero_bytesused(vb);
> +
> +			if (vb->vb2_queue->allow_zero_bytesused)
> +				planes[0].bytesused = b->bytesused;
> +			else
> +				planes[0].bytesused = b->bytesused ?
> +					b->bytesused : planes[0].length;
> +		} else
> +			planes[0].bytesused = 0;
> +
> +	}
> +
> +	/* Zero flags that the vb2 core handles */
> +	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> +	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
> +			!V4L2_TYPE_IS_OUTPUT(b->type)) {
> +		/*
> +		 * Non-COPY timestamps and non-OUTPUT queues will get
> +		 * their timestamp and timestamp source flags from the
> +		 * queue.
> +		 */
> +		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> +	}
> +
> +	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> +		/*
> +		 * For output buffers mask out the timecode flag:
> +		 * this will be handled later in vb2_internal_qbuf().
> +		 * The 'field' is valid metadata for this output buffer
> +		 * and so that needs to be copied here.
> +		 */
> +		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
> +		vbuf->field = b->field;
> +	} else {
> +		/* Zero any output buffer flags as this is a capture buffer */
> +		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
> +	}
> +
> +	return 0;
> +}
> +
> +static int __fill_vb2_timestamp(struct vb2_buffer *vb, void *pb)
> +{
> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct vb2_queue *q = vb->vb2_queue;
> +
> +	/*
> +	 * For output buffers copy the timestamp if needed,
> +	 * and the timecode field and flag if needed.
> +	 */
> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY)
> +		vbuf->timestamp = b->timestamp;
> +	vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> +	if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> +		vbuf->timecode = b->timecode;
> +
> +	return 0;
> +};
> +
> +static int __is_last(struct vb2_buffer *vb)
> +{
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +
> +	return (vbuf->flags & V4L2_BUF_FLAG_LAST);
> +}
> +
> +const struct vb2_buf_ops v4l2_buf_ops = {
> +	.fill_user_buffer	= __fill_v4l2_buffer,
> +	.fill_vb2_buffer	= __fill_vb2_buffer,
> +	.fill_vb2_timestamp	= __fill_vb2_timestamp,
> +	.is_last		= __is_last,
> +};
> +
> +/**
> + * vb2_querybuf() - query video buffer information
> + * @q:		videobuf queue
> + * @b:		buffer struct passed from userspace to vidioc_querybuf handler
> + *		in driver
> + *
> + * Should be called from vidioc_querybuf ioctl handler in driver.
> + * This function will verify the passed v4l2_buffer structure and fill the
> + * relevant information for the userspace.
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_querybuf handler in driver.
> + */
> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +{
> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
> +			b->length, b->m.planes, "querybuf");
> +
> +	return ret ? ret : vb2_core_querybuf(q, b->index, b);
> +}
> +EXPORT_SYMBOL(vb2_querybuf);
> +
> +/**
> + * vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies
> + * the memory and type values.
> + * @q:		videobuf2 queue
> + * @req:	struct passed from userspace to vidioc_reqbufs handler
> + *		in driver
> + */
> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> +{
> +	int ret = vb2_verify_memory_type(q, req->memory, req->type);
> +
> +	if (ret)
> +		return ret;
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_core_reqbufs(q, req->memory, &req->count);
> +}
> +EXPORT_SYMBOL_GPL(vb2_reqbufs);
> +
> +/**
> + * vb2_create_bufs() - Wrapper for vb2_core_create_bufs() that also verifies
> + * the memory and type values.
> + * @q:		videobuf2 queue
> + * @create:	creation parameters, passed from userspace to vidioc_create_bufs
> + *		handler in driver
> + */
> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
> +{
> +	int ret = vb2_verify_memory_type(q, create->memory, create->format.type);
> +
> +	if (ret)
> +		return ret;
> +	if (create->count && vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +	return vb2_core_create_bufs(q, create->memory, &create->count, &create->format);
> +}
> +EXPORT_SYMBOL_GPL(vb2_create_bufs);
> +
> +/**
> + * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
> + * @q:		videobuf2 queue
> + * @b:		buffer structure passed from userspace to vidioc_prepare_buf
> + *		handler in driver
> + *
> + * Should be called from vidioc_prepare_buf ioctl handler of a driver.
> + * This function:
> + * 1) verifies the passed buffer,
> + * 2) calls buf_prepare callback in the driver (if provided), in which
> + *    driver-specific buffer initialization can be performed,
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_prepare_buf handler in driver.
> + */
> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
> +{
> +	int ret;
> +
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
> +			b->length, b->m.planes, "prepare_buf");
> +	if (ret)
> +		return ret;
> +
> +	if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
> +		/*
> +		 * If the format's field is ALTERNATE, then the buffer's field
> +		 * should be either TOP or BOTTOM, not ALTERNATE since that
> +		 * makes no sense. The driver has to know whether the
> +		 * buffer represents a top or a bottom field in order to
> +		 * program any DMA correctly. Using ALTERNATE is wrong, since
> +		 * that just says that it is either a top or a bottom field,
> +		 * but not which of the two it is.
> +		 */
> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
> +				"for an output buffer\n");
> +		return -EINVAL;
> +	}
> +
> +	return vb2_core_prepare_buf(q, b->index, b);
> +}
> +EXPORT_SYMBOL_GPL(vb2_prepare_buf);
> +
> +static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +{
> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
> +			b->length, b->m.planes, "qbuf");
> +	struct vb2_buffer *vb;
> +
> +	if (ret)
> +		return ret;
> +
> +	vb = q->bufs[b->index];
> +
> +	if (vb->state == VB2_BUF_STATE_DEQUEUED
> +			&& b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
> +				"for an output buffer\n");
> +		return -EINVAL;
> +	}
> +
> +	return ret ? ret : vb2_core_qbuf(q, b->index, b);
> +}
> +
> +/**
> + * vb2_qbuf() - Queue a buffer from userspace
> + * @q:		videobuf2 queue
> + * @b:		buffer structure passed from userspace to vidioc_qbuf handler
> + *		in driver
> + *
> + * Should be called from vidioc_qbuf ioctl handler of a driver.
> + * This function:
> + * 1) verifies the passed buffer,
> + * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
> + *    which driver-specific buffer initialization can be performed,
> + * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
> + *    callback for processing.
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_qbuf handler in driver.
> + */
> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_internal_qbuf(q, b);
> +}
> +EXPORT_SYMBOL_GPL(vb2_qbuf);
> +
> +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> +			bool nonblocking)
> +{
> +	if (b->type != q->type) {
> +		dprintk(1, "invalid buffer type\n");
> +		return -EINVAL;
> +	}
> +	return vb2_core_dqbuf(q, b, nonblocking);
> +}
> +
> +/**
> + * vb2_dqbuf() - Dequeue a buffer to the userspace
> + * @q:		videobuf2 queue
> + * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
> + *		in driver
> + * @nonblocking: if true, this call will not sleep waiting for a buffer if no
> + *		 buffers ready for dequeuing are present. Normally the driver
> + *		 would be passing (file->f_flags & O_NONBLOCK) here
> + *
> + * Should be called from vidioc_dqbuf ioctl handler of a driver.
> + * This function:
> + * 1) verifies the passed buffer,
> + * 2) calls buf_finish callback in the driver (if provided), in which
> + *    driver can perform any additional operations that may be required before
> + *    returning the buffer to userspace, such as cache sync,
> + * 3) the buffer struct members are filled with relevant information for
> + *    the userspace.
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_dqbuf handler in driver.
> + */
> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +	return vb2_internal_dqbuf(q, b, nonblocking);
> +}
> +EXPORT_SYMBOL_GPL(vb2_dqbuf);
> +
> +/**
> + * vb2_expbuf() - Export a buffer as a file descriptor
> + * @q:		videobuf2 queue
> + * @eb:		export buffer structure passed from userspace to vidioc_expbuf
> + *		handler in driver
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_expbuf handler in driver.
> + */
> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index,
> +				eb->plane, eb->flags);
> +}
> +EXPORT_SYMBOL_GPL(vb2_expbuf);
> +
> +static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> +{
> +	if (type != q->type) {
> +		dprintk(1, "invalid stream type\n");
> +		return -EINVAL;
> +	}
> +	return vb2_core_streamon(q);
> +}
> +
> +/**
> + * vb2_streamon - start streaming
> + * @q:		videobuf2 queue
> + * @type:	type argument passed from userspace to vidioc_streamon handler
> + *
> + * Should be called from vidioc_streamon handler of a driver.
> + * This function:
> + * 1) verifies current state
> + * 2) passes any previously queued buffers to the driver and starts streaming
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_streamon handler in the driver.
> + */
> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +	return vb2_internal_streamon(q, type);
> +}
> +EXPORT_SYMBOL_GPL(vb2_streamon);
> +
> +static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> +{
> +	if (type != q->type) {
> +		dprintk(1, "invalid stream type\n");
> +		return -EINVAL;
> +	}
> +	return vb2_core_streamoff(q);
> +}
> +
> +/**
> + * vb2_streamoff - stop streaming
> + * @q:		videobuf2 queue
> + * @type:	type argument passed from userspace to vidioc_streamoff handler
> + *
> + * Should be called from vidioc_streamoff handler of a driver.
> + * This function:
> + * 1) verifies current state,
> + * 2) stop streaming and dequeues any queued buffers, including those previously
> + *    passed to the driver (after waiting for the driver to finish).
> + *
> + * This call can be used for pausing playback.
> + * The return values from this function are intended to be directly returned
> + * from vidioc_streamoff handler in the driver
> + */
> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +	return vb2_internal_streamoff(q, type);
> +}
> +EXPORT_SYMBOL_GPL(vb2_streamoff);
> +
> +/**
> + * vb2_mmap() - map video buffers into application address space
> + * @q:		videobuf2 queue
> + * @vma:	vma passed to the mmap file operation handler in the driver
> + *
> + * Should be called from mmap file operation handler of a driver.
> + * This function maps one plane of one of the available video buffers to
> + * userspace. To map whole video memory allocated on reqbufs, this function
> + * has to be called once per each plane per each buffer previously allocated.
> + *
> + * When the userspace application calls mmap, it passes to it an offset returned
> + * to it earlier by the means of vidioc_querybuf handler. That offset acts as
> + * a "cookie", which is then used to identify the plane to be mapped.
> + * This function finds a plane with a matching offset and a mapping is performed
> + * by the means of a provided memory operation.
> + *
> + * The return values from this function are intended to be directly returned
> + * from the mmap handler in driver.
> + */
> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "mmap: file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_core_mmap(q, vma);
> +}
> +EXPORT_SYMBOL_GPL(vb2_mmap);
> +
> +static int __vb2_init_fileio(struct vb2_queue *q, int read);
> +static int __vb2_cleanup_fileio(struct vb2_queue *q);
> +
> +/**
> + * vb2_poll() - implements poll userspace operation
> + * @q:		videobuf2 queue
> + * @file:	file argument passed to the poll file operation handler
> + * @wait:	wait argument passed to the poll file operation handler
> + *
> + * This function implements poll file operation handler for a driver.
> + * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
> + * be informed that the file descriptor of a video device is available for
> + * reading.
> + * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
> + * will be reported as available for writing.
> + *
> + * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
> + * pending events.
> + *
> + * The return values from this function are intended to be directly returned
> + * from poll handler in driver.
> + */
> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> +{
> +	struct video_device *vfd = video_devdata(file);
> +	unsigned long req_events = poll_requested_events(wait);
> +	struct vb2_buffer *vb = NULL;
> +	unsigned int res = 0;
> +	unsigned long flags;
> +
> +	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> +		struct v4l2_fh *fh = file->private_data;
> +
> +		if (v4l2_event_pending(fh))
> +			res = POLLPRI;
> +		else if (req_events & POLLPRI)
> +			poll_wait(file, &fh->wait, wait);
> +	}
> +
> +	if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
> +		return res;
> +	if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
> +		return res;
> +
> +	/*
> +	 * Start file I/O emulator only if streaming API has not been used yet.
> +	 */
> +	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
> +		if (!q->is_output && (q->io_modes & VB2_READ) &&
> +				(req_events & (POLLIN | POLLRDNORM))) {
> +			if (__vb2_init_fileio(q, 1))
> +				return res | POLLERR;
> +		}
> +		if (q->is_output && (q->io_modes & VB2_WRITE) &&
> +				(req_events & (POLLOUT | POLLWRNORM))) {
> +			if (__vb2_init_fileio(q, 0))
> +				return res | POLLERR;
> +			/*
> +			 * Write to OUTPUT queue can be done immediately.
> +			 */
> +			return res | POLLOUT | POLLWRNORM;
> +		}
> +	}
> +
> +	/*
> +	 * There is nothing to wait for if the queue isn't streaming, or if the
> +	 * error flag is set.
> +	 */
> +	if (!vb2_is_streaming(q) || q->error)
> +		return res | POLLERR;
> +	/*
> +	 * For compatibility with vb1: if QBUF hasn't been called yet, then
> +	 * return POLLERR as well. This only affects capture queues, output
> +	 * queues will always initialize waiting_for_buffers to false.
> +	 */
> +	if (q->waiting_for_buffers)
> +		return res | POLLERR;
> +
> +	/*
> +	 * For output streams you can write as long as there are fewer buffers
> +	 * queued than there are buffers available.
> +	 */
> +	if (q->is_output && q->queued_count < q->num_buffers)
> +		return res | POLLOUT | POLLWRNORM;
> +
> +	if (list_empty(&q->done_list)) {
> +		/*
> +		 * If the last buffer was dequeued from a capture queue,
> +		 * return immediately. DQBUF will return -EPIPE.
> +		 */
> +		if (q->last_buffer_dequeued)
> +			return res | POLLIN | POLLRDNORM;
> +
> +		poll_wait(file, &q->done_wq, wait);
> +	}
> +
> +	/*
> +	 * Take first buffer available for dequeuing.
> +	 */
> +	spin_lock_irqsave(&q->done_lock, flags);
> +	if (!list_empty(&q->done_list))
> +		vb = list_first_entry(&q->done_list, struct vb2_buffer,
> +					done_entry);
> +	spin_unlock_irqrestore(&q->done_lock, flags);
> +
> +	if (vb && (vb->state == VB2_BUF_STATE_DONE
> +			|| vb->state == VB2_BUF_STATE_ERROR)) {
> +		return (q->is_output) ?
> +				res | POLLOUT | POLLWRNORM :
> +				res | POLLIN | POLLRDNORM;
> +	}
> +	return res;
> +}
> +EXPORT_SYMBOL_GPL(vb2_poll);
> +
> +/**
> + * vb2_queue_init() - initialize a videobuf2 queue
> + * @q:		videobuf2 queue; this structure should be allocated in driver
> + *
> + * The vb2_queue structure should be allocated by the driver. The driver is
> + * responsible of clearing it's content and setting initial values for some
> + * required entries before calling this function.
> + * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
> + * to the struct vb2_queue description in include/media/videobuf2-core.h
> + * for more information.
> + */
> +int vb2_queue_init(struct vb2_queue *q)
> +{
> +	if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
> +		|| WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
> +		|| WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
> +		return -EINVAL;
> +	/*
> +	 * Sanity check
> +	 */
> +	if (WARN_ON(!q)	|| WARN_ON(!q->type))
> +		return -EINVAL;
> +
> +	if (WARN_ON(q->timestamp_flags &
> +		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> +		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
> +		return -EINVAL;
> +
> +	/* Warn that the driver should choose an appropriate timestamp type */
> +	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> +		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
> +
> +	if (q->buf_struct_size == 0)
> +		q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
> +
> +	q->buf_ops = &v4l2_buf_ops;
> +	q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> +	q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
> +
> +	return vb2_core_queue_init(q);
> +}
> +EXPORT_SYMBOL_GPL(vb2_queue_init);
> +
> +/**
> + * vb2_queue_release() - stop streaming, release the queue and free memory
> + * @q:		videobuf2 queue
> + *
> + * This function stops streaming and performs necessary clean ups, including
> + * freeing video buffer memory. The driver is responsible for freeing
> + * the vb2_queue structure itself.
> + */
> +void vb2_queue_release(struct vb2_queue *q)
> +{
> +	__vb2_cleanup_fileio(q);
> +	vb2_core_queue_release(q);
> +}
> +EXPORT_SYMBOL_GPL(vb2_queue_release);
> +
> +/**
> + * struct vb2_fileio_buf - buffer context used by file io emulator
> + *
> + * vb2 provides a compatibility layer and emulator of file io (read and
> + * write) calls on top of streaming API. This structure is used for
> + * tracking context related to the buffers.
> + */
> +struct vb2_fileio_buf {
> +	void *vaddr;
> +	unsigned int size;
> +	unsigned int pos;
> +	unsigned int queued:1;
> +};
> +
> +/**
> + * struct vb2_fileio_data - queue context used by file io emulator
> + *
> + * @cur_index:	the index of the buffer currently being read from or
> + *		written to. If equal to q->num_buffers then a new buffer
> + *		must be dequeued.
> + * @initial_index: in the read() case all buffers are queued up immediately
> + *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
> + *		buffers. However, in the write() case no buffers are initially
> + *		queued, instead whenever a buffer is full it is queued up by
> + *		__vb2_perform_fileio(). Only once all available buffers have
> + *		been queued up will __vb2_perform_fileio() start to dequeue
> + *		buffers. This means that initially __vb2_perform_fileio()
> + *		needs to know what buffer index to use when it is queuing up
> + *		the buffers for the first time. That initial index is stored
> + *		in this field. Once it is equal to q->num_buffers all
> + *		available buffers have been queued and __vb2_perform_fileio()
> + *		should start the normal dequeue/queue cycle.
> + *
> + * vb2 provides a compatibility layer and emulator of file io (read and
> + * write) calls on top of streaming API. For proper operation it required
> + * this structure to save the driver state between each call of the read
> + * or write function.
> + */
> +struct vb2_fileio_data {
> +	struct v4l2_requestbuffers req;
> +	struct v4l2_plane p;
> +	struct v4l2_buffer b;
> +	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
> +	unsigned int cur_index;
> +	unsigned int initial_index;
> +	unsigned int q_count;
> +	unsigned int dq_count;
> +	unsigned read_once:1;
> +	unsigned write_immediately:1;
> +};
> +
> +/**
> + * __vb2_init_fileio() - initialize file io emulator
> + * @q:		videobuf2 queue
> + * @read:	mode selector (1 means read, 0 means write)
> + */
> +static int __vb2_init_fileio(struct vb2_queue *q, int read)
> +{
> +	struct vb2_fileio_data *fileio;
> +	int i, ret;
> +	unsigned int count = 0;
> +
> +	/*
> +	 * Sanity check
> +	 */
> +	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
> +			(!read && !(q->io_modes & VB2_WRITE))))
> +		return -EINVAL;
> +
> +	/*
> +	 * Check if device supports mapping buffers to kernel virtual space.
> +	 */
> +	if (!q->mem_ops->vaddr)
> +		return -EBUSY;
> +
> +	/*
> +	 * Check if streaming api has not been already activated.
> +	 */
> +	if (q->streaming || q->num_buffers > 0)
> +		return -EBUSY;
> +
> +	/*
> +	 * Start with count 1, driver can increase it in queue_setup()
> +	 */
> +	count = 1;
> +
> +	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, "
> +		"write_immediately %d\n",
> +		(read) ? "read" : "write", count, q->fileio_read_once,
> +		q->fileio_write_immediately);
> +
> +	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
> +	if (fileio == NULL)
> +		return -ENOMEM;
> +
> +	fileio->read_once = q->fileio_read_once;
> +	fileio->write_immediately = q->fileio_write_immediately;
> +
> +	/*
> +	 * Request buffers and use MMAP type to force driver
> +	 * to allocate buffers by itself.
> +	 */
> +	fileio->req.count = count;
> +	fileio->req.memory = V4L2_MEMORY_MMAP;
> +	fileio->req.type = q->type;
> +	q->fileio = fileio;
> +	ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
> +	if (ret)
> +		goto err_kfree;
> +
> +	/*
> +	 * Check if plane_count is correct
> +	 * (multiplane buffers are not supported).
> +	 */
> +	if (q->bufs[0]->num_planes != 1) {
> +		ret = -EBUSY;
> +		goto err_reqbufs;
> +	}
> +
> +	/*
> +	 * Get kernel address of each buffer.
> +	 */
> +	for (i = 0; i < q->num_buffers; i++) {
> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
> +		if (fileio->bufs[i].vaddr == NULL) {
> +			ret = -EINVAL;
> +			goto err_reqbufs;
> +		}
> +		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
> +	}
> +
> +	/*
> +	 * Read mode requires pre queuing of all buffers.
> +	 */
> +	if (read) {
> +		bool is_multiplanar = q->is_multiplanar;
> +
> +		/*
> +		 * Queue all buffers.
> +		 */
> +		for (i = 0; i < q->num_buffers; i++) {
> +			struct v4l2_buffer *b = &fileio->b;
> +
> +			memset(b, 0, sizeof(*b));
> +			b->type = q->type;
> +			if (is_multiplanar) {
> +				memset(&fileio->p, 0, sizeof(fileio->p));
> +				b->m.planes = &fileio->p;
> +				b->length = 1;
> +			}
> +			b->memory = q->memory;
> +			b->index = i;
> +			ret = vb2_internal_qbuf(q, b);
> +			if (ret)
> +				goto err_reqbufs;
> +			fileio->bufs[i].queued = 1;
> +		}
> +		/*
> +		 * All buffers have been queued, so mark that by setting
> +		 * initial_index to q->num_buffers
> +		 */
> +		fileio->initial_index = q->num_buffers;
> +		fileio->cur_index = q->num_buffers;
> +	}
> +
> +	/*
> +	 * Start streaming.
> +	 */
> +	ret = vb2_internal_streamon(q, q->type);
> +	if (ret)
> +		goto err_reqbufs;
> +
> +	return ret;
> +
> +err_reqbufs:
> +	fileio->req.count = 0;
> +	vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
> +
> +err_kfree:
> +	q->fileio = NULL;
> +	kfree(fileio);
> +	return ret;
> +}
> +
> +/**
> + * __vb2_cleanup_fileio() - free resourced used by file io emulator
> + * @q:		videobuf2 queue
> + */
> +static int __vb2_cleanup_fileio(struct vb2_queue *q)
> +{
> +	struct vb2_fileio_data *fileio = q->fileio;
> +
> +	if (fileio) {
> +		vb2_internal_streamoff(q, q->type);
> +		q->fileio = NULL;
> +		fileio->req.count = 0;
> +		vb2_reqbufs(q, &fileio->req);
> +		kfree(fileio);
> +		dprintk(3, "file io emulator closed\n");
> +	}
> +	return 0;
> +}
> +
> +/**
> + * __vb2_perform_fileio() - perform a single file io (read or write) operation
> + * @q:		videobuf2 queue
> + * @data:	pointed to target userspace buffer
> + * @count:	number of bytes to read or write
> + * @ppos:	file handle position tracking pointer
> + * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
> + * @read:	access mode selector (1 means read, 0 means write)
> + */
> +static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data,
> +		size_t count, loff_t *ppos, int nonblock, int read)
> +{
> +	struct vb2_fileio_data *fileio;
> +	struct vb2_fileio_buf *buf;
> +	bool is_multiplanar = q->is_multiplanar;
> +	/*
> +	 * When using write() to write data to an output video node the vb2 core
> +	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
> +	 * else is able to provide this information with the write() operation.
> +	 */
> +	bool set_timestamp = !read &&
> +		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> +		V4L2_BUF_FLAG_TIMESTAMP_COPY;
> +	int ret, index;
> +
> +	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
> +		read ? "read" : "write", (long)*ppos, count,
> +		nonblock ? "non" : "");
> +
> +	if (!data)
> +		return -EINVAL;
> +
> +	/*
> +	 * Initialize emulator on first call.
> +	 */
> +	if (!vb2_fileio_is_active(q)) {
> +		ret = __vb2_init_fileio(q, read);
> +		dprintk(3, "vb2_init_fileio result: %d\n", ret);
> +		if (ret)
> +			return ret;
> +	}
> +	fileio = q->fileio;
> +
> +	/*
> +	 * Check if we need to dequeue the buffer.
> +	 */
> +	index = fileio->cur_index;
> +	if (index >= q->num_buffers) {
> +		/*
> +		 * Call vb2_dqbuf to get buffer back.
> +		 */
> +		memset(&fileio->b, 0, sizeof(fileio->b));
> +		fileio->b.type = q->type;
> +		fileio->b.memory = q->memory;
> +		if (is_multiplanar) {
> +			memset(&fileio->p, 0, sizeof(fileio->p));
> +			fileio->b.m.planes = &fileio->p;
> +			fileio->b.length = 1;
> +		}
> +		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
> +		dprintk(5, "vb2_dqbuf result: %d\n", ret);
> +		if (ret)
> +			return ret;
> +		fileio->dq_count += 1;
> +
> +		fileio->cur_index = index = fileio->b.index;
> +		buf = &fileio->bufs[index];
> +
> +		/*
> +		 * Get number of bytes filled by the driver
> +		 */
> +		buf->pos = 0;
> +		buf->queued = 0;
> +		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> +				 : vb2_plane_size(q->bufs[index], 0);
> +
> +		/*
> +		 * Compensate for data_offset on read
> +		 * in the multiplanar case.
> +		 */
> +		if (is_multiplanar && read &&
> +			fileio->b.m.planes[0].data_offset < buf->size) {
> +			buf->pos = fileio->b.m.planes[0].data_offset;
> +			buf->size -= buf->pos;
> +		}
> +	} else {
> +		buf = &fileio->bufs[index];
> +	}
> +
> +	/*
> +	 * Limit count on last few bytes of the buffer.
> +	 */
> +	if (buf->pos + count > buf->size) {
> +		count = buf->size - buf->pos;
> +		dprintk(5, "reducing read count: %zd\n", count);
> +	}
> +
> +	/*
> +	 * Transfer data to userspace.
> +	 */
> +	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
> +		count, index, buf->pos);
> +	if (read)
> +		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
> +	else
> +		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
> +	if (ret) {
> +		dprintk(3, "error copying data\n");
> +		return -EFAULT;
> +	}
> +
> +	/*
> +	 * Update counters.
> +	 */
> +	buf->pos += count;
> +	*ppos += count;
> +
> +	/*
> +	 * Queue next buffer if required.
> +	 */
> +	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
> +		/*
> +		 * Check if this is the last buffer to read.
> +		 */
> +		if (read && fileio->read_once && fileio->dq_count == 1) {
> +			dprintk(3, "read limit reached\n");
> +			return __vb2_cleanup_fileio(q);
> +		}
> +
> +		/*
> +		 * Call vb2_qbuf and give buffer to the driver.
> +		 */
> +		memset(&fileio->b, 0, sizeof(fileio->b));
> +		fileio->b.type = q->type;
> +		fileio->b.memory = q->memory;
> +		fileio->b.index = index;
> +		fileio->b.bytesused = buf->pos;
> +		if (is_multiplanar) {
> +			memset(&fileio->p, 0, sizeof(fileio->p));
> +			fileio->p.bytesused = buf->pos;
> +			fileio->b.m.planes = &fileio->p;
> +			fileio->b.length = 1;
> +		}
> +		if (set_timestamp)
> +			v4l2_get_timestamp(&fileio->b.timestamp);
> +		ret = vb2_internal_qbuf(q, &fileio->b);
> +		dprintk(5, "vb2_dbuf result: %d\n", ret);
> +		if (ret)
> +			return ret;
> +
> +		/*
> +		 * Buffer has been queued, update the status
> +		 */
> +		buf->pos = 0;
> +		buf->queued = 1;
> +		buf->size = vb2_plane_size(q->bufs[index], 0);
> +		fileio->q_count += 1;
> +		/*
> +		 * If we are queuing up buffers for the first time, then
> +		 * increase initial_index by one.
> +		 */
> +		if (fileio->initial_index < q->num_buffers)
> +			fileio->initial_index++;
> +		/*
> +		 * The next buffer to use is either a buffer that's going to be
> +		 * queued for the first time (initial_index < q->num_buffers)
> +		 * or it is equal to q->num_buffers, meaning that the next
> +		 * time we need to dequeue a buffer since we've now queued up
> +		 * all the 'first time' buffers.
> +		 */
> +		fileio->cur_index = fileio->initial_index;
> +	}
> +
> +	/*
> +	 * Return proper number of bytes processed.
> +	 */
> +	if (ret == 0)
> +		ret = count;
> +	return ret;
> +}
> +
> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> +		loff_t *ppos, int nonblocking)
> +{
> +	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
> +}
> +EXPORT_SYMBOL_GPL(vb2_read);
> +
> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> +		loff_t *ppos, int nonblocking)
> +{
> +	return __vb2_perform_fileio(q, (char __user *) data, count,
> +							ppos, nonblocking, 0);
> +}
> +EXPORT_SYMBOL_GPL(vb2_write);
> +
> +struct vb2_threadio_data {
> +	struct task_struct *thread;
> +	vb2_thread_fnc fnc;
> +	void *priv;
> +	bool stop;
> +};
> +
> +static int vb2_thread(void *data)
> +{
> +	struct vb2_queue *q = data;
> +	struct vb2_threadio_data *threadio = q->threadio;
> +	struct vb2_fileio_data *fileio = q->fileio;
> +	bool set_timestamp = false;
> +	int prequeue = 0;
> +	int index = 0;
> +	int ret = 0;
> +
> +	if (q->is_output) {
> +		prequeue = q->num_buffers;
> +		set_timestamp =
> +			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY;
> +	}
> +
> +	set_freezable();
> +
> +	for (;;) {
> +		struct vb2_buffer *vb;
> +
> +		/*
> +		 * Call vb2_dqbuf to get buffer back.
> +		 */
> +		memset(&fileio->b, 0, sizeof(fileio->b));
> +		fileio->b.type = q->type;
> +		fileio->b.memory = q->memory;
> +		if (prequeue) {
> +			fileio->b.index = index++;
> +			prequeue--;
> +		} else {
> +			call_void_qop(q, wait_finish, q);
> +			if (!threadio->stop)
> +				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
> +			call_void_qop(q, wait_prepare, q);
> +			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
> +		}
> +		if (ret || threadio->stop)
> +			break;
> +		try_to_freeze();
> +
> +		vb = q->bufs[fileio->b.index];
> +		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
> +			if (threadio->fnc(vb, threadio->priv))
> +				break;
> +		call_void_qop(q, wait_finish, q);
> +		if (set_timestamp)
> +			v4l2_get_timestamp(&fileio->b.timestamp);
> +		if (!threadio->stop)
> +			ret = vb2_internal_qbuf(q, &fileio->b);
> +		call_void_qop(q, wait_prepare, q);
> +		if (ret || threadio->stop)
> +			break;
> +	}
> +
> +	/* Hmm, linux becomes *very* unhappy without this ... */
> +	while (!kthread_should_stop()) {
> +		set_current_state(TASK_INTERRUPTIBLE);
> +		schedule();
> +	}
> +	return 0;
> +}
> +
> +/*
> + * This function should not be used for anything else but the videobuf2-dvb
> + * support. If you think you have another good use-case for this, then please
> + * contact the linux-media mailinglist first.
> + */
> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> +			const char *thread_name)
> +{
> +	struct vb2_threadio_data *threadio;
> +	int ret = 0;
> +
> +	if (q->threadio)
> +		return -EBUSY;
> +	if (vb2_is_busy(q))
> +		return -EBUSY;
> +	if (WARN_ON(q->fileio))
> +		return -EBUSY;
> +
> +	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
> +	if (threadio == NULL)
> +		return -ENOMEM;
> +	threadio->fnc = fnc;
> +	threadio->priv = priv;
> +
> +	ret = __vb2_init_fileio(q, !q->is_output);
> +	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
> +	if (ret)
> +		goto nomem;
> +	q->threadio = threadio;
> +	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
> +	if (IS_ERR(threadio->thread)) {
> +		ret = PTR_ERR(threadio->thread);
> +		threadio->thread = NULL;
> +		goto nothread;
> +	}
> +	return 0;
> +
> +nothread:
> +	__vb2_cleanup_fileio(q);
> +nomem:
> +	kfree(threadio);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(vb2_thread_start);
> +
> +int vb2_thread_stop(struct vb2_queue *q)
> +{
> +	struct vb2_threadio_data *threadio = q->threadio;
> +	int err;
> +
> +	if (threadio == NULL)
> +		return 0;
> +	threadio->stop = true;
> +	/* Wake up all pending sleeps in the thread */
> +	vb2_queue_error(q);
> +	err = kthread_stop(threadio->thread);
> +	__vb2_cleanup_fileio(q);
> +	threadio->thread = NULL;
> +	kfree(threadio);
> +	q->threadio = NULL;
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(vb2_thread_stop);
> +
> +/*
> + * The following functions are not part of the vb2 core API, but are helper
> + * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
> + * and struct vb2_ops.
> + * They contain boilerplate code that most if not all drivers have to do
> + * and so they simplify the driver code.
> + */
> +
> +/* The queue is busy if there is a owner and you are not that owner. */
> +static inline
> +bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
> +{
> +	return vdev->queue->owner && vdev->queue->owner != file->private_data;
> +}
> +
> +/* vb2 ioctl helpers */
> +
> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
> +			  struct v4l2_requestbuffers *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
> +
> +	if (res)
> +		return res;
> +	if (vb2_fileio_is_active(vdev->queue))
> +		return -EBUSY;
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count);
> +	/* If count == 0, then the owner has released all buffers and he
> +	   is no longer owner of the queue. Otherwise we have a new owner. */
> +	if (res == 0)
> +		vdev->queue->owner = p->count ? file->private_data : NULL;
> +	return res;
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
> +
> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
> +			  struct v4l2_create_buffers *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	int res = vb2_verify_memory_type(vdev->queue,
> +				p->memory, p->format.type);
> +
> +	if (vb2_fileio_is_active(vdev->queue))
> +		return -EBUSY;
> +	p->index = vdev->queue->num_buffers;
> +	/* If count == 0, then just check if memory and type are valid.
> +	   Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. */
> +	if (p->count == 0)
> +		return res != -EBUSY ? res : 0;
> +	if (res)
> +		return res;
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	res = vb2_core_create_bufs(vdev->queue,
> +				p->memory, &p->count, &p->format);
> +	if (res == 0)
> +		vdev->queue->owner = file->private_data;
> +	return res;
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
> +
> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> +			  struct v4l2_buffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_prepare_buf(vdev->queue, p);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
> +
> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
> +	return vb2_querybuf(vdev->queue, p);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
> +
> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_qbuf(vdev->queue, p);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
> +
> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
> +
> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_streamon(vdev->queue, i);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
> +
> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_streamoff(vdev->queue, i);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
> +
> +int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_expbuf(vdev->queue, p);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
> +
> +/* v4l2_file_operations helpers */
> +
> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_fileio_is_active(vdev->queue)) {
> +		dprintk(1, "mmap: file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_mmap(vdev->queue, vma);
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_mmap);
> +
> +int _vb2_fop_release(struct file *file, struct mutex *lock)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (lock)
> +		mutex_lock(lock);
> +	if (file->private_data == vdev->queue->owner) {
> +		vb2_queue_release(vdev->queue);
> +		vdev->queue->owner = NULL;
> +	}
> +	if (lock)
> +		mutex_unlock(lock);
> +	return v4l2_fh_release(file);
> +}
> +EXPORT_SYMBOL_GPL(_vb2_fop_release);
> +
> +int vb2_fop_release(struct file *file)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> +
> +	return _vb2_fop_release(file, lock);
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_release);
> +
> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> +		size_t count, loff_t *ppos)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> +	int err = -EBUSY;
> +
> +	if (!(vdev->queue->io_modes & VB2_WRITE))
> +		return -EINVAL;
> +	if (lock && mutex_lock_interruptible(lock))
> +		return -ERESTARTSYS;
> +	if (vb2_queue_is_busy(vdev, file))
> +		goto exit;
> +	err = vb2_write(vdev->queue, buf, count, ppos,
> +			file->f_flags & O_NONBLOCK);
> +	if (vdev->queue->fileio)
> +		vdev->queue->owner = file->private_data;
> +exit:
> +	if (lock)
> +		mutex_unlock(lock);
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_write);
> +
> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
> +		size_t count, loff_t *ppos)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> +	int err = -EBUSY;
> +
> +	if (!(vdev->queue->io_modes & VB2_READ))
> +		return -EINVAL;
> +	if (lock && mutex_lock_interruptible(lock))
> +		return -ERESTARTSYS;
> +	if (vb2_queue_is_busy(vdev, file))
> +		goto exit;
> +	err = vb2_read(vdev->queue, buf, count, ppos,
> +			file->f_flags & O_NONBLOCK);
> +	if (vdev->queue->fileio)
> +		vdev->queue->owner = file->private_data;
> +exit:
> +	if (lock)
> +		mutex_unlock(lock);
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_read);
> +
> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	struct vb2_queue *q = vdev->queue;
> +	struct mutex *lock = q->lock ? q->lock : vdev->lock;
> +	unsigned res;
> +	void *fileio;
> +
> +	/*
> +	 * If this helper doesn't know how to lock, then you shouldn't be using
> +	 * it but you should write your own.
> +	 */
> +	WARN_ON(!lock);
> +
> +	if (lock && mutex_lock_interruptible(lock))
> +		return POLLERR;
> +
> +	fileio = q->fileio;
> +
> +	res = vb2_poll(vdev->queue, file, wait);
> +
> +	/* If fileio was started, then we have a new queue owner. */
> +	if (!fileio && q->fileio)
> +		q->owner = file->private_data;
> +	if (lock)
> +		mutex_unlock(lock);
> +	return res;
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_poll);
> +
> +#ifndef CONFIG_MMU
> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> +		unsigned long len, unsigned long pgoff, unsigned long flags)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
> +#endif
> +
> +/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
> +
> +void vb2_ops_wait_prepare(struct vb2_queue *vq)
> +{
> +	mutex_unlock(vq->lock);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
> +
> +void vb2_ops_wait_finish(struct vb2_queue *vq)
> +{
> +	mutex_lock(vq->lock);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
> +
>  MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
>  MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
>  MODULE_LICENSE("GPL");
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index 09d7529..4044bed 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -15,9 +15,18 @@
>  #include <linux/mm_types.h>
>  #include <linux/mutex.h>
>  #include <linux/poll.h>
> -#include <linux/videodev2.h>
>  #include <linux/dma-buf.h>
>  
> +#define VB2_MAX_FRAME	(32)
> +#define VB2_MAX_PLANES	(8)
> +
> +enum vb2_memory {
> +	VB2_MEMORY_UNKNOWN	= 0,
> +	VB2_MEMORY_MMAP		= 1,
> +	VB2_MEMORY_USERPTR	= 2,
> +	VB2_MEMORY_DMABUF	= 4,
> +};
> +
>  struct vb2_alloc_ctx;
>  struct vb2_fileio_data;
>  struct vb2_threadio_data;
> @@ -198,7 +207,7 @@ struct vb2_buffer {
>  	unsigned int		type;
>  	unsigned int		memory;
>  	unsigned int		num_planes;
> -	struct vb2_plane	planes[VIDEO_MAX_PLANES];
> +	struct vb2_plane	planes[VB2_MAX_PLANES];
>  
>  #ifdef CONFIG_VIDEO_ADV_DEBUG
>  	/*
> @@ -330,18 +339,24 @@ struct vb2_ops {
>  	void (*buf_queue)(struct vb2_buffer *vb);
>  };
>  
> -struct v4l2_fh;
> +struct vb2_buf_ops {
> +	int (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
> +	int (*fill_vb2_buffer)(struct vb2_buffer *vb, void *pb,
> +				struct vb2_plane *planes);
> +	int (*fill_vb2_timestamp)(struct vb2_buffer *vb, void *pb);
> +	int (*is_last)(struct vb2_buffer *vb);
> +};
>  
>  /**
>   * struct vb2_queue - a videobuf queue
>   *
> - * @type:	queue type (see V4L2_BUF_TYPE_* in linux/videodev2.h
> + * @type:	queue type (see VB2_BUF_TYPE_*)
>   * @io_modes:	supported io methods (see vb2_io_modes enum)
>   * @fileio_read_once:		report EOF after reading the first buffer
>   * @fileio_write_immediately:	queue buffer after each write() call
>   * @allow_zero_bytesused:	allow bytesused == 0 to be passed to the driver
>   * @lock:	pointer to a mutex that protects the vb2_queue struct. The
> - *		driver can set this to a mutex to let the v4l2 core serialize
> + *		driver can set this to a mutex to let the vb2 core serialize
>   *		the queuing ioctls. If the driver wants to handle locking
>   *		itself, then this should be set to NULL. This lock is not used
>   *		by the videobuf2 core API.
> @@ -351,10 +366,13 @@ struct v4l2_fh;
>   *		drivers to easily associate an owner filehandle with the queue.
>   * @ops:	driver-specific callbacks
>   * @mem_ops:	memory allocator specific callbacks
> + * @buf_ops:	callbacks to deliver buffer information
> + *		between user-space and kernel-space
>   * @drv_priv:	driver private data
>   * @buf_struct_size: size of the driver-specific buffer structure;
>   *		"0" indicates the driver doesn't want to use a custom buffer
> - *		structure type, so sizeof(struct vb2_buffer) will is used
> + *		structure type, so, sizeof(struct vb2_v4l2_buffer) will is used
> + *		in case of v4l2.
>   * @timestamp_flags: Timestamp flags; V4L2_BUF_FLAG_TIMESTAMP_* and
>   *		V4L2_BUF_FLAG_TSTAMP_SRC_*
>   * @gfp_flags:	additional gfp flags used when allocating the buffers.
> @@ -385,6 +403,8 @@ struct v4l2_fh;
>   * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
>   *		buffers. Only set for capture queues if qbuf has not yet been
>   *		called since poll() needs to return POLLERR in that situation.
> + * @is_multiplanar: set if buffer type is multiplanar
> + * @is_output:	set if buffer type is output
>   * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
>   *		last decoded buffer was already dequeued. Set for capture queues
>   *		when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
> @@ -399,10 +419,12 @@ struct vb2_queue {
>  	unsigned			allow_zero_bytesused:1;
>  
>  	struct mutex			*lock;
> -	struct v4l2_fh			*owner;
> +	void				*owner;
>  
>  	const struct vb2_ops		*ops;
>  	const struct vb2_mem_ops	*mem_ops;
> +	const struct vb2_buf_ops	*buf_ops;
> +
>  	void				*drv_priv;
>  	unsigned int			buf_struct_size;
>  	u32				timestamp_flags;
> @@ -412,7 +434,7 @@ struct vb2_queue {
>  	/* private: internal use only */
>  	struct mutex			mmap_lock;
>  	unsigned int			memory;
> -	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
> +	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
>  	unsigned int			num_buffers;
>  
>  	struct list_head		queued_list;
> @@ -423,13 +445,15 @@ struct vb2_queue {
>  	spinlock_t			done_lock;
>  	wait_queue_head_t		done_wq;
>  
> -	void				*alloc_ctx[VIDEO_MAX_PLANES];
> -	unsigned int			plane_sizes[VIDEO_MAX_PLANES];
> +	void				*alloc_ctx[VB2_MAX_PLANES];
> +	unsigned int			plane_sizes[VB2_MAX_PLANES];
>  
>  	unsigned int			streaming:1;
>  	unsigned int			start_streaming_called:1;
>  	unsigned int			error:1;
>  	unsigned int			waiting_for_buffers:1;
> +	unsigned int			is_multiplanar:1;
> +	unsigned int			is_output:1;
>  	unsigned int			last_buffer_dequeued:1;
>  
>  	struct vb2_fileio_data		*fileio;
> @@ -455,25 +479,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
>  void vb2_discard_done(struct vb2_queue *q);
>  int vb2_wait_for_all_buffers(struct vb2_queue *q);
>  
> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
> -
> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
> -
> -int __must_check vb2_queue_init(struct vb2_queue *q);
> -
> -void vb2_queue_release(struct vb2_queue *q);
>  void vb2_queue_error(struct vb2_queue *q);
> -
> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
> -
> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
> -
> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
>  #ifndef CONFIG_MMU
>  unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  				    unsigned long addr,
> @@ -481,41 +487,6 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  				    unsigned long pgoff,
>  				    unsigned long flags);
>  #endif
> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> -		loff_t *ppos, int nonblock);
> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> -		loff_t *ppos, int nonblock);
> -
> -/*
> - * vb2_thread_fnc - callback function for use with vb2_thread
> - *
> - * This is called whenever a buffer is dequeued in the thread.
> - */
> -typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
> -
> -/**
> - * vb2_thread_start() - start a thread for the given queue.
> - * @q:		videobuf queue
> - * @fnc:	callback function
> - * @priv:	priv pointer passed to the callback function
> - * @thread_name:the name of the thread. This will be prefixed with "vb2-".
> - *
> - * This starts a thread that will queue and dequeue until an error occurs
> - * or @vb2_thread_stop is called.
> - *
> - * This function should not be used for anything else but the videobuf2-dvb
> - * support. If you think you have another good use-case for this, then please
> - * contact the linux-media mailinglist first.
> - */
> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> -		     const char *thread_name);
> -
> -/**
> - * vb2_thread_stop() - stop the thread for the given queue.
> - * @q:		videobuf queue
> - */
> -int vb2_thread_stop(struct vb2_queue *q);
>  
>  /**
>   * vb2_is_streaming() - return streaming status of the queue
> @@ -527,23 +498,6 @@ static inline bool vb2_is_streaming(struct vb2_queue *q)
>  }
>  
>  /**
> - * vb2_fileio_is_active() - return true if fileio is active.
> - * @q:		videobuf queue
> - *
> - * This returns true if read() or write() is used to stream the data
> - * as opposed to stream I/O. This is almost never an important distinction,
> - * except in rare cases. One such case is that using read() or write() to
> - * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
> - * is no way you can pass the field information of each buffer to/from
> - * userspace. A driver that supports this field format should check for
> - * this in the queue_setup op and reject it if this function returns true.
> - */
> -static inline bool vb2_fileio_is_active(struct vb2_queue *q)
> -{
> -	return q->fileio;
> -}
> -
> -/**
>   * vb2_is_busy() - return busy status of the queue
>   * @q:		videobuf queue
>   *
> @@ -620,47 +574,4 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q)
>  	q->last_buffer_dequeued = false;
>  }
>  
> -/*
> - * The following functions are not part of the vb2 core API, but are simple
> - * helper functions that you can use in your struct v4l2_file_operations,
> - * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock
> - * or video_device->lock is set, and they will set and test vb2_queue->owner
> - * to check if the calling filehandle is permitted to do the queuing operation.
> - */
> -
> -/* struct v4l2_ioctl_ops helpers */
> -
> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
> -			  struct v4l2_requestbuffers *p);
> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
> -			  struct v4l2_create_buffers *p);
> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> -			  struct v4l2_buffer *p);
> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
> -int vb2_ioctl_expbuf(struct file *file, void *priv,
> -	struct v4l2_exportbuffer *p);
> -
> -/* struct v4l2_file_operations helpers */
> -
> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
> -int vb2_fop_release(struct file *file);
> -int _vb2_fop_release(struct file *file, struct mutex *lock);
> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> -		size_t count, loff_t *ppos);
> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
> -		size_t count, loff_t *ppos);
> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
> -#ifndef CONFIG_MMU
> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> -		unsigned long len, unsigned long pgoff, unsigned long flags);
> -#endif
> -
> -/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
> -
> -void vb2_ops_wait_prepare(struct vb2_queue *vq);
> -void vb2_ops_wait_finish(struct vb2_queue *vq);
>  #endif /* _MEDIA_VIDEOBUF2_CORE_H */
> diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
> index fc2dbe9..790cb7a 100644
> --- a/include/media/videobuf2-v4l2.h
> +++ b/include/media/videobuf2-v4l2.h
> @@ -40,4 +40,120 @@ struct vb2_v4l2_buffer {
>  #define to_vb2_v4l2_buffer(vb) \
>  	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
>  
> +
> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
> +
> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
> +
> +int __must_check vb2_queue_init(struct vb2_queue *q);
> +
> +void vb2_queue_release(struct vb2_queue *q);
> +
> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
> +
> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> +		loff_t *ppos, int nonblock);
> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> +		loff_t *ppos, int nonblock);
> +
> +/*
> + * vb2_thread_fnc - callback function for use with vb2_thread
> + *
> + * This is called whenever a buffer is dequeued in the thread.
> + */
> +typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
> +
> +/**
> + * vb2_thread_start() - start a thread for the given queue.
> + * @q:		videobuf queue
> + * @fnc:	callback function
> + * @priv:	priv pointer passed to the callback function
> + * @thread_name:the name of the thread. This will be prefixed with "vb2-".
> + *
> + * This starts a thread that will queue and dequeue until an error occurs
> + * or @vb2_thread_stop is called.
> + *
> + * This function should not be used for anything else but the videobuf2-dvb
> + * support. If you think you have another good use-case for this, then please
> + * contact the linux-media mailinglist first.
> + */
> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> +		     const char *thread_name);
> +
> +/**
> + * vb2_thread_stop() - stop the thread for the given queue.
> + * @q:		videobuf queue
> + */
> +int vb2_thread_stop(struct vb2_queue *q);
> +
> +/**
> + * vb2_fileio_is_active() - return true if fileio is active.
> + * @q:		videobuf queue
> + *
> + * This returns true if read() or write() is used to stream the data
> + * as opposed to stream I/O. This is almost never an important distinction,
> + * except in rare cases. One such case is that using read() or write() to
> + * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
> + * is no way you can pass the field information of each buffer to/from
> + * userspace. A driver that supports this field format should check for
> + * this in the queue_setup op and reject it if this function returns true.
> + */
> +static inline bool vb2_fileio_is_active(struct vb2_queue *q)
> +{
> +	return q->fileio;
> +}
> +
> +/*
> + * The following functions are not part of the vb2 core API, but are simple
> + * helper functions that you can use in your struct v4l2_file_operations,
> + * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize
> + * if vb2_queue->lock or video_device->lock is set, and they will set
> + * and test vb2_queue->owner to check if the calling filehandle is permitted
> + * to do the queuing operation.
> + */
> +
> +/* struct v4l2_ioctl_ops helpers */
> +
> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
> +			  struct v4l2_requestbuffers *p);
> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
> +			  struct v4l2_create_buffers *p);
> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> +			  struct v4l2_buffer *p);
> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
> +int vb2_ioctl_expbuf(struct file *file, void *priv,
> +	struct v4l2_exportbuffer *p);
> +
> +/* struct v4l2_file_operations helpers */
> +
> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
> +int vb2_fop_release(struct file *file);
> +int _vb2_fop_release(struct file *file, struct mutex *lock);
> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> +		size_t count, loff_t *ppos);
> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
> +		size_t count, loff_t *ppos);
> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
> +#ifndef CONFIG_MMU
> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> +		unsigned long len, unsigned long pgoff, unsigned long flags);
> +#endif
> +
> +/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
> +
> +void vb2_ops_wait_prepare(struct vb2_queue *vq);
> +void vb2_ops_wait_finish(struct vb2_queue *vq);
> +
>  #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
> diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
> index b015b38..f31b258 100644
> --- a/include/trace/events/v4l2.h
> +++ b/include/trace/events/v4l2.h
> @@ -5,6 +5,7 @@
>  #define _TRACE_V4L2_H
>  
>  #include <linux/tracepoint.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  /* Enums require being exported to userspace, for user tool parsing */
>  #undef EM
> @@ -203,7 +204,8 @@ DECLARE_EVENT_CLASS(vb2_event_class,
>  
>  	TP_fast_assign(
>  		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> -		__entry->minor = q->owner ? q->owner->vdev->minor : -1;
> +		struct v4l2_fh *owner = (struct v4l2_fh *) q->owner;
> +		__entry->minor = owner ? owner->vdev->minor : -1;
>  		__entry->queued_count = q->queued_count;
>  		__entry->owned_by_drv_count =
>  			atomic_read(&q->owned_by_drv_count);

Regards,
Mauro

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer
  2015-08-27 10:28   ` Mauro Carvalho Chehab
@ 2015-08-28  1:26     ` Junghak Sung
  2015-08-28  9:09       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 23+ messages in thread
From: Junghak Sung @ 2015-08-28  1:26 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon


Hello Mauro,

First of all, thank you for your detailed review.


On 08/27/2015 07:28 PM, Mauro Carvalho Chehab wrote:
> Em Wed, 26 Aug 2015 20:59:29 +0900
> Junghak Sung <jh1009.sung@samsung.com> escreveu:
>
>> Remove v4l2-specific stuff from struct vb2_buffer and add member variables
>> related with buffer management.
>>
>> struct vb2_plane {
>>          <snip>
>>          /* plane information */
>>          unsigned int            bytesused;
>>          unsigned int            length;
>>          union {
>>                  unsigned int    offset;
>>                  unsigned long   userptr;
>>                  int             fd;
>>          } m;
>>          unsigned int            data_offset;
>> }
>>
>> struct vb2_buffer {
>>          <snip>
>>          /* buffer information */
>>          unsigned int            num_planes;
>>          unsigned int            index;
>>          unsigned int            type;
>>          unsigned int            memory;
>>
>>          struct vb2_plane        planes[VIDEO_MAX_PLANES];
>>          <snip>
>> };
>>
>> And create struct vb2_v4l2_buffer as container buffer for v4l2 use.
>>
>> struct vb2_v4l2_buffer {
>>          struct vb2_buffer       vb2_buf;
>>
>>          __u32                   flags;
>>          __u32                   field;
>>          struct timeval          timestamp;
>>          struct v4l2_timecode    timecode;
>>          __u32                   sequence;
>> };
>
> The comments seemed a little hard for me to read, but the changes
> look ok.
>

Ok, I will modify these comments more clearly at next round.

> I made some comments mostly regarding to documentation. See below.
>
>> This patch includes only changes inside of videobuf2. So, it is required to
>> modify all device drivers which use videobuf2.
>
> So, in practice, we need to fold both patches 2 and 3 when merging upstream,
> to avoid breaking git bisectability.
>

I'm sorry, but I can not understand the meaning of "fold both patches".
Would you please explain more detailed what should I do at next round.
If these two patches are get together to one patch, the size will
be over 300KB, which causes a size problem to send it to ML.

>>
>> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
>> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
>> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>> Acked-by: Inki Dae <inki.dae@samsung.com>
>> ---
>>   drivers/media/v4l2-core/videobuf2-core.c |  324 +++++++++++++++++-------------
>>   include/media/videobuf2-core.h           |   50 ++---
>>   include/media/videobuf2-v4l2.h           |   26 +++
>>   3 files changed, 236 insertions(+), 164 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
>> index ab00ea0..9266d50 100644
>> --- a/drivers/media/v4l2-core/videobuf2-core.c
>> +++ b/drivers/media/v4l2-core/videobuf2-core.c
>> @@ -35,10 +35,10 @@
>>   static int debug;
>>   module_param(debug, int, 0644);
>>
>> -#define dprintk(level, fmt, arg...)					      \
>> -	do {								      \
>> -		if (debug >= level)					      \
>> -			pr_info("vb2: %s: " fmt, __func__, ## arg); \
>> +#define dprintk(level, fmt, arg...)					\
>> +	do {								\
>> +		if (debug >= level)					\
>> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
>>   	} while (0)
>>
>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>> @@ -53,7 +53,7 @@ module_param(debug, int, 0644);
>>
>>   #define log_memop(vb, op)						\
>>   	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
>> -		(vb)->vb2_queue, (vb)->v4l2_buf.index, #op,		\
>> +		(vb)->vb2_queue, (vb)->index, #op,			\
>>   		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
>>
>>   #define call_memop(vb, op, args...)					\
>> @@ -115,7 +115,7 @@ module_param(debug, int, 0644);
>>
>>   #define log_vb_qop(vb, op, args...)					\
>>   	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
>> -		(vb)->vb2_queue, (vb)->v4l2_buf.index, #op,		\
>> +		(vb)->vb2_queue, (vb)->index, #op,			\
>>   		(vb)->vb2_queue->ops->op ? "" : " (nop)")
>>
>>   #define call_vb_qop(vb, op, args...)					\
>> @@ -205,13 +205,13 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
>>   		unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]);
>>
>>   		mem_priv = call_ptr_memop(vb, alloc, q->alloc_ctx[plane],
>> -				      size, dma_dir, q->gfp_flags);
>> +					size, dma_dir, q->gfp_flags);
>>   		if (IS_ERR_OR_NULL(mem_priv))
>>   			goto free;
>>
>>   		/* Associate allocator private data with this plane */
>>   		vb->planes[plane].mem_priv = mem_priv;
>> -		vb->v4l2_planes[plane].length = q->plane_sizes[plane];
>> +		vb->planes[plane].length = q->plane_sizes[plane];
>>   	}
>>
>>   	return 0;
>> @@ -235,8 +235,7 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb)
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		call_void_memop(vb, put, vb->planes[plane].mem_priv);
>>   		vb->planes[plane].mem_priv = NULL;
>> -		dprintk(3, "freed plane %d of buffer %d\n", plane,
>> -			vb->v4l2_buf.index);
>> +		dprintk(3, "freed plane %d of buffer %d\n", plane, vb->index);
>>   	}
>>   }
>>
>> @@ -269,7 +268,9 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p)
>>
>>   	call_void_memop(vb, detach_dmabuf, p->mem_priv);
>>   	dma_buf_put(p->dbuf);
>> -	memset(p, 0, sizeof(*p));
>> +	p->mem_priv = NULL;
>> +	p->dbuf = NULL;
>> +	p->dbuf_mapped = 0;
>>   }
>>
>>   /**
>> @@ -299,7 +300,7 @@ static void __setup_lengths(struct vb2_queue *q, unsigned int n)
>>   			continue;
>>
>>   		for (plane = 0; plane < vb->num_planes; ++plane)
>> -			vb->v4l2_planes[plane].length = q->plane_sizes[plane];
>> +			vb->planes[plane].length = q->plane_sizes[plane];
>>   	}
>>   }
>>
>> @@ -314,10 +315,10 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>>   	unsigned long off;
>>
>>   	if (q->num_buffers) {
>> -		struct v4l2_plane *p;
>> +		struct vb2_plane *p;
>>   		vb = q->bufs[q->num_buffers - 1];
>> -		p = &vb->v4l2_planes[vb->num_planes - 1];
>> -		off = PAGE_ALIGN(p->m.mem_offset + p->length);
>> +		p = &vb->planes[vb->num_planes - 1];
>> +		off = PAGE_ALIGN(p->m.offset + p->length);
>>   	} else {
>>   		off = 0;
>>   	}
>> @@ -328,12 +329,12 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>>   			continue;
>>
>>   		for (plane = 0; plane < vb->num_planes; ++plane) {
>> -			vb->v4l2_planes[plane].m.mem_offset = off;
>> +			vb->planes[plane].m.offset = off;
>>
>>   			dprintk(3, "buffer %d, plane %d offset 0x%08lx\n",
>>   					buffer, plane, off);
>>
>> -			off += vb->v4l2_planes[plane].length;
>> +			off += vb->planes[plane].length;
>>   			off = PAGE_ALIGN(off);
>>   		}
>>   	}
>> @@ -347,7 +348,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>>    * Returns the number of buffers successfully allocated.
>>    */
>>   static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>> -			     unsigned int num_buffers, unsigned int num_planes)
>> +			unsigned int num_buffers, unsigned int num_planes)
>>   {
>>   	unsigned int buffer;
>>   	struct vb2_buffer *vb;
>> @@ -361,16 +362,12 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>>   			break;
>>   		}
>>
>> -		/* Length stores number of planes for multiplanar buffers */
>> -		if (V4L2_TYPE_IS_MULTIPLANAR(q->type))
>> -			vb->v4l2_buf.length = num_planes;
>> -
>>   		vb->state = VB2_BUF_STATE_DEQUEUED;
>>   		vb->vb2_queue = q;
>>   		vb->num_planes = num_planes;
>> -		vb->v4l2_buf.index = q->num_buffers + buffer;
>> -		vb->v4l2_buf.type = q->type;
>> -		vb->v4l2_buf.memory = memory;
>> +		vb->index = q->num_buffers + buffer;
>> +		vb->type = q->type;
>> +		vb->memory = memory;
>>
>>   		/* Allocate video buffer memory for the MMAP type */
>>   		if (memory == V4L2_MEMORY_MMAP) {
>> @@ -418,7 +415,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>>   	struct vb2_buffer *vb;
>>
>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>> -	     ++buffer) {
>> +			++buffer) {
>>   		vb = q->bufs[buffer];
>>   		if (!vb)
>>   			continue;
>> @@ -451,7 +448,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>   	 * just return -EAGAIN.
>>   	 */
>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>> -	     ++buffer) {
>> +			++buffer) {
>>   		if (q->bufs[buffer] == NULL)
>>   			continue;
>>   		if (q->bufs[buffer]->state == VB2_BUF_STATE_PREPARING) {
>> @@ -462,7 +459,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>
>>   	/* Call driver-provided cleanup function for each buffer, if provided */
>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>> -	     ++buffer) {
>> +			++buffer) {
>>   		struct vb2_buffer *vb = q->bufs[buffer];
>>
>>   		if (vb && vb->planes[0].mem_priv)
>> @@ -536,7 +533,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>
>>   	/* Free videobuf buffers */
>>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
>> -	     ++buffer) {
>> +			++buffer) {
>>   		kfree(q->bufs[buffer]);
>>   		q->bufs[buffer] = NULL;
>>   	}
>> @@ -590,23 +587,22 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>>   		for (plane = 0; plane < vb->num_planes; ++plane) {
>>   			length = (b->memory == V4L2_MEMORY_USERPTR ||
>> -				  b->memory == V4L2_MEMORY_DMABUF)
>> -			       ? b->m.planes[plane].length
>> -			       : vb->v4l2_planes[plane].length;
>> +				b->memory == V4L2_MEMORY_DMABUF)
>> +				? b->m.planes[plane].length
>> +				: vb->planes[plane].length;
>>   			bytesused = b->m.planes[plane].bytesused
>> -				  ? b->m.planes[plane].bytesused : length;
>> +				? b->m.planes[plane].bytesused : length;
>>
>>   			if (b->m.planes[plane].bytesused > length)
>>   				return -EINVAL;
>>
>>   			if (b->m.planes[plane].data_offset > 0 &&
>> -			    b->m.planes[plane].data_offset >= bytesused)
>> +				b->m.planes[plane].data_offset >= bytesused)
>>   				return -EINVAL;
>>   		}
>>   	} else {
>>   		length = (b->memory == V4L2_MEMORY_USERPTR)
>> -		       ? b->length : vb->v4l2_planes[0].length;
>> -		bytesused = b->bytesused ? b->bytesused : length;
>> +			? b->length : vb->planes[0].length;
>>
>>   		if (b->bytesused > length)
>>   			return -EINVAL;
>> @@ -656,12 +652,21 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>    */
>>   static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>>   {
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>   	struct vb2_queue *q = vb->vb2_queue;
>> +	unsigned int plane;
>>
>>   	/* Copy back data such as timestamp, flags, etc. */
>> -	memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
>> -	b->reserved2 = vb->v4l2_buf.reserved2;
>> -	b->reserved = vb->v4l2_buf.reserved;
>> +	b->index = vb->index;
>> +	b->type = vb->type;
>> +	b->memory = vb->memory;
>> +	b->bytesused = 0;
>> +
>> +	b->flags = vbuf->flags;
>> +	b->field = vbuf->field;
>> +	b->timestamp = vbuf->timestamp;
>> +	b->timecode = vbuf->timecode;
>> +	b->sequence = vbuf->sequence;
>>
>>   	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>>   		/*
>> @@ -669,21 +674,33 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>>   		 * for it. The caller has already verified memory and size.
>>   		 */
>>   		b->length = vb->num_planes;
>> -		memcpy(b->m.planes, vb->v4l2_planes,
>> -			b->length * sizeof(struct v4l2_plane));
>> +		for (plane = 0; plane < vb->num_planes; ++plane) {
>> +			struct v4l2_plane *pdst = &b->m.planes[plane];
>> +			struct vb2_plane *psrc = &vb->planes[plane];
>> +
>> +			pdst->bytesused = psrc->bytesused;
>> +			pdst->length = psrc->length;
>> +			if (q->memory == V4L2_MEMORY_MMAP)
>> +				pdst->m.mem_offset = psrc->m.offset;
>> +			else if (q->memory == V4L2_MEMORY_USERPTR)
>> +				pdst->m.userptr = psrc->m.userptr;
>> +			else if (q->memory == V4L2_MEMORY_DMABUF)
>> +				pdst->m.fd = psrc->m.fd;
>> +			pdst->data_offset = psrc->data_offset;
>> +		}
>>   	} else {
>>   		/*
>>   		 * We use length and offset in v4l2_planes array even for
>>   		 * single-planar buffers, but userspace does not.
>>   		 */
>> -		b->length = vb->v4l2_planes[0].length;
>> -		b->bytesused = vb->v4l2_planes[0].bytesused;
>> +		b->length = vb->planes[0].length;
>> +		b->bytesused = vb->planes[0].bytesused;
>>   		if (q->memory == V4L2_MEMORY_MMAP)
>> -			b->m.offset = vb->v4l2_planes[0].m.mem_offset;
>> +			b->m.offset = vb->planes[0].m.offset;
>>   		else if (q->memory == V4L2_MEMORY_USERPTR)
>> -			b->m.userptr = vb->v4l2_planes[0].m.userptr;
>> +			b->m.userptr = vb->planes[0].m.userptr;
>>   		else if (q->memory == V4L2_MEMORY_DMABUF)
>> -			b->m.fd = vb->v4l2_planes[0].m.fd;
>> +			b->m.fd = vb->planes[0].m.fd;
>>   	}
>>
>>   	/*
>> @@ -692,7 +709,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>>   	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>>   	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>>   	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> -	    V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>>   		/*
>>   		 * For non-COPY timestamps, drop timestamp source bits
>>   		 * and obtain the timestamp source from the queue.
>> @@ -767,7 +784,7 @@ EXPORT_SYMBOL(vb2_querybuf);
>>   static int __verify_userptr_ops(struct vb2_queue *q)
>>   {
>>   	if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
>> -	    !q->mem_ops->put_userptr)
>> +			!q->mem_ops->put_userptr)
>>   		return -EINVAL;
>>
>>   	return 0;
>> @@ -780,7 +797,7 @@ static int __verify_userptr_ops(struct vb2_queue *q)
>>   static int __verify_mmap_ops(struct vb2_queue *q)
>>   {
>>   	if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
>> -	    !q->mem_ops->put || !q->mem_ops->mmap)
>> +			!q->mem_ops->put || !q->mem_ops->mmap)
>>   		return -EINVAL;
>>
>>   	return 0;
>> @@ -793,8 +810,8 @@ static int __verify_mmap_ops(struct vb2_queue *q)
>>   static int __verify_dmabuf_ops(struct vb2_queue *q)
>>   {
>>   	if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
>> -	    !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
>> -	    !q->mem_ops->unmap_dmabuf)
>> +		!q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
>> +		!q->mem_ops->unmap_dmabuf)
>>   		return -EINVAL;
>>
>>   	return 0;
>> @@ -808,7 +825,7 @@ static int __verify_memory_type(struct vb2_queue *q,
>>   		enum v4l2_memory memory, enum v4l2_buf_type type)
>>   {
>>   	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
>> -	    memory != V4L2_MEMORY_DMABUF) {
>> +			memory != V4L2_MEMORY_DMABUF) {
>>   		dprintk(1, "unsupported memory type\n");
>>   		return -EINVAL;
>>   	}
>> @@ -927,7 +944,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   	 * Driver also sets the size and allocator context for each plane.
>>   	 */
>>   	ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
>> -		       q->plane_sizes, q->alloc_ctx);
>> +			q->plane_sizes, q->alloc_ctx);
>>   	if (ret)
>>   		return ret;
>>
>> @@ -952,7 +969,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   		num_buffers = allocated_buffers;
>>
>>   		ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
>> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
>> +				&num_planes, q->plane_sizes, q->alloc_ctx);
>>
>>   		if (!ret && allocated_buffers < num_buffers)
>>   			ret = -ENOMEM;
>> @@ -1040,7 +1057,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   	 * buffer and their sizes are acceptable
>>   	 */
>>   	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>> -		       &num_planes, q->plane_sizes, q->alloc_ctx);
>> +			&num_planes, q->plane_sizes, q->alloc_ctx);
>>   	if (ret)
>>   		return ret;
>>
>> @@ -1063,7 +1080,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   		 * queue driver has set up
>>   		 */
>>   		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
>> +				&num_planes, q->plane_sizes, q->alloc_ctx);
>>
>>   		if (!ret && allocated_buffers < num_buffers)
>>   			ret = -ENOMEM;
>> @@ -1183,8 +1200,8 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
>>   		return;
>>
>>   	if (WARN_ON(state != VB2_BUF_STATE_DONE &&
>> -		    state != VB2_BUF_STATE_ERROR &&
>> -		    state != VB2_BUF_STATE_QUEUED))
>> +		state != VB2_BUF_STATE_ERROR &&
>> +		state != VB2_BUF_STATE_QUEUED))
>>   		state = VB2_BUF_STATE_ERROR;
>>
>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>> @@ -1195,7 +1212,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
>>   	vb->cnt_buf_done++;
>>   #endif
>>   	dprintk(4, "done processing on buffer %d, state: %d\n",
>> -			vb->v4l2_buf.index, state);
>> +			vb->index, state);
>>
>>   	/* sync buffers */
>>   	for (plane = 0; plane < vb->num_planes; ++plane)
>> @@ -1268,25 +1285,26 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>>    * v4l2_buffer by the userspace. The caller has already verified that struct
>>    * v4l2_buffer has a valid number of planes.
>>    */
>> -static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
>> -				struct v4l2_plane *v4l2_planes)
>> +static void __fill_vb2_buffer(struct vb2_buffer *vb,
>> +		const struct v4l2_buffer *b, struct vb2_plane *planes)
>>   {
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>   	unsigned int plane;
>>
>>   	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>>   		if (b->memory == V4L2_MEMORY_USERPTR) {
>>   			for (plane = 0; plane < vb->num_planes; ++plane) {
>> -				v4l2_planes[plane].m.userptr =
>> +				planes[plane].m.userptr =
>>   					b->m.planes[plane].m.userptr;
>> -				v4l2_planes[plane].length =
>> +				planes[plane].length =
>>   					b->m.planes[plane].length;
>>   			}
>>   		}
>>   		if (b->memory == V4L2_MEMORY_DMABUF) {
>>   			for (plane = 0; plane < vb->num_planes; ++plane) {
>> -				v4l2_planes[plane].m.fd =
>> +				planes[plane].m.fd =
>>   					b->m.planes[plane].m.fd;
>> -				v4l2_planes[plane].length =
>> +				planes[plane].length =
>>   					b->m.planes[plane].length;
>>   			}
>>   		}
>> @@ -1310,7 +1328,7 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>>   			 * applications working.
>>   			 */
>>   			for (plane = 0; plane < vb->num_planes; ++plane) {
>> -				struct v4l2_plane *pdst = &v4l2_planes[plane];
>> +				struct vb2_plane *pdst = &planes[plane];
>>   				struct v4l2_plane *psrc = &b->m.planes[plane];
>>
>>   				if (psrc->bytesused == 0)
>> @@ -1340,13 +1358,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>>   		 * old userspace applications working.
>>   		 */
>>   		if (b->memory == V4L2_MEMORY_USERPTR) {
>> -			v4l2_planes[0].m.userptr = b->m.userptr;
>> -			v4l2_planes[0].length = b->length;
>> +			planes[0].m.userptr = b->m.userptr;
>> +			planes[0].length = b->length;
>>   		}
>>
>>   		if (b->memory == V4L2_MEMORY_DMABUF) {
>> -			v4l2_planes[0].m.fd = b->m.fd;
>> -			v4l2_planes[0].length = b->length;
>> +			planes[0].m.fd = b->m.fd;
>> +			planes[0].length = b->length;
>>   		}
>>
>>   		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> @@ -1354,25 +1372,26 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>>   				vb2_warn_zero_bytesused(vb);
>>
>>   			if (vb->vb2_queue->allow_zero_bytesused)
>> -				v4l2_planes[0].bytesused = b->bytesused;
>> +				planes[0].bytesused = b->bytesused;
>>   			else
>> -				v4l2_planes[0].bytesused = b->bytesused ?
>> -					b->bytesused : v4l2_planes[0].length;
>> +				planes[0].bytesused = b->bytesused ?
>> +					b->bytesused : planes[0].length;
>>   		} else
>> -			v4l2_planes[0].bytesused = 0;
>> +			planes[0].bytesused = 0;
>>
>>   	}
>>
>>   	/* Zero flags that the vb2 core handles */
>> -	vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
>> +	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
>>   	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> -	    V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
>> +			!V4L2_TYPE_IS_OUTPUT(b->type)) {
>>   		/*
>>   		 * Non-COPY timestamps and non-OUTPUT queues will get
>>   		 * their timestamp and timestamp source flags from the
>>   		 * queue.
>>   		 */
>> -		vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> +		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>>   	}
>>
>>   	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> @@ -1382,11 +1401,11 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>>   		 * The 'field' is valid metadata for this output buffer
>>   		 * and so that needs to be copied here.
>>   		 */
>> -		vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TIMECODE;
>> -		vb->v4l2_buf.field = b->field;
>> +		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
>> +		vbuf->field = b->field;
>>   	} else {
>>   		/* Zero any output buffer flags as this is a capture buffer */
>> -		vb->v4l2_buf.flags &= ~V4L2_BUFFER_OUT_FLAGS;
>> +		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
>>   	}
>>   }
>>
>> @@ -1395,7 +1414,7 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
>>    */
>>   static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   {
>> -	__fill_vb2_buffer(vb, b, vb->v4l2_planes);
>> +	__fill_vb2_buffer(vb, b, vb->planes);
>>   	return call_vb_qop(vb, buf_prepare, vb);
>>   }
>>
>> @@ -1404,7 +1423,7 @@ static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>    */
>>   static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   {
>> -	struct v4l2_plane planes[VIDEO_MAX_PLANES];
>> +	struct vb2_plane planes[VIDEO_MAX_PLANES];
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	void *mem_priv;
>>   	unsigned int plane;
>> @@ -1419,9 +1438,9 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		/* Skip the plane if already verified */
>> -		if (vb->v4l2_planes[plane].m.userptr &&
>> -		    vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
>> -		    && vb->v4l2_planes[plane].length == planes[plane].length)
>> +		if (vb->planes[plane].m.userptr &&
>> +			vb->planes[plane].m.userptr == planes[plane].m.userptr
>> +			&& vb->planes[plane].length == planes[plane].length)
>>   			continue;
>>
>>   		dprintk(3, "userspace address for plane %d changed, "
>> @@ -1447,12 +1466,15 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   		}
>>
>>   		vb->planes[plane].mem_priv = NULL;
>> -		memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
>> +		vb->planes[plane].bytesused = 0;
>> +		vb->planes[plane].length = 0;
>> +		vb->planes[plane].m.userptr = 0;
>> +		vb->planes[plane].data_offset = 0;
>>
>>   		/* Acquire each plane's memory */
>>   		mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane],
>> -				      planes[plane].m.userptr,
>> -				      planes[plane].length, dma_dir);
>> +					planes[plane].m.userptr,
>> +					planes[plane].length, dma_dir);
>>   		if (IS_ERR_OR_NULL(mem_priv)) {
>>   			dprintk(1, "failed acquiring userspace "
>>   						"memory for plane %d\n", plane);
>> @@ -1466,8 +1488,12 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   	 * Now that everything is in order, copy relevant information
>>   	 * provided by userspace.
>>   	 */
>> -	for (plane = 0; plane < vb->num_planes; ++plane)
>> -		vb->v4l2_planes[plane] = planes[plane];
>> +	for (plane = 0; plane < vb->num_planes; ++plane) {
>> +		vb->planes[plane].bytesused = planes[plane].bytesused;
>> +		vb->planes[plane].length = planes[plane].length;
>> +		vb->planes[plane].m.userptr = planes[plane].m.userptr;
>> +		vb->planes[plane].data_offset = planes[plane].data_offset;
>> +	}
>>
>>   	if (reacquired) {
>>   		/*
>> @@ -1494,10 +1520,11 @@ err:
>>   	/* In case of errors, release planes that were already acquired */
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		if (vb->planes[plane].mem_priv)
>> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
>> +			call_void_memop(vb, put_userptr,
>> +				vb->planes[plane].mem_priv);
>>   		vb->planes[plane].mem_priv = NULL;
>> -		vb->v4l2_planes[plane].m.userptr = 0;
>> -		vb->v4l2_planes[plane].length = 0;
>> +		vb->planes[plane].m.userptr = 0;
>> +		vb->planes[plane].length = 0;
>>   	}
>>
>>   	return ret;
>> @@ -1508,7 +1535,7 @@ err:
>>    */
>>   static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   {
>> -	struct v4l2_plane planes[VIDEO_MAX_PLANES];
>> +	struct vb2_plane planes[VIDEO_MAX_PLANES];
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	void *mem_priv;
>>   	unsigned int plane;
>> @@ -1544,7 +1571,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>
>>   		/* Skip the plane if already verified */
>>   		if (dbuf == vb->planes[plane].dbuf &&
>> -		    vb->v4l2_planes[plane].length == planes[plane].length) {
>> +			vb->planes[plane].length == planes[plane].length) {
>>   			dma_buf_put(dbuf);
>>   			continue;
>>   		}
>> @@ -1558,11 +1585,15 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>
>>   		/* Release previously acquired memory if present */
>>   		__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
>> -		memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
>> +		vb->planes[plane].bytesused = 0;
>> +		vb->planes[plane].length = 0;
>> +		vb->planes[plane].m.fd = 0;
>> +		vb->planes[plane].data_offset = 0;
>>
>>   		/* Acquire each plane's memory */
>> -		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
>> -			dbuf, planes[plane].length, dma_dir);
>> +		mem_priv = call_ptr_memop(vb, attach_dmabuf,
>> +			q->alloc_ctx[plane], dbuf, planes[plane].length,
>> +			dma_dir);
>>   		if (IS_ERR(mem_priv)) {
>>   			dprintk(1, "failed to attach dmabuf\n");
>>   			ret = PTR_ERR(mem_priv);
>> @@ -1592,8 +1623,12 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   	 * Now that everything is in order, copy relevant information
>>   	 * provided by userspace.
>>   	 */
>> -	for (plane = 0; plane < vb->num_planes; ++plane)
>> -		vb->v4l2_planes[plane] = planes[plane];
>> +	for (plane = 0; plane < vb->num_planes; ++plane) {
>> +		vb->planes[plane].bytesused = planes[plane].bytesused;
>> +		vb->planes[plane].length = planes[plane].length;
>> +		vb->planes[plane].m.fd = planes[plane].m.userptr;
>> +		vb->planes[plane].data_offset = planes[plane].data_offset;
>> +	}
>>
>>   	if (reacquired) {
>>   		/*
>> @@ -1644,6 +1679,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
>>
>>   static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   {
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	int ret;
>>
>> @@ -1672,9 +1708,9 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   	}
>>
>>   	vb->state = VB2_BUF_STATE_PREPARING;
>> -	vb->v4l2_buf.timestamp.tv_sec = 0;
>> -	vb->v4l2_buf.timestamp.tv_usec = 0;
>> -	vb->v4l2_buf.sequence = 0;
>> +	vbuf->timestamp.tv_sec = 0;
>> +	vbuf->timestamp.tv_usec = 0;
>> +	vbuf->sequence = 0;
>>
>>   	switch (q->memory) {
>>   	case V4L2_MEMORY_MMAP:
>> @@ -1701,7 +1737,7 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   }
>>
>>   static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
>> -				    const char *opname)
>> +					const char *opname)
>>   {
>>   	if (b->type != q->type) {
>>   		dprintk(1, "%s: invalid buffer type\n", opname);
>> @@ -1768,7 +1804,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   		/* Fill buffer information for the userspace */
>>   		__fill_v4l2_buffer(vb, b);
>>
>> -		dprintk(1, "prepare of buffer %d succeeded\n", vb->v4l2_buf.index);
>> +		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
>>   	}
>>   	return ret;
>>   }
>> @@ -1800,7 +1836,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>   	/* Tell the driver to start streaming */
>>   	q->start_streaming_called = 1;
>>   	ret = call_qop(q, start_streaming, q,
>> -		       atomic_read(&q->owned_by_drv_count));
>> +			atomic_read(&q->owned_by_drv_count));
>>   	if (!ret)
>>   		return 0;
>>
>> @@ -1810,7 +1846,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>   	/*
>>   	 * If you see this warning, then the driver isn't cleaning up properly
>>   	 * after a failed start_streaming(). See the start_streaming()
>> -	 * documentation in videobuf2-v4l2.h for more information how buffers
>> +	 * documentation in videobuf2-core.h for more information how buffers
>>   	 * should be returned to vb2 in start_streaming().
>>   	 */
>>   	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
>> @@ -1841,11 +1877,13 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   {
>>   	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
>>   	struct vb2_buffer *vb;
>> +	struct vb2_v4l2_buffer *vbuf;
>>
>>   	if (ret)
>>   		return ret;
>>
>>   	vb = q->bufs[b->index];
>> +	vbuf = to_vb2_v4l2_buffer(vb);
>>
>>   	switch (vb->state) {
>>   	case VB2_BUF_STATE_DEQUEUED:
>> @@ -1877,11 +1915,11 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   		 * and the timecode field and flag if needed.
>>   		 */
>>   		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> -		    V4L2_BUF_FLAG_TIMESTAMP_COPY)
>> -			vb->v4l2_buf.timestamp = b->timestamp;
>> -		vb->v4l2_buf.flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
>> +				V4L2_BUF_FLAG_TIMESTAMP_COPY)
>> +			vbuf->timestamp = b->timestamp;
>> +		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
>>   		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
>> -			vb->v4l2_buf.timecode = b->timecode;
>> +			vbuf->timecode = b->timecode;
>>   	}
>>
>>   	trace_vb2_qbuf(q, vb);
>> @@ -1903,13 +1941,13 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   	 * then we can finally call start_streaming().
>>   	 */
>>   	if (q->streaming && !q->start_streaming_called &&
>> -	    q->queued_count >= q->min_buffers_needed) {
>> +			q->queued_count >= q->min_buffers_needed) {
>>   		ret = vb2_start_streaming(q);
>>   		if (ret)
>>   			return ret;
>>   	}
>>
>> -	dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
>> +	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
>>   	return 0;
>>   }
>>
>> @@ -2099,9 +2137,11 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
>>   		}
>>   }
>>
>> -static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
>> +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>> +		bool nonblocking)
>>   {
>>   	struct vb2_buffer *vb = NULL;
>> +	struct vb2_v4l2_buffer *vbuf = NULL;
>>   	int ret;
>>
>>   	if (b->type != q->type) {
>> @@ -2134,14 +2174,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool n
>>
>>   	trace_vb2_dqbuf(q, vb);
>>
>> +	vbuf = to_vb2_v4l2_buffer(vb);
>>   	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
>> -	    vb->v4l2_buf.flags & V4L2_BUF_FLAG_LAST)
>> +			vbuf->flags & V4L2_BUF_FLAG_LAST)
>>   		q->last_buffer_dequeued = true;
>>   	/* go back to dequeued state */
>>   	__vb2_dqbuf(vb);
>>
>>   	dprintk(1, "dqbuf of buffer %d, with state %d\n",
>> -			vb->v4l2_buf.index, vb->state);
>> +			vb->index, vb->state);
>>
>>   	return 0;
>>   }
>> @@ -2197,7 +2238,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>   	/*
>>   	 * If you see this warning, then the driver isn't cleaning up properly
>>   	 * in stop_streaming(). See the stop_streaming() documentation in
>> -	 * videobuf2-v4l2.h for more information how buffers should be returned
>> +	 * videobuf2-core.h for more information how buffers should be returned
>>   	 * to vb2 in stop_streaming().
>>   	 */
>>   	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
>> @@ -2399,7 +2440,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>   		vb = q->bufs[buffer];
>>
>>   		for (plane = 0; plane < vb->num_planes; ++plane) {
>> -			if (vb->v4l2_planes[plane].m.mem_offset == off) {
>> +			if (vb->planes[plane].m.offset == off) {
>>   				*_buffer = buffer;
>>   				*_plane = plane;
>>   				return 0;
>> @@ -2557,7 +2598,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   	 * The buffer length was page_aligned at __vb2_buf_mem_alloc(),
>>   	 * so, we need to do the same here.
>>   	 */
>> -	length = PAGE_ALIGN(vb->v4l2_planes[plane].length);
>> +	length = PAGE_ALIGN(vb->planes[plane].length);
>>   	if (length < (vma->vm_end - vma->vm_start)) {
>>   		dprintk(1,
>>   			"MMAP invalid, as it would overflow buffer length\n");
>> @@ -2577,10 +2618,10 @@ EXPORT_SYMBOL_GPL(vb2_mmap);
>>
>>   #ifndef CONFIG_MMU
>>   unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>> -				    unsigned long addr,
>> -				    unsigned long len,
>> -				    unsigned long pgoff,
>> -				    unsigned long flags)
>> +					unsigned long addr,
>> +					unsigned long len,
>> +					unsigned long pgoff,
>> +					unsigned long flags)
>>   {
>>   	unsigned long off = pgoff << PAGE_SHIFT;
>>   	struct vb2_buffer *vb;
>> @@ -2731,7 +2772,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
>>    * responsible of clearing it's content and setting initial values for some
>>    * required entries before calling this function.
>>    * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
>> - * to the struct vb2_queue description in include/media/videobuf2-v4l2.h
>> + * to the struct vb2_queue description in include/media/videobuf2-core.h
>>    * for more information.
>>    */
>>   int vb2_queue_init(struct vb2_queue *q)
>> @@ -2739,16 +2780,16 @@ int vb2_queue_init(struct vb2_queue *q)
>>   	/*
>>   	 * Sanity check
>>   	 */
>> -	if (WARN_ON(!q)			  ||
>> -	    WARN_ON(!q->ops)		  ||
>> -	    WARN_ON(!q->mem_ops)	  ||
>> -	    WARN_ON(!q->type)		  ||
>> -	    WARN_ON(!q->io_modes)	  ||
>> -	    WARN_ON(!q->ops->queue_setup) ||
>> -	    WARN_ON(!q->ops->buf_queue)   ||
>> -	    WARN_ON(q->timestamp_flags &
>> -		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
>> -		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
>> +	if (WARN_ON(!q)				||
>> +		WARN_ON(!q->ops)		||
>> +		WARN_ON(!q->mem_ops)		||
>> +		WARN_ON(!q->type)		||
>> +		WARN_ON(!q->io_modes)		||
>> +		WARN_ON(!q->ops->queue_setup)	||
>> +		WARN_ON(!q->ops->buf_queue)	||
>> +		WARN_ON(q->timestamp_flags &
>> +			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
>> +			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
>>   		return -EINVAL;
>>
>>   	/* Warn that the driver should choose an appropriate timestamp type */
>> @@ -2852,7 +2893,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
>>   	 * Sanity check
>>   	 */
>>   	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
>> -		    (!read && !(q->io_modes & VB2_WRITE))))
>> +			(!read && !(q->io_modes & VB2_WRITE))))
>>   		return -EINVAL;
>>
>>   	/*
>> @@ -3063,9 +3104,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
>>   		buf->queued = 0;
>>   		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>>   				 : vb2_plane_size(q->bufs[index], 0);
>> -		/* Compensate for data_offset on read in the multiplanar case. */
>> +		/*
>> +		 * Compensate for data_offset on read
>> +		 * in the multiplanar case
>> +		 */
>>   		if (is_multiplanar && read &&
>> -		    fileio->b.m.planes[0].data_offset < buf->size) {
>> +			fileio->b.m.planes[0].data_offset < buf->size) {
>>   			buf->pos = fileio->b.m.planes[0].data_offset;
>>   			buf->size -= buf->pos;
>>   		}
>> @@ -3257,7 +3301,7 @@ static int vb2_thread(void *data)
>>    * contact the linux-media mailinglist first.
>>    */
>>   int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
>> -		     const char *thread_name)
>> +			const char *thread_name)
>>   {
>>   	struct vb2_threadio_data *threadio;
>>   	int ret = 0;
>> @@ -3491,7 +3535,7 @@ ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>>   	if (vb2_queue_is_busy(vdev, file))
>>   		goto exit;
>>   	err = vb2_write(vdev->queue, buf, count, ppos,
>> -		       file->f_flags & O_NONBLOCK);
>> +			file->f_flags & O_NONBLOCK);
>>   	if (vdev->queue->fileio)
>>   		vdev->queue->owner = file->private_data;
>>   exit:
>> @@ -3515,7 +3559,7 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf,
>>   	if (vb2_queue_is_busy(vdev, file))
>>   		goto exit;
>>   	err = vb2_read(vdev->queue, buf, count, ppos,
>> -		       file->f_flags & O_NONBLOCK);
>> +			file->f_flags & O_NONBLOCK);
>>   	if (vdev->queue->fileio)
>>   		vdev->queue->owner = file->private_data;
>>   exit:
>> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
>> index 155991e..8787a6c 100644
>> --- a/include/media/videobuf2-core.h
>> +++ b/include/media/videobuf2-core.h
>> @@ -115,6 +115,16 @@ struct vb2_plane {
>>   	void			*mem_priv;
>>   	struct dma_buf		*dbuf;
>>   	unsigned int		dbuf_mapped;
>> +
>> +	/* plane information */
>> +	unsigned int		bytesused;
>> +	unsigned int		length;
>> +	union {
>> +		unsigned int	offset;
>> +		unsigned long	userptr;
>> +		int		fd;
>> +	} m;
>> +	unsigned int		data_offset;
>>   };
>
> Nitpick: it would be good to add a documentation for struct vb2_plane,
> describing what each field means on this struct. Granted, this could
> be added after this patch series.
>
> Btw, I don't see much reason to have the:
> 	/* plane information */
> comment here, as this struct is all about plane information, right?
> Or, maybe you wanted, instead, to comment that those fields should
> have what's there at struct v4l2_plane? That would make sense ;)

Latter is right.

> So, I would change this comment to something like:
>
> 	/*
> 	 * Should contain enough plane information to contain the
> 	 * fields needed to fill struct v4l2_plane at videodev2.h
> 	 */
>
OK, I will change it.
>
>>
>>   /**
>> @@ -161,41 +171,33 @@ struct vb2_queue;
>>
>>   /**
>>    * struct vb2_buffer - represents a video buffer
>> - * @v4l2_buf:		struct v4l2_buffer associated with this buffer; can
>> - *			be read by the driver and relevant entries can be
>> - *			changed by the driver in case of CAPTURE types
>> - *			(such as timestamp)
>> - * @v4l2_planes:	struct v4l2_planes associated with this buffer; can
>> - *			be read by the driver and relevant entries can be
>> - *			changed by the driver in case of CAPTURE types
>> - *			(such as bytesused); NOTE that even for single-planar
>> - *			types, the v4l2_planes[0] struct should be used
>> - *			instead of v4l2_buf for filling bytesused - drivers
>> - *			should use the vb2_set_plane_payload() function for that
>>    * @vb2_queue:		the queue to which this driver belongs
>> - * @num_planes:		number of planes in the buffer
>> - *			on an internal driver queue
>>    * @state:		current buffer state; do not change
>>    * @queued_entry:	entry on the queued buffers list, which holds all
>>    *			buffers queued from userspace
>>    * @done_entry:		entry on the list that stores all buffers ready to
>>    *			be dequeued to userspace
>> + * @index:		id number of the buffer
>> + * @type:		buffer type
>> + * @memory:		the method, in which the actual data is passed
>> + * @num_planes:		number of planes in the buffer
>> + *			on an internal driver queue
>>    * @planes:		private per-plane information; do not change
>>    */
>>   struct vb2_buffer {
>> -	struct v4l2_buffer	v4l2_buf;
>> -	struct v4l2_plane	v4l2_planes[VIDEO_MAX_PLANES];
>> -
>>   	struct vb2_queue	*vb2_queue;
>>
>> -	unsigned int		num_planes;
>> -
>> -/* Private: internal use only */
>> +	/* Private: internal use only */
>>   	enum vb2_buffer_state	state;
>>
>>   	struct list_head	queued_entry;
>>   	struct list_head	done_entry;
>>
>> +	/* buffer information */
>> +	unsigned int		index;
>> +	unsigned int		type;
>> +	unsigned int		memory;
>> +	unsigned int		num_planes;
>
> Nitpick: Those comments that follow Documentation/kernel-doc-nano-HOWTO.txt
> are used to produce DocBook data, on both html and manpages formats.
> As documented there, DocBook discards documentation for all fields after a
> /*private: ...*/ comment.
>
> In other words, we need to take care of putting things after /*private:*/
> only when we're 100% sure that such fields are not meant to be filled/used
> by the callers, and will be used only internally, and don't deserve any
> documentation for the kABI.
>
> As you're adding documentation for those fields, and num_planes were
> documented before your series, I suspect that this is not what you want.
> So, please move them to be before the private: comment.

Oh, I didn't know that /*private: ...*/ comment have so much meaning.
I will change it at next round.

>
> Btw, if your patches are based on top of the current patchwork tree
> e. g. if it has this patch:
> 	http://git.linuxtv.org/cgit.cgi/media_tree.git/commit/?id=d071c833a0d30e7aae0ea565d92ef83c79106d6f
>
> Then you can make the Kernel to handle all those kernel-doc-nano
> comments with:
>
> 	make cleandocs && make DOCBOOKS=device-drivers.xml htmldocs
>
> It will produce some html pages like:
> 	http://linuxtv.org/downloads/v4l-dvb-internals/device-drivers/mediadev.html
>
> With can be useful to check if the documentation tags are properly placed.
>
>>   	struct vb2_plane	planes[VIDEO_MAX_PLANES];
>>
>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>> @@ -390,7 +392,7 @@ struct v4l2_fh;
>>    * @threadio:	thread io internal data, used only if thread is active
>>    */
>>   struct vb2_queue {
>> -	enum v4l2_buf_type		type;
>> +	unsigned int			type;
>>   	unsigned int			io_modes;
>>   	unsigned			fileio_read_once:1;
>>   	unsigned			fileio_write_immediately:1;
>> @@ -409,7 +411,7 @@ struct vb2_queue {
>>
>>   	/* private: internal use only */
>>   	struct mutex			mmap_lock;
>> -	enum v4l2_memory		memory;
>> +	unsigned int			memory;
>
> Will the vb2-core use type/memory fields or just vb2-v4l2? As you
> removed the enum, I suspect you won't be relying on having the videodev2.h
> header included here, right.

Exactly.

>
> If so, then the meaning of the type/memory fields are private to the
> caller of the VB2-core  (e. .g. the meaning are private to vb2-v4l2 and
> vb2-dvb). So, you should be changing the description of those fields
> at the doc-nano to:
> ...
>   * @type: private type whose content is defined by the vb2-core caller.
>   *        For example, for V4L2, it should match the V4L2_BUF_TYPE_*
>   *	  in include/uapi/linux/videodev2.h
> ...
>
> to let it clear.
>

0k, I will change it as your comment.

>>   	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
>>   	unsigned int			num_buffers;
>>
>> @@ -571,7 +573,7 @@ static inline void vb2_set_plane_payload(struct vb2_buffer *vb,
>>   				 unsigned int plane_no, unsigned long size)
>>   {
>>   	if (plane_no < vb->num_planes)
>> -		vb->v4l2_planes[plane_no].bytesused = size;
>> +		vb->planes[plane_no].bytesused = size;
>>   }
>>
>>   /**
>> @@ -583,7 +585,7 @@ static inline unsigned long vb2_get_plane_payload(struct vb2_buffer *vb,
>>   				 unsigned int plane_no)
>>   {
>>   	if (plane_no < vb->num_planes)
>> -		return vb->v4l2_planes[plane_no].bytesused;
>> +		return vb->planes[plane_no].bytesused;
>>   	return 0;
>>   }
>>
>> @@ -596,7 +598,7 @@ static inline unsigned long
>>   vb2_plane_size(struct vb2_buffer *vb, unsigned int plane_no)
>>   {
>>   	if (plane_no < vb->num_planes)
>> -		return vb->v4l2_planes[plane_no].length;
>> +		return vb->planes[plane_no].length;
>>   	return 0;
>>   }
>>
>> diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
>> index d4a4d9a..fc2dbe9 100644
>> --- a/include/media/videobuf2-v4l2.h
>> +++ b/include/media/videobuf2-v4l2.h
>> @@ -12,6 +12,32 @@
>>   #ifndef _MEDIA_VIDEOBUF2_V4L2_H
>>   #define _MEDIA_VIDEOBUF2_V4L2_H
>>
>> +#include <linux/videodev2.h>
>>   #include <media/videobuf2-core.h>
>>
>> +/**
>> + * struct vb2_v4l2_buffer - video buffer information for v4l2
>> + * @vb2_buf:	video buffer 2
>> + * @flags:	buffer informational flags
>> + * @field:	enum v4l2_field; field order of the image in the buffer
>> + * @timestamp:	frame timestamp
>> + * @timecode:	frame timecode
>> + * @sequence:	sequence count of this frame
>> + */
>> +struct vb2_v4l2_buffer {
>> +	struct vb2_buffer	vb2_buf;
>> +
>> +	__u32			flags;
>> +	__u32			field;
>> +	struct timeval		timestamp;
>> +	struct v4l2_timecode	timecode;
>> +	__u32			sequence;
>> +};
>> +
>> +/**
>> + * to_vb2_v4l2_buffer() - cast struct vb2_buffer * to struct vb2_v4l2_buffer *
>> + */
>> +#define to_vb2_v4l2_buffer(vb) \
>> +	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
>> +
>>   #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
>
> Regards,
> Mauro
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 3/5] media: videobuf2: Modify all device drivers
  2015-08-27 10:33   ` Mauro Carvalho Chehab
@ 2015-08-28  2:19     ` Junghak Sung
  2015-08-28  9:14       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 23+ messages in thread
From: Junghak Sung @ 2015-08-28  2:19 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Dear Mauro,

I'm sorry but patch 3 is very incomplete.
At this round, I could not modify all device drivers,
because there are too many files to be changed
and I should change them by hands.

I just want to be reviewed the modification pattern only before
I start to modify whole related device drivers.
I mean that .. most of drivers will be changed with a similar pattern
,even though, detailed will be a little different.

Could you verify whether my modification in this patch is correct?


On 08/27/2015 07:33 PM, Mauro Carvalho Chehab wrote:
> Em Wed, 26 Aug 2015 20:59:30 +0900
> Junghak Sung <jh1009.sung@samsung.com> escreveu:
>
>> Modify all device drivers related with previous change that restructures
>> vb2_buffer for common use.
>> Actually, not all device drivers, yet. So, it required to modifiy more file
>> to complete this patch.
>
> I was expecting to be able to compile everything after applying both
> patches 2 and 3, but compilation failed:
>
> In file included from drivers/media/platform/am437x/am437x-vpfe.c:41:0:
> drivers/media/platform/am437x/am437x-vpfe.h:107:25: error: field 'vb' has incomplete type
>    struct vb2_v4l2_buffer vb;
>                           ^
> drivers/media/platform/am437x/am437x-vpfe.c: In function 'to_vpfe_buffer':
> drivers/media/platform/am437x/am437x-vpfe.c:312:72: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
> drivers/media/platform/am437x/am437x-vpfe.c: In function 'vpfe_buffer_prepare':
> drivers/media/platform/am437x/am437x-vpfe.c:1952:4: error: 'struct vb2_buffer' has no member named 'v4l2_buf'
>    vb->v4l2_buf.field = vpfe->fmt.fmt.pix.field;
>      ^
> drivers/media/platform/am437x/am437x-vpfe.c: In function 'to_vpfe_buffer':
> drivers/media/platform/am437x/am437x-vpfe.c:313:1: warning: control reaches end of non-void function [-Wreturn-type]
>   }
>   ^
> scripts/Makefile.build:258: recipe for target 'drivers/media/platform/am437x/am437x-vpfe.o' failed
> make[3]: *** [drivers/media/platform/am437x/am437x-vpfe.o] Error 1
> scripts/Makefile.build:403: recipe for target 'drivers/media/platform/am437x' failed
> make[2]: *** [drivers/media/platform/am437x] Error 2
> scripts/Makefile.build:403: recipe for target 'drivers/media/platform' failed
> make[1]: *** [drivers/media/platform] Error 2
> make[1]: *** Waiting for unfinished jobs....
> In file included from drivers/media/pci/cobalt/cobalt-driver.c:30:0:
> drivers/media/pci/cobalt/cobalt-driver.h:209:25: error: field 'vb' has incomplete type
>    struct vb2_v4l2_buffer vb;
>                           ^
> drivers/media/pci/cobalt/cobalt-driver.h: In function 'to_cobalt_buffer':
> drivers/media/pci/cobalt/cobalt-driver.h:215:70: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
> scripts/Makefile.build:258: recipe for target 'drivers/media/pci/cobalt/cobalt-driver.o' failed
> make[3]: *** [drivers/media/pci/cobalt/cobalt-driver.o] Error 1
> scripts/Makefile.build:403: recipe for target 'drivers/media/pci/cobalt' failed
> make[2]: *** [drivers/media/pci/cobalt] Error 2
> scripts/Makefile.build:403: recipe for target 'drivers/media/pci' failed
> make[1]: *** [drivers/media/pci] Error 2
> drivers/media/dvb-frontends/rtl2832_sdr.c:110:25: error: field 'vb' has incomplete type
>    struct vb2_v4l2_buffer vb;   /* common v4l buffer stuff -- must be first */
>                           ^
> drivers/media/dvb-frontends/rtl2832_sdr.c: In function 'rtl2832_sdr_buf_queue':
> drivers/media/dvb-frontends/rtl2832_sdr.c:523:73: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
> drivers/media/dvb-frontends/rtl2832_sdr.c:523:73: note: (near initialization for 'buf')
> scripts/Makefile.build:258: recipe for target 'drivers/media/dvb-frontends/rtl2832_sdr.o' failed
> make[2]: *** [drivers/media/dvb-frontends/rtl2832_sdr.o] Error 1
> scripts/Makefile.build:403: recipe for target 'drivers/media/dvb-frontends' failed
> make[1]: *** [drivers/media/dvb-frontends] Error 2
> Makefile:1380: recipe for target '_module_drivers/media' failed
> make: *** [_module_drivers/media] Error 2
>
>
> So, obviously there's something wrong there. Please fix.
>
> I'll skip this patch from my review.
>
> Thanks!
> Mauro
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts
  2015-08-27 11:43   ` Mauro Carvalho Chehab
@ 2015-08-28  6:50     ` Junghak Sung
  2015-08-28  9:05       ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 23+ messages in thread
From: Junghak Sung @ 2015-08-28  6:50 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon



On 08/27/2015 08:43 PM, Mauro Carvalho Chehab wrote:
> Em Wed, 26 Aug 2015 20:59:32 +0900
> Junghak Sung <jh1009.sung@samsung.com> escreveu:
>
>> Divide videobuf2-core into core part and v4l2-specific part
>> - core part: videobuf2 core related with buffer management & memory
>>   allocation
>> - v4l2-specific part: v4l2-specific stuff
>
> This patch is really hard to review, as the diff changes are too high to
> be useful. I did a patch before this one doing a:
> 	cp drivers/media/v4l2-core/videobuf2-core.c drivers/media/v4l2-core/videobuf2-v4l2.c
>
> still, to properly be able to review it, we'll need to compile and
> do some tests, but, as patch 2 and 3 broke compilation, we can't do
> it :(
>
> So, I'll point for the things I found so far. I'll do a better review
> on your next submission, after being able to compile all drivers, and
> testing it with a few different devices to see how this works.
>

Ok, I got your point. I will focus on solving the compilation problem
at next round.
And.. if possible, I will divide this patch into several
pieces for easier review.

>>
>> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
>> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
>> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>> Acked-by: Inki Dae <inki.dae@samsung.com>
>> ---
>>   drivers/media/v4l2-core/videobuf2-core.c     | 1933 +++-----------------------
>>   drivers/media/v4l2-core/videobuf2-internal.h |  184 +++
>>   drivers/media/v4l2-core/videobuf2-v4l2.c     | 1640 ++++++++++++++++++++++
>>   include/media/videobuf2-core.h               |  157 +--
>>   include/media/videobuf2-v4l2.h               |  116 ++
>>   include/trace/events/v4l2.h                  |    4 +-
>>   6 files changed, 2154 insertions(+), 1880 deletions(-)
>>   create mode 100644 drivers/media/v4l2-core/videobuf2-internal.h
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
>> index 9266d50..2cd4241 100644
>> --- a/drivers/media/v4l2-core/videobuf2-core.c
>> +++ b/drivers/media/v4l2-core/videobuf2-core.c
>> @@ -6,9 +6,6 @@
>>    * Author: Pawel Osciak <pawel@osciak.com>
>>    *	   Marek Szyprowski <m.szyprowski@samsung.com>
>>    *
>> - * The vb2_thread implementation was based on code from videobuf-dvb.c:
>> - *	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
>> - *
>
> Please keep the credits here. The entire videobuf stuff was actually
> started with the first implementation done by Gerd.
>

I removed the comment because videobuf2-core would not have vb2_thread,
which is moved to videobuf2-v4l2.
For this reason, I would like to modify this credits like:

  * Copyright (C) 2010 Samsung Electronics
  *
  * Author: Pawel Osciak <pawel@osciak.com>
  *	   Marek Szyprowski <m.szyprowski@samsung.com>
  *
  * Copyright (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
  *

Is it ok? Or just leave it as it is.


>>    * This program is free software; you can redistribute it and/or modify
>>    * it under the terms of the GNU General Public License as published by
>>    * the Free Software Foundation.
>> @@ -24,164 +21,14 @@
>>   #include <linux/freezer.h>
>>   #include <linux/kthread.h>
>>
>> -#include <media/v4l2-dev.h>
>> -#include <media/v4l2-fh.h>
>> -#include <media/v4l2-event.h>
>> -#include <media/v4l2-common.h>
>> -#include <media/videobuf2-v4l2.h>
>> +#include <media/videobuf2-core.h>
>> +#include "videobuf2-internal.h"
>>
>>   #include <trace/events/v4l2.h>
>>
>> -static int debug;
>> -module_param(debug, int, 0644);
>> -
>> -#define dprintk(level, fmt, arg...)					\
>> -	do {								\
>> -		if (debug >= level)					\
>> -			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
>> -	} while (0)
>> -
>> -#ifdef CONFIG_VIDEO_ADV_DEBUG
>> -
>> -/*
>> - * If advanced debugging is on, then count how often each op is called
>> - * successfully, which can either be per-buffer or per-queue.
>> - *
>> - * This makes it easy to check that the 'init' and 'cleanup'
>> - * (and variations thereof) stay balanced.
>> - */
>> -
>> -#define log_memop(vb, op)						\
>> -	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
>> -		(vb)->vb2_queue, (vb)->index, #op,			\
>> -		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
>> -
>> -#define call_memop(vb, op, args...)					\
>> -({									\
>> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> -	int err;							\
>> -									\
>> -	log_memop(vb, op);						\
>> -	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
>> -	if (!err)							\
>> -		(vb)->cnt_mem_ ## op++;					\
>> -	err;								\
>> -})
>> -
>> -#define call_ptr_memop(vb, op, args...)					\
>> -({									\
>> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> -	void *ptr;							\
>> -									\
>> -	log_memop(vb, op);						\
>> -	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
>> -	if (!IS_ERR_OR_NULL(ptr))					\
>> -		(vb)->cnt_mem_ ## op++;					\
>> -	ptr;								\
>> -})
>> -
>> -#define call_void_memop(vb, op, args...)				\
>> -({									\
>> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> -									\
>> -	log_memop(vb, op);						\
>> -	if (_q->mem_ops->op)						\
>> -		_q->mem_ops->op(args);					\
>> -	(vb)->cnt_mem_ ## op++;						\
>> -})
>> -
>> -#define log_qop(q, op)							\
>> -	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
>> -		(q)->ops->op ? "" : " (nop)")
>> -
>> -#define call_qop(q, op, args...)					\
>> -({									\
>> -	int err;							\
>> -									\
>> -	log_qop(q, op);							\
>> -	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
>> -	if (!err)							\
>> -		(q)->cnt_ ## op++;					\
>> -	err;								\
>> -})
>> -
>> -#define call_void_qop(q, op, args...)					\
>> -({									\
>> -	log_qop(q, op);							\
>> -	if ((q)->ops->op)						\
>> -		(q)->ops->op(args);					\
>> -	(q)->cnt_ ## op++;						\
>> -})
>> -
>> -#define log_vb_qop(vb, op, args...)					\
>> -	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
>> -		(vb)->vb2_queue, (vb)->index, #op,			\
>> -		(vb)->vb2_queue->ops->op ? "" : " (nop)")
>> -
>> -#define call_vb_qop(vb, op, args...)					\
>> -({									\
>> -	int err;							\
>> -									\
>> -	log_vb_qop(vb, op);						\
>> -	err = (vb)->vb2_queue->ops->op ?				\
>> -		(vb)->vb2_queue->ops->op(args) : 0;			\
>> -	if (!err)							\
>> -		(vb)->cnt_ ## op++;					\
>> -	err;								\
>> -})
>> -
>> -#define call_void_vb_qop(vb, op, args...)				\
>> -({									\
>> -	log_vb_qop(vb, op);						\
>> -	if ((vb)->vb2_queue->ops->op)					\
>> -		(vb)->vb2_queue->ops->op(args);				\
>> -	(vb)->cnt_ ## op++;						\
>> -})
>> -
>> -#else
>> -
>> -#define call_memop(vb, op, args...)					\
>> -	((vb)->vb2_queue->mem_ops->op ?					\
>> -		(vb)->vb2_queue->mem_ops->op(args) : 0)
>> -
>> -#define call_ptr_memop(vb, op, args...)					\
>> -	((vb)->vb2_queue->mem_ops->op ?					\
>> -		(vb)->vb2_queue->mem_ops->op(args) : NULL)
>> -
>> -#define call_void_memop(vb, op, args...)				\
>> -	do {								\
>> -		if ((vb)->vb2_queue->mem_ops->op)			\
>> -			(vb)->vb2_queue->mem_ops->op(args);		\
>> -	} while (0)
>> -
>> -#define call_qop(q, op, args...)					\
>> -	((q)->ops->op ? (q)->ops->op(args) : 0)
>> -
>> -#define call_void_qop(q, op, args...)					\
>> -	do {								\
>> -		if ((q)->ops->op)					\
>> -			(q)->ops->op(args);				\
>> -	} while (0)
>> -
>> -#define call_vb_qop(vb, op, args...)					\
>> -	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
>> -
>> -#define call_void_vb_qop(vb, op, args...)				\
>> -	do {								\
>> -		if ((vb)->vb2_queue->ops->op)				\
>> -			(vb)->vb2_queue->ops->op(args);			\
>> -	} while (0)
>> -
>> -#endif
>> -
>> -/* Flags that are set by the vb2 core */
>> -#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
>> -				 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
>> -				 V4L2_BUF_FLAG_PREPARED | \
>> -				 V4L2_BUF_FLAG_TIMESTAMP_MASK)
>> -/* Output buffer flags that should be passed on to the driver */
>> -#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
>> -				 V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
>> +int vb2_debug;
>> +module_param_named(debug, vb2_debug, int, 0644);
>> +EXPORT_SYMBOL_GPL(vb2_debug);
>>
>>   static void __vb2_queue_cancel(struct vb2_queue *q);
>>   static void __enqueue_in_driver(struct vb2_buffer *vb);
>> @@ -193,7 +40,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
>>   {
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	enum dma_data_direction dma_dir =
>> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>> +			q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>>   	void *mem_priv;
>>   	int plane;
>>
>> @@ -249,7 +96,8 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
>>
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		if (vb->planes[plane].mem_priv)
>> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
>> +			call_void_memop(vb, put_userptr,
>> +					vb->planes[plane].mem_priv);
>>   		vb->planes[plane].mem_priv = NULL;
>>   	}
>>   }
>> @@ -347,7 +195,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>>    *
>>    * Returns the number of buffers successfully allocated.
>>    */
>> -static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>> +static int __vb2_queue_alloc(struct vb2_queue *q, unsigned int memory,
>>   			unsigned int num_buffers, unsigned int num_planes)
>>   {
>>   	unsigned int buffer;
>> @@ -370,7 +218,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>>   		vb->memory = memory;
>>
>>   		/* Allocate video buffer memory for the MMAP type */
>> -		if (memory == V4L2_MEMORY_MMAP) {
>> +		if (memory == VB2_MEMORY_MMAP) {
>
> Ok, that answers my implicit question on patch 2/5: you're actually
> defining a new enum for VB2.
>
> The right thing to do is to replace the
> 	unsigned int			memory;
>
> at struct vb2_queue by the right type, in order to enforce the type.
> The vb2_buffer comment then needs to be changed, as it currently
> references the types defined at videodev2.h.
>

OK, according to your comment, I will change memory field
at struct vb2_queue and struct vb2_buffer like:

	enum vb2_memory			memory;

As a member variable of vb2_queue and vb2_buffer, memory field will
be used by only videobuf2-core. The memory field will be translated in
videobuf2-v4l2. e.g V4L2_MEMORY_MMAP -> VB2_MEMORY_MMAP.
Actually, translation is not needed because the real values correspond 
with v4l2's values, and that is confirmed at vb2_queue_init().

int vb2_queue_init(struct vb2_queue *q)
{
	if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
		|| WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
		|| WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
		return -EINVAL;


>>   			ret = __vb2_buf_mem_alloc(vb);
>>   			if (ret) {
>>   				dprintk(1, "failed allocating memory for "
>> @@ -397,7 +245,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>>   	}
>>
>>   	__setup_lengths(q, buffer);
>> -	if (memory == V4L2_MEMORY_MMAP)
>> +	if (memory == VB2_MEMORY_MMAP)
>>   		__setup_offsets(q, buffer);
>>
>>   	dprintk(1, "allocated %d buffers, %d plane(s) each\n",
>> @@ -421,9 +269,9 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>>   			continue;
>>
>>   		/* Free MMAP buffers or release USERPTR buffers */
>> -		if (q->memory == V4L2_MEMORY_MMAP)
>> +		if (q->memory == VB2_MEMORY_MMAP)
>>   			__vb2_buf_mem_free(vb);
>> -		else if (q->memory == V4L2_MEMORY_DMABUF)
>> +		else if (q->memory == VB2_MEMORY_DMABUF)
>>   			__vb2_buf_dmabuf_put(vb);
>>   		else
>>   			__vb2_buf_userptr_put(vb);
>> @@ -547,75 +395,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>   }
>>
>>   /**
>> - * __verify_planes_array() - verify that the planes array passed in struct
>> - * v4l2_buffer from userspace can be safely used
>> - */
>> -static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> -{
>> -	if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
>> -		return 0;
>> -
>> -	/* Is memory for copying plane information present? */
>> -	if (NULL == b->m.planes) {
>> -		dprintk(1, "multi-planar buffer passed but "
>> -			   "planes array not provided\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
>> -		dprintk(1, "incorrect planes array length, "
>> -			   "expected %d, got %d\n", vb->num_planes, b->length);
>> -		return -EINVAL;
>> -	}
>> -
>> -	return 0;
>> -}
>> -
>> -/**
>> - * __verify_length() - Verify that the bytesused value for each plane fits in
>> - * the plane length and that the data offset doesn't exceed the bytesused value.
>> - */
>> -static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> -{
>> -	unsigned int length;
>> -	unsigned int bytesused;
>> -	unsigned int plane;
>> -
>> -	if (!V4L2_TYPE_IS_OUTPUT(b->type))
>> -		return 0;
>> -
>> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>> -		for (plane = 0; plane < vb->num_planes; ++plane) {
>> -			length = (b->memory == V4L2_MEMORY_USERPTR ||
>> -				b->memory == V4L2_MEMORY_DMABUF)
>> -				? b->m.planes[plane].length
>> -				: vb->planes[plane].length;
>> -			bytesused = b->m.planes[plane].bytesused
>> -				? b->m.planes[plane].bytesused : length;
>> -
>> -			if (b->m.planes[plane].bytesused > length)
>> -				return -EINVAL;
>> -
>> -			if (b->m.planes[plane].data_offset > 0 &&
>> -				b->m.planes[plane].data_offset >= bytesused)
>> -				return -EINVAL;
>> -		}
>> -	} else {
>> -		length = (b->memory == V4L2_MEMORY_USERPTR)
>> -			? b->length : vb->planes[0].length;
>> -
>> -		if (b->bytesused > length)
>> -			return -EINVAL;
>> -	}
>> -
>> -	return 0;
>> -}
>> -
>> -/**
>> - * __buffer_in_use() - return true if the buffer is in use and
>> + * vb2_buffer_in_use() - return true if the buffer is in use and
>>    * the queue cannot be freed (by the means of REQBUFS(0)) call
>>    */
>> -static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>>   {
>>   	unsigned int plane;
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>> @@ -631,6 +414,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>>   	}
>>   	return false;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_buffer_in_use);
>>
>>   /**
>>    * __buffers_in_use() - return true if any buffers on the queue are in use and
>> @@ -640,142 +424,26 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>   {
>>   	unsigned int buffer;
>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		if (__buffer_in_use(q, q->bufs[buffer]))
>> +		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>>   			return true;
>>   	}
>>   	return false;
>>   }
>>
>>   /**
>> - * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
>> - * returned to userspace
>> - */
>> -static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>> -{
>> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> -	struct vb2_queue *q = vb->vb2_queue;
>> -	unsigned int plane;
>> -
>> -	/* Copy back data such as timestamp, flags, etc. */
>> -	b->index = vb->index;
>> -	b->type = vb->type;
>> -	b->memory = vb->memory;
>> -	b->bytesused = 0;
>> -
>> -	b->flags = vbuf->flags;
>> -	b->field = vbuf->field;
>> -	b->timestamp = vbuf->timestamp;
>> -	b->timecode = vbuf->timecode;
>> -	b->sequence = vbuf->sequence;
>> -
>> -	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>> -		/*
>> -		 * Fill in plane-related data if userspace provided an array
>> -		 * for it. The caller has already verified memory and size.
>> -		 */
>> -		b->length = vb->num_planes;
>> -		for (plane = 0; plane < vb->num_planes; ++plane) {
>> -			struct v4l2_plane *pdst = &b->m.planes[plane];
>> -			struct vb2_plane *psrc = &vb->planes[plane];
>> -
>> -			pdst->bytesused = psrc->bytesused;
>> -			pdst->length = psrc->length;
>> -			if (q->memory == V4L2_MEMORY_MMAP)
>> -				pdst->m.mem_offset = psrc->m.offset;
>> -			else if (q->memory == V4L2_MEMORY_USERPTR)
>> -				pdst->m.userptr = psrc->m.userptr;
>> -			else if (q->memory == V4L2_MEMORY_DMABUF)
>> -				pdst->m.fd = psrc->m.fd;
>> -			pdst->data_offset = psrc->data_offset;
>> -		}
>> -	} else {
>> -		/*
>> -		 * We use length and offset in v4l2_planes array even for
>> -		 * single-planar buffers, but userspace does not.
>> -		 */
>> -		b->length = vb->planes[0].length;
>> -		b->bytesused = vb->planes[0].bytesused;
>> -		if (q->memory == V4L2_MEMORY_MMAP)
>> -			b->m.offset = vb->planes[0].m.offset;
>> -		else if (q->memory == V4L2_MEMORY_USERPTR)
>> -			b->m.userptr = vb->planes[0].m.userptr;
>> -		else if (q->memory == V4L2_MEMORY_DMABUF)
>> -			b->m.fd = vb->planes[0].m.fd;
>> -	}
>> -
>> -	/*
>> -	 * Clear any buffer state related flags.
>> -	 */
>> -	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>> -	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>> -	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> -			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>> -		/*
>> -		 * For non-COPY timestamps, drop timestamp source bits
>> -		 * and obtain the timestamp source from the queue.
>> -		 */
>> -		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> -		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> -	}
>> -
>> -	switch (vb->state) {
>> -	case VB2_BUF_STATE_QUEUED:
>> -	case VB2_BUF_STATE_ACTIVE:
>> -		b->flags |= V4L2_BUF_FLAG_QUEUED;
>> -		break;
>> -	case VB2_BUF_STATE_ERROR:
>> -		b->flags |= V4L2_BUF_FLAG_ERROR;
>> -		/* fall through */
>> -	case VB2_BUF_STATE_DONE:
>> -		b->flags |= V4L2_BUF_FLAG_DONE;
>> -		break;
>> -	case VB2_BUF_STATE_PREPARED:
>> -		b->flags |= V4L2_BUF_FLAG_PREPARED;
>> -		break;
>> -	case VB2_BUF_STATE_PREPARING:
>> -	case VB2_BUF_STATE_DEQUEUED:
>> -		/* nothing */
>> -		break;
>> -	}
>> -
>> -	if (__buffer_in_use(q, vb))
>> -		b->flags |= V4L2_BUF_FLAG_MAPPED;
>> -}
>> -
>> -/**
>> - * vb2_querybuf() - query video buffer information
>> + * vb2_core_querybuf() - query video buffer information
>>    * @q:		videobuf queue
>> + * @index:	id number of the buffer
>>    * @b:		buffer struct passed from userspace to vidioc_querybuf handler
>>    *		in driver
>> - *
>> - * Should be called from vidioc_querybuf ioctl handler in driver.
>> - * This function will verify the passed v4l2_buffer structure and fill the
>> - * relevant information for the userspace.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_querybuf handler in driver.
>>    */
>> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>>   {
>> -	struct vb2_buffer *vb;
>> -	int ret;
>> -
>> -	if (b->type != q->type) {
>> -		dprintk(1, "wrong buffer type\n");
>> -		return -EINVAL;
>> -	}
>> +	call_bufop(q, fill_user_buffer, q->bufs[index], pb);
>>
>> -	if (b->index >= q->num_buffers) {
>> -		dprintk(1, "buffer index out of range\n");
>> -		return -EINVAL;
>> -	}
>> -	vb = q->bufs[b->index];
>> -	ret = __verify_planes_array(vb, b);
>> -	if (!ret)
>> -		__fill_v4l2_buffer(vb, b);
>> -	return ret;
>> +	return 0;
>>   }
>> -EXPORT_SYMBOL(vb2_querybuf);
>> +EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>>
>>   /**
>>    * __verify_userptr_ops() - verify that all memory operations required for
>> @@ -818,14 +486,14 @@ static int __verify_dmabuf_ops(struct vb2_queue *q)
>>   }
>>
>>   /**
>> - * __verify_memory_type() - Check whether the memory type and buffer type
>> + * vb2_verify_memory_type() - Check whether the memory type and buffer type
>>    * passed to a buffer operation are compatible with the queue.
>>    */
>> -static int __verify_memory_type(struct vb2_queue *q,
>> -		enum v4l2_memory memory, enum v4l2_buf_type type)
>> +int vb2_verify_memory_type(struct vb2_queue *q,
>> +		unsigned int memory, unsigned int type)
>>   {
>> -	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
>> -			memory != V4L2_MEMORY_DMABUF) {
>> +	if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
>> +		memory != VB2_MEMORY_DMABUF) {
>>   		dprintk(1, "unsupported memory type\n");
>>   		return -EINVAL;
>>   	}
>> @@ -839,37 +507,30 @@ static int __verify_memory_type(struct vb2_queue *q,
>>   	 * Make sure all the required memory ops for given memory type
>>   	 * are available.
>>   	 */
>> -	if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
>> +	if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
>>   		dprintk(1, "MMAP for current setup unsupported\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
>> +	if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
>>   		dprintk(1, "USERPTR for current setup unsupported\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
>> +	if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
>>   		dprintk(1, "DMABUF for current setup unsupported\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	/*
>> -	 * Place the busy tests at the end: -EBUSY can be ignored when
>> -	 * create_bufs is called with count == 0, but count == 0 should still
>> -	 * do the memory and type validation.
>> -	 */
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>>   	return 0;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_verify_memory_type);
>>
>>   /**
>> - * __reqbufs() - Initiate streaming
>> + * vb2_core_reqbufs() - Initiate streaming
>>    * @q:		videobuf2 queue
>> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
>> + * @memory:
>> + * @count:
>>    *
>>    * Should be called from vidioc_reqbufs ioctl handler of a driver.
>>    * This function:
>> @@ -889,7 +550,8 @@ static int __verify_memory_type(struct vb2_queue *q,
>>    * The return values from this function are intended to be directly returned
>>    * from vidioc_reqbufs handler in driver.
>>    */
>> -static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
>> +		unsigned int *count)
>>   {
>>   	unsigned int num_buffers, allocated_buffers, num_planes = 0;
>>   	int ret;
>> @@ -899,13 +561,13 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   		return -EBUSY;
>>   	}
>>
>> -	if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
>> +	if (*count == 0 || q->num_buffers != 0 || q->memory != memory) {
>>   		/*
>>   		 * We already have buffers allocated, so first check if they
>>   		 * are not in use and can be freed.
>>   		 */
>>   		mutex_lock(&q->mmap_lock);
>> -		if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) {
>> +		if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
>>   			mutex_unlock(&q->mmap_lock);
>>   			dprintk(1, "memory in use, cannot free\n");
>>   			return -EBUSY;
>> @@ -926,18 +588,18 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   		 * In case of REQBUFS(0) return immediately without calling
>>   		 * driver's queue_setup() callback and allocating resources.
>>   		 */
>> -		if (req->count == 0)
>> +		if (*count == 0)
>>   			return 0;
>>   	}
>>
>>   	/*
>>   	 * Make sure the requested values and current defaults are sane.
>>   	 */
>> -	num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
>> +	num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME);
>>   	num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed);
>>   	memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
>>   	memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
>> -	q->memory = req->memory;
>> +	q->memory = memory;
>>
>>   	/*
>>   	 * Ask the driver how many buffers and planes per buffer it requires.
>> @@ -949,7 +611,8 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   		return ret;
>>
>>   	/* Finally, allocate buffers and video memory */
>> -	allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
>> +	allocated_buffers =
>> +		__vb2_queue_alloc(q, memory, num_buffers, num_planes);
>>   	if (allocated_buffers == 0) {
>>   		dprintk(1, "memory allocation failed\n");
>>   		return -ENOMEM;
>> @@ -998,28 +661,15 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   	 * Return the number of successfully allocated buffers
>>   	 * to the userspace.
>>   	 */
>> -	req->count = allocated_buffers;
>> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
>> +	*count = allocated_buffers;
>> +	q->waiting_for_buffers = !q->is_output;
>>
>>   	return 0;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
>>
>>   /**
>> - * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and
>> - * type values.
>> - * @q:		videobuf2 queue
>> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
>> - */
>> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>> -{
>> -	int ret = __verify_memory_type(q, req->memory, req->type);
>> -
>> -	return ret ? ret : __reqbufs(q, req);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_reqbufs);
>> -
>> -/**
>> - * __create_bufs() - Allocate buffers and any required auxiliary structs
>> + * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs
>>    * @q:		videobuf2 queue
>>    * @create:	creation parameters, passed from userspace to vidioc_create_bufs
>>    *		handler in driver
>> @@ -1033,12 +683,13 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs);
>>    * The return values from this function are intended to be directly returned
>>    * from vidioc_create_bufs handler in driver.
>>    */
>> -static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
>> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
>> +		unsigned int *count, void *parg)
>>   {
>>   	unsigned int num_planes = 0, num_buffers, allocated_buffers;
>>   	int ret;
>>
>> -	if (q->num_buffers == VIDEO_MAX_FRAME) {
>> +	if (q->num_buffers == VB2_MAX_FRAME) {
>>   		dprintk(1, "maximum number of buffers already allocated\n");
>>   		return -ENOBUFS;
>>   	}
>> @@ -1046,23 +697,23 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   	if (!q->num_buffers) {
>>   		memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
>>   		memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
>> -		q->memory = create->memory;
>> -		q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
>> +		q->memory = memory;
>> +		q->waiting_for_buffers = !q->is_output;
>>   	}
>>
>> -	num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
>> +	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
>>
>>   	/*
>>   	 * Ask the driver, whether the requested number of buffers, planes per
>>   	 * buffer and their sizes are acceptable
>>   	 */
>> -	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>> +	ret = call_qop(q, queue_setup, q, parg, &num_buffers,
>>   			&num_planes, q->plane_sizes, q->alloc_ctx);
>>   	if (ret)
>>   		return ret;
>>
>>   	/* Finally, allocate buffers and video memory */
>> -	allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers,
>> +	allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
>>   				num_planes);
>>   	if (allocated_buffers == 0) {
>>   		dprintk(1, "memory allocation failed\n");
>> @@ -1079,7 +730,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   		 * q->num_buffers contains the total number of buffers, that the
>>   		 * queue driver has set up
>>   		 */
>> -		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>> +		ret = call_qop(q, queue_setup, q, parg, &num_buffers,
>>   				&num_planes, q->plane_sizes, q->alloc_ctx);
>>
>>   		if (!ret && allocated_buffers < num_buffers)
>> @@ -1109,28 +760,11 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   	 * Return the number of successfully allocated buffers
>>   	 * to the userspace.
>>   	 */
>> -	create->count = allocated_buffers;
>> +	*count = allocated_buffers;
>>
>>   	return 0;
>>   }
>> -
>> -/**
>> - * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the
>> - * memory and type values.
>> - * @q:		videobuf2 queue
>> - * @create:	creation parameters, passed from userspace to vidioc_create_bufs
>> - *		handler in driver
>> - */
>> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
>> -{
>> -	int ret = __verify_memory_type(q, create->memory, create->format.type);
>> -
>> -	create->index = q->num_buffers;
>> -	if (create->count == 0)
>> -		return ret != -EBUSY ? ret : 0;
>> -	return ret ? ret : __create_bufs(q, create);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_create_bufs);
>> +EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
>>
>>   /**
>>    * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
>> @@ -1263,7 +897,7 @@ void vb2_discard_done(struct vb2_queue *q)
>>   }
>>   EXPORT_SYMBOL_GPL(vb2_discard_done);
>>
>> -static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>>   {
>>   	static bool __check_once __read_mostly;
>>
>> @@ -1279,162 +913,34 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>>   	else
>>   		pr_warn_once("use the actual size instead.\n");
>>   }
>> -
>> -/**
>> - * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
>> - * v4l2_buffer by the userspace. The caller has already verified that struct
>> - * v4l2_buffer has a valid number of planes.
>> - */
>> -static void __fill_vb2_buffer(struct vb2_buffer *vb,
>> -		const struct v4l2_buffer *b, struct vb2_plane *planes)
>> -{
>> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> -	unsigned int plane;
>> -
>> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>> -		if (b->memory == V4L2_MEMORY_USERPTR) {
>> -			for (plane = 0; plane < vb->num_planes; ++plane) {
>> -				planes[plane].m.userptr =
>> -					b->m.planes[plane].m.userptr;
>> -				planes[plane].length =
>> -					b->m.planes[plane].length;
>> -			}
>> -		}
>> -		if (b->memory == V4L2_MEMORY_DMABUF) {
>> -			for (plane = 0; plane < vb->num_planes; ++plane) {
>> -				planes[plane].m.fd =
>> -					b->m.planes[plane].m.fd;
>> -				planes[plane].length =
>> -					b->m.planes[plane].length;
>> -			}
>> -		}
>> -
>> -		/* Fill in driver-provided information for OUTPUT types */
>> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> -			/*
>> -			 * Will have to go up to b->length when API starts
>> -			 * accepting variable number of planes.
>> -			 *
>> -			 * If bytesused == 0 for the output buffer, then fall
>> -			 * back to the full buffer size. In that case
>> -			 * userspace clearly never bothered to set it and
>> -			 * it's a safe assumption that they really meant to
>> -			 * use the full plane sizes.
>> -			 *
>> -			 * Some drivers, e.g. old codec drivers, use bytesused == 0
>> -			 * as a way to indicate that streaming is finished.
>> -			 * In that case, the driver should use the
>> -			 * allow_zero_bytesused flag to keep old userspace
>> -			 * applications working.
>> -			 */
>> -			for (plane = 0; plane < vb->num_planes; ++plane) {
>> -				struct vb2_plane *pdst = &planes[plane];
>> -				struct v4l2_plane *psrc = &b->m.planes[plane];
>> -
>> -				if (psrc->bytesused == 0)
>> -					vb2_warn_zero_bytesused(vb);
>> -
>> -				if (vb->vb2_queue->allow_zero_bytesused)
>> -					pdst->bytesused = psrc->bytesused;
>> -				else
>> -					pdst->bytesused = psrc->bytesused ?
>> -						psrc->bytesused : pdst->length;
>> -				pdst->data_offset = psrc->data_offset;
>> -			}
>> -		}
>> -	} else {
>> -		/*
>> -		 * Single-planar buffers do not use planes array,
>> -		 * so fill in relevant v4l2_buffer struct fields instead.
>> -		 * In videobuf we use our internal V4l2_planes struct for
>> -		 * single-planar buffers as well, for simplicity.
>> -		 *
>> -		 * If bytesused == 0 for the output buffer, then fall back
>> -		 * to the full buffer size as that's a sensible default.
>> -		 *
>> -		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
>> -		 * a way to indicate that streaming is finished. In that case,
>> -		 * the driver should use the allow_zero_bytesused flag to keep
>> -		 * old userspace applications working.
>> -		 */
>> -		if (b->memory == V4L2_MEMORY_USERPTR) {
>> -			planes[0].m.userptr = b->m.userptr;
>> -			planes[0].length = b->length;
>> -		}
>> -
>> -		if (b->memory == V4L2_MEMORY_DMABUF) {
>> -			planes[0].m.fd = b->m.fd;
>> -			planes[0].length = b->length;
>> -		}
>> -
>> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> -			if (b->bytesused == 0)
>> -				vb2_warn_zero_bytesused(vb);
>> -
>> -			if (vb->vb2_queue->allow_zero_bytesused)
>> -				planes[0].bytesused = b->bytesused;
>> -			else
>> -				planes[0].bytesused = b->bytesused ?
>> -					b->bytesused : planes[0].length;
>> -		} else
>> -			planes[0].bytesused = 0;
>> -
>> -	}
>> -
>> -	/* Zero flags that the vb2 core handles */
>> -	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
>> -	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> -			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
>> -			!V4L2_TYPE_IS_OUTPUT(b->type)) {
>> -		/*
>> -		 * Non-COPY timestamps and non-OUTPUT queues will get
>> -		 * their timestamp and timestamp source flags from the
>> -		 * queue.
>> -		 */
>> -		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> -	}
>> -
>> -	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> -		/*
>> -		 * For output buffers mask out the timecode flag:
>> -		 * this will be handled later in vb2_internal_qbuf().
>> -		 * The 'field' is valid metadata for this output buffer
>> -		 * and so that needs to be copied here.
>> -		 */
>> -		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
>> -		vbuf->field = b->field;
>> -	} else {
>> -		/* Zero any output buffer flags as this is a capture buffer */
>> -		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
>> -	}
>> -}
>> +EXPORT_SYMBOL_GPL(vb2_warn_zero_bytesused);
>>
>>   /**
>>    * __qbuf_mmap() - handle qbuf of an MMAP buffer
>>    */
>> -static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +static int __qbuf_mmap(struct vb2_buffer *vb, void *pb)
>>   {
>> -	__fill_vb2_buffer(vb, b, vb->planes);
>> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, vb->planes);
>>   	return call_vb_qop(vb, buf_prepare, vb);
>>   }
>>
>>   /**
>>    * __qbuf_userptr() - handle qbuf of a USERPTR buffer
>>    */
>> -static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +static int __qbuf_userptr(struct vb2_buffer *vb, void *pb)
>>   {
>> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
>> +	struct vb2_plane planes[VB2_MAX_PLANES];
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	void *mem_priv;
>>   	unsigned int plane;
>>   	int ret;
>>   	enum dma_data_direction dma_dir =
>> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>>   	bool reacquired = vb->planes[0].mem_priv == NULL;
>>
>>   	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
>>   	/* Copy relevant information provided by the userspace */
>> -	__fill_vb2_buffer(vb, b, planes);
>> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
>>
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		/* Skip the plane if already verified */
>> @@ -1462,7 +968,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   				reacquired = true;
>>   				call_void_vb_qop(vb, buf_cleanup, vb);
>>   			}
>> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
>> +			call_void_memop(vb, put_userptr,
>> +					vb->planes[plane].mem_priv);
>>   		}
>>
>>   		vb->planes[plane].mem_priv = NULL;
>> @@ -1533,20 +1040,20 @@ err:
>>   /**
>>    * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
>>    */
>> -static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +static int __qbuf_dmabuf(struct vb2_buffer *vb, void *pb)
>>   {
>> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
>> +	struct vb2_plane planes[VB2_MAX_PLANES];
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	void *mem_priv;
>>   	unsigned int plane;
>>   	int ret;
>>   	enum dma_data_direction dma_dir =
>> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>>   	bool reacquired = vb->planes[0].mem_priv == NULL;
>>
>>   	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
>>   	/* Copy relevant information provided by the userspace */
>> -	__fill_vb2_buffer(vb, b, planes);
>> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
>>
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
>> @@ -1591,9 +1098,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   		vb->planes[plane].data_offset = 0;
>>
>>   		/* Acquire each plane's memory */
>> -		mem_priv = call_ptr_memop(vb, attach_dmabuf,
>> -			q->alloc_ctx[plane], dbuf, planes[plane].length,
>> -			dma_dir);
>> +		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
>> +			dbuf, planes[plane].length, dma_dir);
>>   		if (IS_ERR(mem_priv)) {
>>   			dprintk(1, "failed to attach dmabuf\n");
>>   			ret = PTR_ERR(mem_priv);
>> @@ -1626,7 +1132,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		vb->planes[plane].bytesused = planes[plane].bytesused;
>>   		vb->planes[plane].length = planes[plane].length;
>> -		vb->planes[plane].m.fd = planes[plane].m.userptr;
>> +		vb->planes[plane].m.fd = planes[plane].m.fd;
>>   		vb->planes[plane].data_offset = planes[plane].data_offset;
>>   	}
>>
>> @@ -1677,52 +1183,27 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
>>   	call_void_vb_qop(vb, buf_queue, vb);
>>   }
>>
>> -static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +static int __buf_prepare(struct vb2_buffer *vb, void *pb)
>>   {
>> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	int ret;
>>
>> -	ret = __verify_length(vb, b);
>> -	if (ret < 0) {
>> -		dprintk(1, "plane parameters verification failed: %d\n", ret);
>> -		return ret;
>> -	}
>> -	if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) {
>> -		/*
>> -		 * If the format's field is ALTERNATE, then the buffer's field
>> -		 * should be either TOP or BOTTOM, not ALTERNATE since that
>> -		 * makes no sense. The driver has to know whether the
>> -		 * buffer represents a top or a bottom field in order to
>> -		 * program any DMA correctly. Using ALTERNATE is wrong, since
>> -		 * that just says that it is either a top or a bottom field,
>> -		 * but not which of the two it is.
>> -		 */
>> -		dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
>> -		return -EINVAL;
>> -	}
>> -
>>   	if (q->error) {
>>   		dprintk(1, "fatal error occurred on queue\n");
>>   		return -EIO;
>>   	}
>>
>> -	vb->state = VB2_BUF_STATE_PREPARING;
>> -	vbuf->timestamp.tv_sec = 0;
>> -	vbuf->timestamp.tv_usec = 0;
>> -	vbuf->sequence = 0;
>> -
>>   	switch (q->memory) {
>> -	case V4L2_MEMORY_MMAP:
>> -		ret = __qbuf_mmap(vb, b);
>> +	case VB2_MEMORY_MMAP:
>> +		ret = __qbuf_mmap(vb, pb);
>>   		break;
>> -	case V4L2_MEMORY_USERPTR:
>> +	case VB2_MEMORY_USERPTR:
>>   		down_read(&current->mm->mmap_sem);
>> -		ret = __qbuf_userptr(vb, b);
>> +		ret = __qbuf_userptr(vb, pb);
>>   		up_read(&current->mm->mmap_sem);
>>   		break;
>> -	case V4L2_MEMORY_DMABUF:
>> -		ret = __qbuf_dmabuf(vb, b);
>> +	case VB2_MEMORY_DMABUF:
>> +		ret = __qbuf_dmabuf(vb, pb);
>>   		break;
>>   	default:
>>   		WARN(1, "Invalid queue type\n");
>> @@ -1736,35 +1217,56 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   	return ret;
>>   }
>>
>> -static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
>> -					const char *opname)
>> +int vb2_verify_buffer(struct vb2_queue *q,
>> +			unsigned int memory, unsigned int type,
>> +			unsigned int index, unsigned int nplanes,
>> +			void *pplane, const char *opname)
>>   {
>> -	if (b->type != q->type) {
>> +	if (type != q->type) {
>>   		dprintk(1, "%s: invalid buffer type\n", opname);
>>   		return -EINVAL;
>>   	}
>>
>> -	if (b->index >= q->num_buffers) {
>> +	if (index >= q->num_buffers) {
>>   		dprintk(1, "%s: buffer index out of range\n", opname);
>>   		return -EINVAL;
>>   	}
>>
>> -	if (q->bufs[b->index] == NULL) {
>> +	if (q->bufs[index] == NULL) {
>>   		/* Should never happen */
>>   		dprintk(1, "%s: buffer is NULL\n", opname);
>>   		return -EINVAL;
>>   	}
>>
>> -	if (b->memory != q->memory) {
>> +	if (memory != VB2_MEMORY_UNKNOWN && memory != q->memory) {
>>   		dprintk(1, "%s: invalid memory type\n", opname);
>>   		return -EINVAL;
>>   	}
>>
>> -	return __verify_planes_array(q->bufs[b->index], b);
>> +	if (q->is_multiplanar) {
>> +		struct vb2_buffer *vb = q->bufs[index];
>> +
>> +		/* Is memory for copying plane information present? */
>> +		if (NULL == pplane) {
>> +			dprintk(1, "%s: multi-planar buffer passed but "
>> +				"planes array not provided\n", opname);
>> +			return -EINVAL;
>> +		}
>> +
>> +		if (nplanes < vb->num_planes || nplanes > VB2_MAX_PLANES) {
>> +			dprintk(1, "%s: incorrect planes array length, "
>> +				"expected %d, got %d\n",
>> +				opname, vb->num_planes, nplanes);
>> +			return -EINVAL;
>> +		}
>> +	}
>> +
>> +	return 0;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_verify_buffer);
>>
>>   /**
>> - * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
>> + * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
>>    * @q:		videobuf2 queue
>>    * @b:		buffer structure passed from userspace to vidioc_prepare_buf
>>    *		handler in driver
>> @@ -1778,37 +1280,28 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
>>    * The return values from this function are intended to be directly returned
>>    * from vidioc_prepare_buf handler in driver.
>>    */
>> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>>   {
>>   	struct vb2_buffer *vb;
>>   	int ret;
>>
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -
>> -	ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
>> -	if (ret)
>> -		return ret;
>> -
>> -	vb = q->bufs[b->index];
>> +	vb = q->bufs[index];
>>   	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>>   		dprintk(1, "invalid buffer state %d\n",
>>   			vb->state);
>>   		return -EINVAL;
>>   	}
>>
>> -	ret = __buf_prepare(vb, b);
>> +	ret = __buf_prepare(vb, pb);
>>   	if (!ret) {
>>   		/* Fill buffer information for the userspace */
>> -		__fill_v4l2_buffer(vb, b);
>> +		call_bufop(q, fill_user_buffer, vb, pb);
>>
>>   		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
>>   	}
>>   	return ret;
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_prepare_buf);
>> +EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
>>
>>   /**
>>    * vb2_start_streaming() - Attempt to start streaming.
>> @@ -1873,21 +1366,16 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>   	return ret;
>>   }
>>
>> -static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
>>   {
>> -	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
>> +	int ret;
>>   	struct vb2_buffer *vb;
>> -	struct vb2_v4l2_buffer *vbuf;
>> -
>> -	if (ret)
>> -		return ret;
>>
>> -	vb = q->bufs[b->index];
>> -	vbuf = to_vb2_v4l2_buffer(vb);
>> +	vb = q->bufs[index];
>>
>>   	switch (vb->state) {
>>   	case VB2_BUF_STATE_DEQUEUED:
>> -		ret = __buf_prepare(vb, b);
>> +		ret = __buf_prepare(vb, pb);
>>   		if (ret)
>>   			return ret;
>>   		break;
>> @@ -1909,18 +1397,9 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   	q->queued_count++;
>>   	q->waiting_for_buffers = false;
>>   	vb->state = VB2_BUF_STATE_QUEUED;
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
>> -		/*
>> -		 * For output buffers copy the timestamp if needed,
>> -		 * and the timecode field and flag if needed.
>> -		 */
>> -		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> -				V4L2_BUF_FLAG_TIMESTAMP_COPY)
>> -			vbuf->timestamp = b->timestamp;
>> -		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
>> -		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
>> -			vbuf->timecode = b->timecode;
>> -	}
>> +
>> +	if (q->is_output)
>> +		call_bufop(q, fill_vb2_timestamp, vb, pb);
>>
>>   	trace_vb2_qbuf(q, vb);
>>
>> @@ -1932,7 +1411,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   		__enqueue_in_driver(vb);
>>
>>   	/* Fill buffer information for the userspace */
>> -	__fill_v4l2_buffer(vb, b);
>> +	call_bufop(q, fill_user_buffer, vb, pb);
>>
>>   	/*
>>   	 * If streamon has been called, and we haven't yet called
>> @@ -1950,34 +1429,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
>>   	return 0;
>>   }
>> -
>> -/**
>> - * vb2_qbuf() - Queue a buffer from userspace
>> - * @q:		videobuf2 queue
>> - * @b:		buffer structure passed from userspace to vidioc_qbuf handler
>> - *		in driver
>> - *
>> - * Should be called from vidioc_qbuf ioctl handler of a driver.
>> - * This function:
>> - * 1) verifies the passed buffer,
>> - * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
>> - *    which driver-specific buffer initialization can be performed,
>> - * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
>> - *    callback for processing.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_qbuf handler in driver.
>> - */
>> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> -{
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -
>> -	return vb2_internal_qbuf(q, b);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_qbuf);
>> +EXPORT_SYMBOL_GPL(vb2_core_qbuf);
>>
>>   /**
>>    * __vb2_wait_for_done_vb() - wait for a buffer to become available
>> @@ -2061,7 +1513,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
>>    * Will sleep if required for nonblocking == false.
>>    */
>>   static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
>> -				struct v4l2_buffer *b, int nonblocking)
>> +				int nonblocking)
>>   {
>>   	unsigned long flags;
>>   	int ret;
>> @@ -2082,10 +1534,11 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
>>   	/*
>>   	 * Only remove the buffer from done_list if v4l2_buffer can handle all
>>   	 * the planes.
>> +	 * ret = __verify_planes_array(*vb, pb);
>> +	 * But, actually that's unnecessary since this is checked already
>> +	 * before the buffer is queued/prepared. So it can never fails
>>   	 */
>> -	ret = __verify_planes_array(*vb, b);
>> -	if (!ret)
>> -		list_del(&(*vb)->done_entry);
>> +	list_del(&(*vb)->done_entry);
>>   	spin_unlock_irqrestore(&q->done_lock, flags);
>>
>>   	return ret;
>> @@ -2128,27 +1581,22 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
>>   	vb->state = VB2_BUF_STATE_DEQUEUED;
>>
>>   	/* unmap DMABUF buffer */
>> -	if (q->memory == V4L2_MEMORY_DMABUF)
>> +	if (q->memory == VB2_MEMORY_DMABUF)
>>   		for (i = 0; i < vb->num_planes; ++i) {
>>   			if (!vb->planes[i].dbuf_mapped)
>>   				continue;
>> -			call_void_memop(vb, unmap_dmabuf, vb->planes[i].mem_priv);
>> +			call_void_memop(vb, unmap_dmabuf,
>> +					vb->planes[i].mem_priv);
>>   			vb->planes[i].dbuf_mapped = 0;
>>   		}
>>   }
>>
>> -static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>> -		bool nonblocking)
>> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
>>   {
>>   	struct vb2_buffer *vb = NULL;
>> -	struct vb2_v4l2_buffer *vbuf = NULL;
>>   	int ret;
>>
>> -	if (b->type != q->type) {
>> -		dprintk(1, "invalid buffer type\n");
>> -		return -EINVAL;
>> -	}
>> -	ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
>> +	ret = __vb2_get_done_vb(q, &vb, nonblocking);
>>   	if (ret < 0)
>>   		return ret;
>>
>> @@ -2167,16 +1615,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>>   	call_void_vb_qop(vb, buf_finish, vb);
>>
>>   	/* Fill buffer information for the userspace */
>> -	__fill_v4l2_buffer(vb, b);
>> +	call_bufop(q, fill_user_buffer, vb, pb);
>>   	/* Remove from videobuf queue */
>>   	list_del(&vb->queued_entry);
>>   	q->queued_count--;
>>
>>   	trace_vb2_dqbuf(q, vb);
>>
>> -	vbuf = to_vb2_v4l2_buffer(vb);
>> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
>> -			vbuf->flags & V4L2_BUF_FLAG_LAST)
>> +	if (!q->is_output &&
>> +			call_bufop(q, is_last, vb))
>>   		q->last_buffer_dequeued = true;
>>   	/* go back to dequeued state */
>>   	__vb2_dqbuf(vb);
>> @@ -2186,37 +1633,7 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>>
>>   	return 0;
>>   }
>> -
>> -/**
>> - * vb2_dqbuf() - Dequeue a buffer to the userspace
>> - * @q:		videobuf2 queue
>> - * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
>> - *		in driver
>> - * @nonblocking: if true, this call will not sleep waiting for a buffer if no
>> - *		 buffers ready for dequeuing are present. Normally the driver
>> - *		 would be passing (file->f_flags & O_NONBLOCK) here
>> - *
>> - * Should be called from vidioc_dqbuf ioctl handler of a driver.
>> - * This function:
>> - * 1) verifies the passed buffer,
>> - * 2) calls buf_finish callback in the driver (if provided), in which
>> - *    driver can perform any additional operations that may be required before
>> - *    returning the buffer to userspace, such as cache sync,
>> - * 3) the buffer struct members are filled with relevant information for
>> - *    the userspace.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_dqbuf handler in driver.
>> - */
>> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
>> -{
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -	return vb2_internal_dqbuf(q, b, nonblocking);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_dqbuf);
>> +EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
>>
>>   /**
>>    * __vb2_queue_cancel() - cancel and stop (pause) streaming
>> @@ -2286,15 +1703,10 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>   	}
>>   }
>>
>> -static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>> +int vb2_core_streamon(struct vb2_queue *q)
>>   {
>>   	int ret;
>>
>> -	if (type != q->type) {
>> -		dprintk(1, "invalid stream type\n");
>> -		return -EINVAL;
>> -	}
>> -
>>   	if (q->streaming) {
>>   		dprintk(3, "already streaming\n");
>>   		return 0;
>> @@ -2328,6 +1740,7 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>>   	dprintk(3, "successful\n");
>>   	return 0;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_core_streamon);
>>
>>   /**
>>    * vb2_queue_error() - signal a fatal error on the queue
>> @@ -2350,36 +1763,8 @@ void vb2_queue_error(struct vb2_queue *q)
>>   }
>>   EXPORT_SYMBOL_GPL(vb2_queue_error);
>>
>> -/**
>> - * vb2_streamon - start streaming
>> - * @q:		videobuf2 queue
>> - * @type:	type argument passed from userspace to vidioc_streamon handler
>> - *
>> - * Should be called from vidioc_streamon handler of a driver.
>> - * This function:
>> - * 1) verifies current state
>> - * 2) passes any previously queued buffers to the driver and starts streaming
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_streamon handler in the driver.
>> - */
>> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>> -{
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -	return vb2_internal_streamon(q, type);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_streamon);
>> -
>> -static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>> +int vb2_core_streamoff(struct vb2_queue *q)
>>   {
>> -	if (type != q->type) {
>> -		dprintk(1, "invalid stream type\n");
>> -		return -EINVAL;
>> -	}
>> -
>>   	/*
>>   	 * Cancel will pause streaming and remove all buffers from the driver
>>   	 * and videobuf, effectively returning control over them to userspace.
>> @@ -2390,37 +1775,13 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>>   	 * their normal dequeued state.
>>   	 */
>>   	__vb2_queue_cancel(q);
>> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
>> +	q->waiting_for_buffers = !q->is_output;
>>   	q->last_buffer_dequeued = false;
>>
>>   	dprintk(3, "successful\n");
>>   	return 0;
>>   }
>> -
>> -/**
>> - * vb2_streamoff - stop streaming
>> - * @q:		videobuf2 queue
>> - * @type:	type argument passed from userspace to vidioc_streamoff handler
>> - *
>> - * Should be called from vidioc_streamoff handler of a driver.
>> - * This function:
>> - * 1) verifies current state,
>> - * 2) stop streaming and dequeues any queued buffers, including those previously
>> - *    passed to the driver (after waiting for the driver to finish).
>> - *
>> - * This call can be used for pausing playback.
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_streamoff handler in the driver
>> - */
>> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>> -{
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -	return vb2_internal_streamoff(q, type);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_streamoff);
>> +EXPORT_SYMBOL_GPL(vb2_core_streamoff);
>>
>>   /**
>>    * __find_plane_by_offset() - find plane associated with the given offset off
>> @@ -2452,7 +1813,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>   }
>>
>>   /**
>> - * vb2_expbuf() - Export a buffer as a file descriptor
>> + * vb2_core_expbuf() - Export a buffer as a file descriptor
>>    * @q:		videobuf2 queue
>>    * @eb:		export buffer structure passed from userspace to vidioc_expbuf
>>    *		handler in driver
>> @@ -2460,14 +1821,15 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>    * The return values from this function are intended to be directly returned
>>    * from vidioc_expbuf handler in driver.
>>    */
>> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
>> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>> +		unsigned int index, unsigned int plane, unsigned int flags)
>>   {
>>   	struct vb2_buffer *vb = NULL;
>>   	struct vb2_plane *vb_plane;
>>   	int ret;
>>   	struct dma_buf *dbuf;
>>
>> -	if (q->memory != V4L2_MEMORY_MMAP) {
>> +	if (q->memory != VB2_MEMORY_MMAP) {
>>   		dprintk(1, "queue is not currently set up for mmap\n");
>>   		return -EINVAL;
>>   	}
>> @@ -2477,78 +1839,60 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
>>   		return -EINVAL;
>>   	}
>>
>> -	if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
>> +	if (flags & ~(O_CLOEXEC | O_ACCMODE)) {
>>   		dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (eb->type != q->type) {
>> +	if (type != q->type) {
>>   		dprintk(1, "invalid buffer type\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (eb->index >= q->num_buffers) {
>> +	if (index >= q->num_buffers) {
>>   		dprintk(1, "buffer index out of range\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	vb = q->bufs[eb->index];
>> +	vb = q->bufs[index];
>>
>> -	if (eb->plane >= vb->num_planes) {
>> +	if (plane >= vb->num_planes) {
>>   		dprintk(1, "buffer plane out of range\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "expbuf: file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> +	vb_plane = &vb->planes[plane];
>>
>> -	vb_plane = &vb->planes[eb->plane];
>> -
>> -	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
>> +	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv,
>> +				flags & O_ACCMODE);
>>   	if (IS_ERR_OR_NULL(dbuf)) {
>>   		dprintk(1, "failed to export buffer %d, plane %d\n",
>> -			eb->index, eb->plane);
>> +			index, plane);
>>   		return -EINVAL;
>>   	}
>>
>> -	ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
>> +	ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
>>   	if (ret < 0) {
>>   		dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
>> -			eb->index, eb->plane, ret);
>> +			index, plane, ret);
>>   		dma_buf_put(dbuf);
>>   		return ret;
>>   	}
>>
>>   	dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
>> -		eb->index, eb->plane, ret);
>> -	eb->fd = ret;
>> +		index, plane, ret);
>> +	*fd = ret;
>>
>>   	return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_expbuf);
>> +EXPORT_SYMBOL_GPL(vb2_core_expbuf);
>>
>>   /**
>> - * vb2_mmap() - map video buffers into application address space
>> + * vb2_core_mmap() - map video buffers into application address space
>>    * @q:		videobuf2 queue
>>    * @vma:	vma passed to the mmap file operation handler in the driver
>> - *
>> - * Should be called from mmap file operation handler of a driver.
>> - * This function maps one plane of one of the available video buffers to
>> - * userspace. To map whole video memory allocated on reqbufs, this function
>> - * has to be called once per each plane per each buffer previously allocated.
>> - *
>> - * When the userspace application calls mmap, it passes to it an offset returned
>> - * to it earlier by the means of vidioc_querybuf handler. That offset acts as
>> - * a "cookie", which is then used to identify the plane to be mapped.
>> - * This function finds a plane with a matching offset and a mapping is performed
>> - * by the means of a provided memory operation.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from the mmap handler in driver.
>
> Please keep some documentation here. Ok, the function is now more
> generic, but still it deserves to be properly documented ;)

As your comment, vb2_core_* functions is more generic, but they will be
used internally by videobuf2. So, I move these documantaion to
videobuf2-v4l2, which is exposed to device drivers.
Which is better? Keep these documentation at both side,
or at vb2-core, or at vb2-v4l2.
I think that "at vb2-v4l2" is the best.

>
>>    */
>> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   {
>>   	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
>>   	struct vb2_buffer *vb;
>> @@ -2556,7 +1900,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   	int ret;
>>   	unsigned long length;
>>
>> -	if (q->memory != V4L2_MEMORY_MMAP) {
>> +	if (q->memory != VB2_MEMORY_MMAP) {
>>   		dprintk(1, "queue is not currently set up for mmap\n");
>>   		return -EINVAL;
>>   	}
>> @@ -2568,7 +1912,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   		dprintk(1, "invalid vma flags, VM_SHARED needed\n");
>>   		return -EINVAL;
>>   	}
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
>> +	if (q->is_output) {
>>   		if (!(vma->vm_flags & VM_WRITE)) {
>>   			dprintk(1, "invalid vma flags, VM_WRITE needed\n");
>>   			return -EINVAL;
>> @@ -2579,10 +1923,6 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   			return -EINVAL;
>>   		}
>>   	}
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "mmap: file io in progress\n");
>> -		return -EBUSY;
>> -	}
>>
>>   	/*
>>   	 * Find the plane corresponding to the offset passed by userspace.
>> @@ -2614,7 +1954,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   	dprintk(3, "buffer %d, plane %d successfully mapped\n", buffer, plane);
>>   	return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_mmap);
>> +EXPORT_SYMBOL_GPL(vb2_core_mmap);
>>
>>   #ifndef CONFIG_MMU
>>   unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>> @@ -2629,7 +1969,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>   	void *vaddr;
>>   	int ret;
>>
>> -	if (q->memory != V4L2_MEMORY_MMAP) {
>> +	if (q->memory != VB2_MEMORY_MMAP) {
>>   		dprintk(1, "queue is not currently set up for mmap\n");
>>   		return -EINVAL;
>>   	}
>> @@ -2649,123 +1989,8 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>   EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
>>   #endif
>>
>> -static int __vb2_init_fileio(struct vb2_queue *q, int read);
>> -static int __vb2_cleanup_fileio(struct vb2_queue *q);
>> -
>> -/**
>> - * vb2_poll() - implements poll userspace operation
>> - * @q:		videobuf2 queue
>> - * @file:	file argument passed to the poll file operation handler
>> - * @wait:	wait argument passed to the poll file operation handler
>> - *
>> - * This function implements poll file operation handler for a driver.
>> - * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
>> - * be informed that the file descriptor of a video device is available for
>> - * reading.
>> - * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
>> - * will be reported as available for writing.
>> - *
>> - * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
>> - * pending events.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from poll handler in driver.
>> - */
>> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
>> -{
>> -	struct video_device *vfd = video_devdata(file);
>> -	unsigned long req_events = poll_requested_events(wait);
>> -	struct vb2_buffer *vb = NULL;
>> -	unsigned int res = 0;
>> -	unsigned long flags;
>> -
>> -	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
>> -		struct v4l2_fh *fh = file->private_data;
>> -
>> -		if (v4l2_event_pending(fh))
>> -			res = POLLPRI;
>> -		else if (req_events & POLLPRI)
>> -			poll_wait(file, &fh->wait, wait);
>> -	}
>> -
>> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLIN | POLLRDNORM)))
>> -		return res;
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLOUT | POLLWRNORM)))
>> -		return res;
>> -
>> -	/*
>> -	 * Start file I/O emulator only if streaming API has not been used yet.
>> -	 */
>> -	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
>> -		if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
>> -				(req_events & (POLLIN | POLLRDNORM))) {
>> -			if (__vb2_init_fileio(q, 1))
>> -				return res | POLLERR;
>> -		}
>> -		if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
>> -				(req_events & (POLLOUT | POLLWRNORM))) {
>> -			if (__vb2_init_fileio(q, 0))
>> -				return res | POLLERR;
>> -			/*
>> -			 * Write to OUTPUT queue can be done immediately.
>> -			 */
>> -			return res | POLLOUT | POLLWRNORM;
>> -		}
>> -	}
>> -
>> -	/*
>> -	 * There is nothing to wait for if the queue isn't streaming, or if the
>> -	 * error flag is set.
>> -	 */
>> -	if (!vb2_is_streaming(q) || q->error)
>> -		return res | POLLERR;
>> -	/*
>> -	 * For compatibility with vb1: if QBUF hasn't been called yet, then
>> -	 * return POLLERR as well. This only affects capture queues, output
>> -	 * queues will always initialize waiting_for_buffers to false.
>> -	 */
>> -	if (q->waiting_for_buffers)
>> -		return res | POLLERR;
>> -
>> -	/*
>> -	 * For output streams you can write as long as there are fewer buffers
>> -	 * queued than there are buffers available.
>> -	 */
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
>> -		return res | POLLOUT | POLLWRNORM;
>> -
>> -	if (list_empty(&q->done_list)) {
>> -		/*
>> -		 * If the last buffer was dequeued from a capture queue,
>> -		 * return immediately. DQBUF will return -EPIPE.
>> -		 */
>> -		if (q->last_buffer_dequeued)
>> -			return res | POLLIN | POLLRDNORM;
>> -
>> -		poll_wait(file, &q->done_wq, wait);
>> -	}
>> -
>> -	/*
>> -	 * Take first buffer available for dequeuing.
>> -	 */
>> -	spin_lock_irqsave(&q->done_lock, flags);
>> -	if (!list_empty(&q->done_list))
>> -		vb = list_first_entry(&q->done_list, struct vb2_buffer,
>> -					done_entry);
>> -	spin_unlock_irqrestore(&q->done_lock, flags);
>> -
>> -	if (vb && (vb->state == VB2_BUF_STATE_DONE
>> -			|| vb->state == VB2_BUF_STATE_ERROR)) {
>> -		return (V4L2_TYPE_IS_OUTPUT(q->type)) ?
>> -				res | POLLOUT | POLLWRNORM :
>> -				res | POLLIN | POLLRDNORM;
>> -	}
>> -	return res;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_poll);
>> -
>>   /**
>> - * vb2_queue_init() - initialize a videobuf2 queue
>> + * vb2_core_queue_init() - initialize a videobuf2 queue
>>    * @q:		videobuf2 queue; this structure should be allocated in driver
>>    *
>>    * The vb2_queue structure should be allocated by the driver. The driver is
>> @@ -2775,7 +2000,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
>>    * to the struct vb2_queue description in include/media/videobuf2-core.h
>>    * for more information.
>>    */
>> -int vb2_queue_init(struct vb2_queue *q)
>> +int vb2_core_queue_init(struct vb2_queue *q)
>>   {
>>   	/*
>>   	 * Sanity check
>> @@ -2783,19 +2008,13 @@ int vb2_queue_init(struct vb2_queue *q)
>>   	if (WARN_ON(!q)				||
>>   		WARN_ON(!q->ops)		||
>>   		WARN_ON(!q->mem_ops)		||
>> +		WARN_ON(!q->buf_ops)		||
>>   		WARN_ON(!q->type)		||
>>   		WARN_ON(!q->io_modes)		||
>>   		WARN_ON(!q->ops->queue_setup)	||
>> -		WARN_ON(!q->ops->buf_queue)	||
>> -		WARN_ON(q->timestamp_flags &
>> -			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
>> -			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
>> +		WARN_ON(!q->ops->buf_queue))
>>   		return -EINVAL;
>>
>> -	/* Warn that the driver should choose an appropriate timestamp type */
>> -	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> -		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
>> -
>>   	INIT_LIST_HEAD(&q->queued_list);
>>   	INIT_LIST_HEAD(&q->done_list);
>>   	spin_lock_init(&q->done_lock);
>> @@ -2807,822 +2026,24 @@ int vb2_queue_init(struct vb2_queue *q)
>>
>>   	return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_queue_init);
>> +EXPORT_SYMBOL_GPL(vb2_core_queue_init);
>>
>>   /**
>> - * vb2_queue_release() - stop streaming, release the queue and free memory
>> + * vb2_core_queue_release() - stop streaming, release the queue and free memory
>>    * @q:		videobuf2 queue
>>    *
>>    * This function stops streaming and performs necessary clean ups, including
>>    * freeing video buffer memory. The driver is responsible for freeing
>>    * the vb2_queue structure itself.
>>    */
>> -void vb2_queue_release(struct vb2_queue *q)
>> +void vb2_core_queue_release(struct vb2_queue *q)
>>   {
>> -	__vb2_cleanup_fileio(q);
>>   	__vb2_queue_cancel(q);
>>   	mutex_lock(&q->mmap_lock);
>>   	__vb2_queue_free(q, q->num_buffers);
>>   	mutex_unlock(&q->mmap_lock);
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_queue_release);
>> -
>> -/**
>> - * struct vb2_fileio_buf - buffer context used by file io emulator
>> - *
>> - * vb2 provides a compatibility layer and emulator of file io (read and
>> - * write) calls on top of streaming API. This structure is used for
>> - * tracking context related to the buffers.
>> - */
>> -struct vb2_fileio_buf {
>> -	void *vaddr;
>> -	unsigned int size;
>> -	unsigned int pos;
>> -	unsigned int queued:1;
>> -};
>> -
>> -/**
>> - * struct vb2_fileio_data - queue context used by file io emulator
>> - *
>> - * @cur_index:	the index of the buffer currently being read from or
>> - *		written to. If equal to q->num_buffers then a new buffer
>> - *		must be dequeued.
>> - * @initial_index: in the read() case all buffers are queued up immediately
>> - *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
>> - *		buffers. However, in the write() case no buffers are initially
>> - *		queued, instead whenever a buffer is full it is queued up by
>> - *		__vb2_perform_fileio(). Only once all available buffers have
>> - *		been queued up will __vb2_perform_fileio() start to dequeue
>> - *		buffers. This means that initially __vb2_perform_fileio()
>> - *		needs to know what buffer index to use when it is queuing up
>> - *		the buffers for the first time. That initial index is stored
>> - *		in this field. Once it is equal to q->num_buffers all
>> - *		available buffers have been queued and __vb2_perform_fileio()
>> - *		should start the normal dequeue/queue cycle.
>> - *
>> - * vb2 provides a compatibility layer and emulator of file io (read and
>> - * write) calls on top of streaming API. For proper operation it required
>> - * this structure to save the driver state between each call of the read
>> - * or write function.
>> - */
>> -struct vb2_fileio_data {
>> -	struct v4l2_requestbuffers req;
>> -	struct v4l2_plane p;
>> -	struct v4l2_buffer b;
>> -	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
>> -	unsigned int cur_index;
>> -	unsigned int initial_index;
>> -	unsigned int q_count;
>> -	unsigned int dq_count;
>> -	unsigned read_once:1;
>> -	unsigned write_immediately:1;
>> -};
>> -
>> -/**
>> - * __vb2_init_fileio() - initialize file io emulator
>> - * @q:		videobuf2 queue
>> - * @read:	mode selector (1 means read, 0 means write)
>> - */
>> -static int __vb2_init_fileio(struct vb2_queue *q, int read)
>> -{
>> -	struct vb2_fileio_data *fileio;
>> -	int i, ret;
>> -	unsigned int count = 0;
>> -
>> -	/*
>> -	 * Sanity check
>> -	 */
>> -	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
>> -			(!read && !(q->io_modes & VB2_WRITE))))
>> -		return -EINVAL;
>> -
>> -	/*
>> -	 * Check if device supports mapping buffers to kernel virtual space.
>> -	 */
>> -	if (!q->mem_ops->vaddr)
>> -		return -EBUSY;
>> -
>> -	/*
>> -	 * Check if streaming api has not been already activated.
>> -	 */
>> -	if (q->streaming || q->num_buffers > 0)
>> -		return -EBUSY;
>> -
>> -	/*
>> -	 * Start with count 1, driver can increase it in queue_setup()
>> -	 */
>> -	count = 1;
>> -
>> -	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
>> -		(read) ? "read" : "write", count, q->fileio_read_once,
>> -		q->fileio_write_immediately);
>> -
>> -	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
>> -	if (fileio == NULL)
>> -		return -ENOMEM;
>> -
>> -	fileio->read_once = q->fileio_read_once;
>> -	fileio->write_immediately = q->fileio_write_immediately;
>> -
>> -	/*
>> -	 * Request buffers and use MMAP type to force driver
>> -	 * to allocate buffers by itself.
>> -	 */
>> -	fileio->req.count = count;
>> -	fileio->req.memory = V4L2_MEMORY_MMAP;
>> -	fileio->req.type = q->type;
>> -	q->fileio = fileio;
>> -	ret = __reqbufs(q, &fileio->req);
>> -	if (ret)
>> -		goto err_kfree;
>> -
>> -	/*
>> -	 * Check if plane_count is correct
>> -	 * (multiplane buffers are not supported).
>> -	 */
>> -	if (q->bufs[0]->num_planes != 1) {
>> -		ret = -EBUSY;
>> -		goto err_reqbufs;
>> -	}
>> -
>> -	/*
>> -	 * Get kernel address of each buffer.
>> -	 */
>> -	for (i = 0; i < q->num_buffers; i++) {
>> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>> -		if (fileio->bufs[i].vaddr == NULL) {
>> -			ret = -EINVAL;
>> -			goto err_reqbufs;
>> -		}
>> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>> -	}
>> -
>> -	/*
>> -	 * Read mode requires pre queuing of all buffers.
>> -	 */
>> -	if (read) {
>> -		bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
>> -
>> -		/*
>> -		 * Queue all buffers.
>> -		 */
>> -		for (i = 0; i < q->num_buffers; i++) {
>> -			struct v4l2_buffer *b = &fileio->b;
>> -
>> -			memset(b, 0, sizeof(*b));
>> -			b->type = q->type;
>> -			if (is_multiplanar) {
>> -				memset(&fileio->p, 0, sizeof(fileio->p));
>> -				b->m.planes = &fileio->p;
>> -				b->length = 1;
>> -			}
>> -			b->memory = q->memory;
>> -			b->index = i;
>> -			ret = vb2_internal_qbuf(q, b);
>> -			if (ret)
>> -				goto err_reqbufs;
>> -			fileio->bufs[i].queued = 1;
>> -		}
>> -		/*
>> -		 * All buffers have been queued, so mark that by setting
>> -		 * initial_index to q->num_buffers
>> -		 */
>> -		fileio->initial_index = q->num_buffers;
>> -		fileio->cur_index = q->num_buffers;
>> -	}
>> -
>> -	/*
>> -	 * Start streaming.
>> -	 */
>> -	ret = vb2_internal_streamon(q, q->type);
>> -	if (ret)
>> -		goto err_reqbufs;
>> -
>> -	return ret;
>> -
>> -err_reqbufs:
>> -	fileio->req.count = 0;
>> -	__reqbufs(q, &fileio->req);
>> -
>> -err_kfree:
>> -	q->fileio = NULL;
>> -	kfree(fileio);
>> -	return ret;
>> -}
>> -
>> -/**
>> - * __vb2_cleanup_fileio() - free resourced used by file io emulator
>> - * @q:		videobuf2 queue
>> - */
>> -static int __vb2_cleanup_fileio(struct vb2_queue *q)
>> -{
>> -	struct vb2_fileio_data *fileio = q->fileio;
>> -
>> -	if (fileio) {
>> -		vb2_internal_streamoff(q, q->type);
>> -		q->fileio = NULL;
>> -		fileio->req.count = 0;
>> -		vb2_reqbufs(q, &fileio->req);
>> -		kfree(fileio);
>> -		dprintk(3, "file io emulator closed\n");
>> -	}
>> -	return 0;
>> -}
>> -
>> -/**
>> - * __vb2_perform_fileio() - perform a single file io (read or write) operation
>> - * @q:		videobuf2 queue
>> - * @data:	pointed to target userspace buffer
>> - * @count:	number of bytes to read or write
>> - * @ppos:	file handle position tracking pointer
>> - * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
>> - * @read:	access mode selector (1 means read, 0 means write)
>> - */
>> -static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
>> -		loff_t *ppos, int nonblock, int read)
>> -{
>> -	struct vb2_fileio_data *fileio;
>> -	struct vb2_fileio_buf *buf;
>> -	bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
>> -	/*
>> -	 * When using write() to write data to an output video node the vb2 core
>> -	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
>> -	 * else is able to provide this information with the write() operation.
>> -	 */
>> -	bool set_timestamp = !read &&
>> -		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> -		V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> -	int ret, index;
>> -
>> -	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
>> -		read ? "read" : "write", (long)*ppos, count,
>> -		nonblock ? "non" : "");
>> -
>> -	if (!data)
>> -		return -EINVAL;
>> -
>> -	/*
>> -	 * Initialize emulator on first call.
>> -	 */
>> -	if (!vb2_fileio_is_active(q)) {
>> -		ret = __vb2_init_fileio(q, read);
>> -		dprintk(3, "vb2_init_fileio result: %d\n", ret);
>> -		if (ret)
>> -			return ret;
>> -	}
>> -	fileio = q->fileio;
>> -
>> -	/*
>> -	 * Check if we need to dequeue the buffer.
>> -	 */
>> -	index = fileio->cur_index;
>> -	if (index >= q->num_buffers) {
>> -		/*
>> -		 * Call vb2_dqbuf to get buffer back.
>> -		 */
>> -		memset(&fileio->b, 0, sizeof(fileio->b));
>> -		fileio->b.type = q->type;
>> -		fileio->b.memory = q->memory;
>> -		if (is_multiplanar) {
>> -			memset(&fileio->p, 0, sizeof(fileio->p));
>> -			fileio->b.m.planes = &fileio->p;
>> -			fileio->b.length = 1;
>> -		}
>> -		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
>> -		dprintk(5, "vb2_dqbuf result: %d\n", ret);
>> -		if (ret)
>> -			return ret;
>> -		fileio->dq_count += 1;
>> -
>> -		fileio->cur_index = index = fileio->b.index;
>> -		buf = &fileio->bufs[index];
>> -
>> -		/*
>> -		 * Get number of bytes filled by the driver
>> -		 */
>> -		buf->pos = 0;
>> -		buf->queued = 0;
>> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>> -				 : vb2_plane_size(q->bufs[index], 0);
>> -		/*
>> -		 * Compensate for data_offset on read
>> -		 * in the multiplanar case
>> -		 */
>> -		if (is_multiplanar && read &&
>> -			fileio->b.m.planes[0].data_offset < buf->size) {
>> -			buf->pos = fileio->b.m.planes[0].data_offset;
>> -			buf->size -= buf->pos;
>> -		}
>> -	} else {
>> -		buf = &fileio->bufs[index];
>> -	}
>> -
>> -	/*
>> -	 * Limit count on last few bytes of the buffer.
>> -	 */
>> -	if (buf->pos + count > buf->size) {
>> -		count = buf->size - buf->pos;
>> -		dprintk(5, "reducing read count: %zd\n", count);
>> -	}
>> -
>> -	/*
>> -	 * Transfer data to userspace.
>> -	 */
>> -	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
>> -		count, index, buf->pos);
>> -	if (read)
>> -		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
>> -	else
>> -		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
>> -	if (ret) {
>> -		dprintk(3, "error copying data\n");
>> -		return -EFAULT;
>> -	}
>> -
>> -	/*
>> -	 * Update counters.
>> -	 */
>> -	buf->pos += count;
>> -	*ppos += count;
>> -
>> -	/*
>> -	 * Queue next buffer if required.
>> -	 */
>> -	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>> -		/*
>> -		 * Check if this is the last buffer to read.
>> -		 */
>> -		if (read && fileio->read_once && fileio->dq_count == 1) {
>> -			dprintk(3, "read limit reached\n");
>> -			return __vb2_cleanup_fileio(q);
>> -		}
>> -
>> -		/*
>> -		 * Call vb2_qbuf and give buffer to the driver.
>> -		 */
>> -		memset(&fileio->b, 0, sizeof(fileio->b));
>> -		fileio->b.type = q->type;
>> -		fileio->b.memory = q->memory;
>> -		fileio->b.index = index;
>> -		fileio->b.bytesused = buf->pos;
>> -		if (is_multiplanar) {
>> -			memset(&fileio->p, 0, sizeof(fileio->p));
>> -			fileio->p.bytesused = buf->pos;
>> -			fileio->b.m.planes = &fileio->p;
>> -			fileio->b.length = 1;
>> -		}
>> -		if (set_timestamp)
>> -			v4l2_get_timestamp(&fileio->b.timestamp);
>> -		ret = vb2_internal_qbuf(q, &fileio->b);
>> -		dprintk(5, "vb2_dbuf result: %d\n", ret);
>> -		if (ret)
>> -			return ret;
>> -
>> -		/*
>> -		 * Buffer has been queued, update the status
>> -		 */
>> -		buf->pos = 0;
>> -		buf->queued = 1;
>> -		buf->size = vb2_plane_size(q->bufs[index], 0);
>> -		fileio->q_count += 1;
>> -		/*
>> -		 * If we are queuing up buffers for the first time, then
>> -		 * increase initial_index by one.
>> -		 */
>> -		if (fileio->initial_index < q->num_buffers)
>> -			fileio->initial_index++;
>> -		/*
>> -		 * The next buffer to use is either a buffer that's going to be
>> -		 * queued for the first time (initial_index < q->num_buffers)
>> -		 * or it is equal to q->num_buffers, meaning that the next
>> -		 * time we need to dequeue a buffer since we've now queued up
>> -		 * all the 'first time' buffers.
>> -		 */
>> -		fileio->cur_index = fileio->initial_index;
>> -	}
>> -
>> -	/*
>> -	 * Return proper number of bytes processed.
>> -	 */
>> -	if (ret == 0)
>> -		ret = count;
>> -	return ret;
>> -}
>> -
>> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
>> -		loff_t *ppos, int nonblocking)
>> -{
>> -	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_read);
>> -
>> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
>> -		loff_t *ppos, int nonblocking)
>> -{
>> -	return __vb2_perform_fileio(q, (char __user *) data, count,
>> -							ppos, nonblocking, 0);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_write);
>> -
>> -struct vb2_threadio_data {
>> -	struct task_struct *thread;
>> -	vb2_thread_fnc fnc;
>> -	void *priv;
>> -	bool stop;
>> -};
>> -
>> -static int vb2_thread(void *data)
>> -{
>> -	struct vb2_queue *q = data;
>> -	struct vb2_threadio_data *threadio = q->threadio;
>> -	struct vb2_fileio_data *fileio = q->fileio;
>> -	bool set_timestamp = false;
>> -	int prequeue = 0;
>> -	int index = 0;
>> -	int ret = 0;
>> -
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
>> -		prequeue = q->num_buffers;
>> -		set_timestamp =
>> -			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> -			V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> -	}
>> -
>> -	set_freezable();
>> -
>> -	for (;;) {
>> -		struct vb2_buffer *vb;
>> -
>> -		/*
>> -		 * Call vb2_dqbuf to get buffer back.
>> -		 */
>> -		memset(&fileio->b, 0, sizeof(fileio->b));
>> -		fileio->b.type = q->type;
>> -		fileio->b.memory = q->memory;
>> -		if (prequeue) {
>> -			fileio->b.index = index++;
>> -			prequeue--;
>> -		} else {
>> -			call_void_qop(q, wait_finish, q);
>> -			if (!threadio->stop)
>> -				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
>> -			call_void_qop(q, wait_prepare, q);
>> -			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
>> -		}
>> -		if (ret || threadio->stop)
>> -			break;
>> -		try_to_freeze();
>> -
>> -		vb = q->bufs[fileio->b.index];
>> -		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
>> -			if (threadio->fnc(vb, threadio->priv))
>> -				break;
>> -		call_void_qop(q, wait_finish, q);
>> -		if (set_timestamp)
>> -			v4l2_get_timestamp(&fileio->b.timestamp);
>> -		if (!threadio->stop)
>> -			ret = vb2_internal_qbuf(q, &fileio->b);
>> -		call_void_qop(q, wait_prepare, q);
>> -		if (ret || threadio->stop)
>> -			break;
>> -	}
>> -
>> -	/* Hmm, linux becomes *very* unhappy without this ... */
>> -	while (!kthread_should_stop()) {
>> -		set_current_state(TASK_INTERRUPTIBLE);
>> -		schedule();
>> -	}
>> -	return 0;
>> -}
>> -
>> -/*
>> - * This function should not be used for anything else but the videobuf2-dvb
>> - * support. If you think you have another good use-case for this, then please
>> - * contact the linux-media mailinglist first.
>> - */
>> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
>> -			const char *thread_name)
>> -{
>> -	struct vb2_threadio_data *threadio;
>> -	int ret = 0;
>> -
>> -	if (q->threadio)
>> -		return -EBUSY;
>> -	if (vb2_is_busy(q))
>> -		return -EBUSY;
>> -	if (WARN_ON(q->fileio))
>> -		return -EBUSY;
>> -
>> -	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
>> -	if (threadio == NULL)
>> -		return -ENOMEM;
>> -	threadio->fnc = fnc;
>> -	threadio->priv = priv;
>> -
>> -	ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type));
>> -	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
>> -	if (ret)
>> -		goto nomem;
>> -	q->threadio = threadio;
>> -	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
>> -	if (IS_ERR(threadio->thread)) {
>> -		ret = PTR_ERR(threadio->thread);
>> -		threadio->thread = NULL;
>> -		goto nothread;
>> -	}
>> -	return 0;
>> -
>> -nothread:
>> -	__vb2_cleanup_fileio(q);
>> -nomem:
>> -	kfree(threadio);
>> -	return ret;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_thread_start);
>> -
>> -int vb2_thread_stop(struct vb2_queue *q)
>> -{
>> -	struct vb2_threadio_data *threadio = q->threadio;
>> -	int err;
>> -
>> -	if (threadio == NULL)
>> -		return 0;
>> -	threadio->stop = true;
>> -	/* Wake up all pending sleeps in the thread */
>> -	vb2_queue_error(q);
>> -	err = kthread_stop(threadio->thread);
>> -	__vb2_cleanup_fileio(q);
>> -	threadio->thread = NULL;
>> -	kfree(threadio);
>> -	q->threadio = NULL;
>> -	return err;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_thread_stop);
>> -
>> -/*
>> - * The following functions are not part of the vb2 core API, but are helper
>> - * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
>> - * and struct vb2_ops.
>> - * They contain boilerplate code that most if not all drivers have to do
>> - * and so they simplify the driver code.
>> - */
>> -
>> -/* The queue is busy if there is a owner and you are not that owner. */
>> -static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
>> -{
>> -	return vdev->queue->owner && vdev->queue->owner != file->private_data;
>> -}
>> -
>> -/* vb2 ioctl helpers */
>> -
>> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
>> -			  struct v4l2_requestbuffers *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	int res = __verify_memory_type(vdev->queue, p->memory, p->type);
>> -
>> -	if (res)
>> -		return res;
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	res = __reqbufs(vdev->queue, p);
>> -	/* If count == 0, then the owner has released all buffers and he
>> -	   is no longer owner of the queue. Otherwise we have a new owner. */
>> -	if (res == 0)
>> -		vdev->queue->owner = p->count ? file->private_data : NULL;
>> -	return res;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
>> -
>> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
>> -			  struct v4l2_create_buffers *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	int res = __verify_memory_type(vdev->queue, p->memory, p->format.type);
>> -
>> -	p->index = vdev->queue->num_buffers;
>> -	/* If count == 0, then just check if memory and type are valid.
>> -	   Any -EBUSY result from __verify_memory_type can be mapped to 0. */
>> -	if (p->count == 0)
>> -		return res != -EBUSY ? res : 0;
>> -	if (res)
>> -		return res;
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	res = __create_bufs(vdev->queue, p);
>> -	if (res == 0)
>> -		vdev->queue->owner = file->private_data;
>> -	return res;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
>> -
>> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
>> -			  struct v4l2_buffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_prepare_buf(vdev->queue, p);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
>> -
>> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
>> -	return vb2_querybuf(vdev->queue, p);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
>> -
>> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_qbuf(vdev->queue, p);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
>> -
>> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
>> -
>> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_streamon(vdev->queue, i);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
>> -
>> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_streamoff(vdev->queue, i);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
>> -
>> -int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_expbuf(vdev->queue, p);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
>> -
>> -/* v4l2_file_operations helpers */
>> -
>> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	return vb2_mmap(vdev->queue, vma);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_mmap);
>> -
>> -int _vb2_fop_release(struct file *file, struct mutex *lock)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (lock)
>> -		mutex_lock(lock);
>> -	if (file->private_data == vdev->queue->owner) {
>> -		vb2_queue_release(vdev->queue);
>> -		vdev->queue->owner = NULL;
>> -	}
>> -	if (lock)
>> -		mutex_unlock(lock);
>> -	return v4l2_fh_release(file);
>> -}
>> -EXPORT_SYMBOL_GPL(_vb2_fop_release);
>> -
>> -int vb2_fop_release(struct file *file)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> -
>> -	return _vb2_fop_release(file, lock);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_release);
>> -
>> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>> -		size_t count, loff_t *ppos)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> -	int err = -EBUSY;
>> -
>> -	if (!(vdev->queue->io_modes & VB2_WRITE))
>> -		return -EINVAL;
>> -	if (lock && mutex_lock_interruptible(lock))
>> -		return -ERESTARTSYS;
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		goto exit;
>> -	err = vb2_write(vdev->queue, buf, count, ppos,
>> -			file->f_flags & O_NONBLOCK);
>> -	if (vdev->queue->fileio)
>> -		vdev->queue->owner = file->private_data;
>> -exit:
>> -	if (lock)
>> -		mutex_unlock(lock);
>> -	return err;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_write);
>> -
>> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
>> -		size_t count, loff_t *ppos)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> -	int err = -EBUSY;
>> -
>> -	if (!(vdev->queue->io_modes & VB2_READ))
>> -		return -EINVAL;
>> -	if (lock && mutex_lock_interruptible(lock))
>> -		return -ERESTARTSYS;
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		goto exit;
>> -	err = vb2_read(vdev->queue, buf, count, ppos,
>> -			file->f_flags & O_NONBLOCK);
>> -	if (vdev->queue->fileio)
>> -		vdev->queue->owner = file->private_data;
>> -exit:
>> -	if (lock)
>> -		mutex_unlock(lock);
>> -	return err;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_read);
>> -
>> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	struct vb2_queue *q = vdev->queue;
>> -	struct mutex *lock = q->lock ? q->lock : vdev->lock;
>> -	unsigned res;
>> -	void *fileio;
>> -
>> -	/*
>> -	 * If this helper doesn't know how to lock, then you shouldn't be using
>> -	 * it but you should write your own.
>> -	 */
>> -	WARN_ON(!lock);
>> -
>> -	if (lock && mutex_lock_interruptible(lock))
>> -		return POLLERR;
>> -
>> -	fileio = q->fileio;
>> -
>> -	res = vb2_poll(vdev->queue, file, wait);
>> -
>> -	/* If fileio was started, then we have a new queue owner. */
>> -	if (!fileio && q->fileio)
>> -		q->owner = file->private_data;
>> -	if (lock)
>> -		mutex_unlock(lock);
>> -	return res;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_poll);
>> -
>> -#ifndef CONFIG_MMU
>> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>> -		unsigned long len, unsigned long pgoff, unsigned long flags)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
>> -#endif
>> -
>> -/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
>> -
>> -void vb2_ops_wait_prepare(struct vb2_queue *vq)
>> -{
>> -	mutex_unlock(vq->lock);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
>> -
>> -void vb2_ops_wait_finish(struct vb2_queue *vq)
>> -{
>> -	mutex_lock(vq->lock);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
>> +EXPORT_SYMBOL_GPL(vb2_core_queue_release);
>>
>>   MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
>>   MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
>> diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h
>> new file mode 100644
>> index 0000000..3998ac9
>> --- /dev/null
>> +++ b/drivers/media/v4l2-core/videobuf2-internal.h
>> @@ -0,0 +1,184 @@
>> +#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H
>> +#define _MEDIA_VIDEOBUF2_INTERNAL_H
>> +
>> +#include <linux/err.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <media/videobuf2-core.h>
>> +
>> +extern int vb2_debug;
>> +
>> +#define dprintk(level, fmt, arg...)					\
>> +	do {								\
>> +		if (vb2_debug >= level)					\
>> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
>> +	} while (0)
>> +
>> +#ifdef CONFIG_VIDEO_ADV_DEBUG
>> +
>> +/*
>> + * If advanced debugging is on, then count how often each op is called
>> + * successfully, which can either be per-buffer or per-queue.
>> + *
>> + * This makes it easy to check that the 'init' and 'cleanup'
>> + * (and variations thereof) stay balanced.
>> + */
>> +
>> +#define log_memop(vb, op)						\
>> +	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
>> +		(vb)->vb2_queue, (vb)->index, #op,			\
>> +		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
>> +
>> +#define call_memop(vb, op, args...)					\
>> +({									\
>> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> +	int err;							\
>> +									\
>> +	log_memop(vb, op);						\
>> +	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
>> +	if (!err)							\
>> +		(vb)->cnt_mem_ ## op++;					\
>> +	err;								\
>> +})
>> +
>> +#define call_ptr_memop(vb, op, args...)					\
>> +({									\
>> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> +	void *ptr;							\
>> +									\
>> +	log_memop(vb, op);						\
>> +	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
>> +	if (!IS_ERR_OR_NULL(ptr))					\
>> +		(vb)->cnt_mem_ ## op++;					\
>> +	ptr;								\
>> +})
>> +
>> +#define call_void_memop(vb, op, args...)				\
>> +({									\
>> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> +									\
>> +	log_memop(vb, op);						\
>> +	if (_q->mem_ops->op)						\
>> +		_q->mem_ops->op(args);					\
>> +	(vb)->cnt_mem_ ## op++;						\
>> +})
>> +
>> +#define log_qop(q, op)							\
>> +	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
>> +		(q)->ops->op ? "" : " (nop)")
>> +
>> +#define call_qop(q, op, args...)					\
>> +({									\
>> +	int err;							\
>> +									\
>> +	log_qop(q, op);							\
>> +	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
>> +	if (!err)							\
>> +		(q)->cnt_ ## op++;					\
>> +	err;								\
>> +})
>> +
>> +#define call_void_qop(q, op, args...)					\
>> +({									\
>> +	log_qop(q, op);							\
>> +	if ((q)->ops->op)						\
>> +		(q)->ops->op(args);					\
>> +	(q)->cnt_ ## op++;						\
>> +})
>> +
>> +#define log_vb_qop(vb, op, args...)					\
>> +	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
>> +		(vb)->vb2_queue, (vb)->index, #op,			\
>> +		(vb)->vb2_queue->ops->op ? "" : " (nop)")
>> +
>> +#define call_vb_qop(vb, op, args...)					\
>> +({									\
>> +	int err;							\
>> +									\
>> +	log_vb_qop(vb, op);						\
>> +	err = (vb)->vb2_queue->ops->op ?				\
>> +		(vb)->vb2_queue->ops->op(args) : 0;			\
>> +	if (!err)							\
>> +		(vb)->cnt_ ## op++;					\
>> +	err;								\
>> +})
>> +
>> +#define call_void_vb_qop(vb, op, args...)				\
>> +({									\
>> +	log_vb_qop(vb, op);						\
>> +	if ((vb)->vb2_queue->ops->op)					\
>> +		(vb)->vb2_queue->ops->op(args);				\
>> +	(vb)->cnt_ ## op++;						\
>> +})
>> +
>> +#else
>> +
>> +#define call_memop(vb, op, args...)					\
>> +	((vb)->vb2_queue->mem_ops->op ?					\
>> +		(vb)->vb2_queue->mem_ops->op(args) : 0)
>> +
>> +#define call_ptr_memop(vb, op, args...)					\
>> +	((vb)->vb2_queue->mem_ops->op ?					\
>> +		(vb)->vb2_queue->mem_ops->op(args) : NULL)
>> +
>> +#define call_void_memop(vb, op, args...)				\
>> +	do {								\
>> +		if ((vb)->vb2_queue->mem_ops->op)			\
>> +			(vb)->vb2_queue->mem_ops->op(args);		\
>> +	} while (0)
>> +
>> +#define call_qop(q, op, args...)					\
>> +	((q)->ops->op ? (q)->ops->op(args) : 0)
>> +
>> +#define call_void_qop(q, op, args...)					\
>> +	do {								\
>> +		if ((q)->ops->op)					\
>> +			(q)->ops->op(args);				\
>> +	} while (0)
>> +
>> +#define call_vb_qop(vb, op, args...)					\
>> +	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
>> +
>> +#define call_void_vb_qop(vb, op, args...)				\
>> +	do {								\
>> +		if ((vb)->vb2_queue->ops->op)				\
>> +			(vb)->vb2_queue->ops->op(args);			\
>> +	} while (0)
>> +
>> +#endif
>> +
>> +#define call_bufop(q, op, args...)					\
>> +({									\
>> +	int ret = 0;							\
>> +	if (q && q->buf_ops && q->buf_ops->op)				\
>> +		ret = q->buf_ops->op(args);				\
>> +	ret;								\
>> +})
>> +
>> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
>> +int vb2_verify_memory_type(struct vb2_queue *q,
>> +		unsigned int memory, unsigned int type);
>> +int vb2_verify_buffer(struct vb2_queue *q,
>> +			unsigned int memory, unsigned int type,
>> +			unsigned int index, unsigned int nplanes,
>> +			void *pplane, const char *opname);
>> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb);
>> +
>> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb);
>> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
>> +		unsigned int *count);
>> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
>> +		unsigned int *count, void *parg);
>> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
>> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb);
>> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblock);
>> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>> +		unsigned int index, unsigned int plane, unsigned int flags);
>> +int vb2_core_streamon(struct vb2_queue *q);
>> +int vb2_core_streamoff(struct vb2_queue *q);
>> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
>> +
>> +int __must_check vb2_core_queue_init(struct vb2_queue *q);
>> +void vb2_core_queue_release(struct vb2_queue *q);
>> +
>> +#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */
>> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> index 2f2b738..9fc6bef 100644
>> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
>> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> @@ -24,8 +24,1648 @@
>>   #include <linux/freezer.h>
>>   #include <linux/kthread.h>
>>
>> +#include <media/v4l2-dev.h>
>> +#include <media/v4l2-fh.h>
>> +#include <media/v4l2-event.h>
>> +#include <media/v4l2-common.h>
>>   #include <media/videobuf2-v4l2.h>
>>
>> +#include "videobuf2-internal.h"
>> +
>> +/* Flags that are set by the vb2 core */
>> +#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | \
>> +				V4L2_BUF_FLAG_QUEUED | \
>> +				V4L2_BUF_FLAG_DONE | \
>> +				V4L2_BUF_FLAG_ERROR | \
>> +				V4L2_BUF_FLAG_PREPARED | \
>> +				V4L2_BUF_FLAG_TIMESTAMP_MASK)
>> +
>> +/* Output buffer flags that should be passed on to the driver */
>> +#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | \
>> +				V4L2_BUF_FLAG_BFRAME | \
>> +				V4L2_BUF_FLAG_KEYFRAME | \
>> +				V4L2_BUF_FLAG_TIMECODE)
>> +
>> +/**
>> + * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
>> + * returned to userspace
>> + */
>> +static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
>> +{
>> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
>
> As commented before, avoid doing typecasts if not required.
>
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +	struct vb2_queue *q = vb->vb2_queue;
>> +	unsigned int plane;
>> +
>> +	/* Copy back data such as timestamp, flags, etc. */
>> +	b->index = vb->index;
>> +	b->type = vb->type;
>> +	b->memory = vb->memory;
>> +	b->bytesused = 0;
>> +
>> +	b->flags = vbuf->flags;
>> +	b->field = vbuf->field;
>> +	b->timestamp = vbuf->timestamp;
>> +	b->timecode = vbuf->timecode;
>> +	b->sequence = vbuf->sequence;
>> +
>> +	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>> +		/*
>> +		 * Fill in plane-related data if userspace provided an array
>> +		 * for it. The caller has already verified memory and size.
>> +		 */
>> +		b->length = vb->num_planes;
>> +		for (plane = 0; plane < vb->num_planes; ++plane) {
>> +			struct v4l2_plane *pdst = &b->m.planes[plane];
>> +			struct vb2_plane *psrc = &vb->planes[plane];
>> +
>> +			pdst->bytesused = psrc->bytesused;
>> +			pdst->length = psrc->length;
>> +			if (q->memory == V4L2_MEMORY_MMAP)
>> +				pdst->m.mem_offset = psrc->m.offset;
>> +			else if (q->memory == V4L2_MEMORY_USERPTR)
>> +				pdst->m.userptr = psrc->m.userptr;
>> +			else if (q->memory == V4L2_MEMORY_DMABUF)
>> +				pdst->m.fd = psrc->m.fd;
>> +			pdst->data_offset = psrc->data_offset;
>> +		}
>> +	} else {
>> +		/*
>> +		 * We use length and offset in v4l2_planes array even for
>> +		 * single-planar buffers, but userspace does not.
>> +		 */
>> +		b->length = vb->planes[0].length;
>> +		b->bytesused = vb->planes[0].bytesused;
>> +		if (q->memory == V4L2_MEMORY_MMAP)
>> +			b->m.offset = vb->planes[0].m.offset;
>> +		else if (q->memory == V4L2_MEMORY_USERPTR)
>> +			b->m.userptr = vb->planes[0].m.userptr;
>> +		else if (q->memory == V4L2_MEMORY_DMABUF)
>> +			b->m.fd = vb->planes[0].m.fd;
>> +	}
>> +
>> +	/*
>> +	 * Clear any buffer state related flags.
>> +	 */
>> +	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>> +	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>> +		/*
>> +		 * For non-COPY timestamps, drop timestamp source bits
>> +		 * and obtain the timestamp source from the queue.
>> +		 */
>> +		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> +		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> +	}
>> +
>> +	switch (vb->state) {
>> +	case VB2_BUF_STATE_QUEUED:
>> +	case VB2_BUF_STATE_ACTIVE:
>> +		b->flags |= V4L2_BUF_FLAG_QUEUED;
>> +		break;
>> +	case VB2_BUF_STATE_ERROR:
>> +		b->flags |= V4L2_BUF_FLAG_ERROR;
>> +		/* fall through */
>> +	case VB2_BUF_STATE_DONE:
>> +		b->flags |= V4L2_BUF_FLAG_DONE;
>> +		break;
>> +	case VB2_BUF_STATE_PREPARED:
>> +		b->flags |= V4L2_BUF_FLAG_PREPARED;
>> +		break;
>> +	case VB2_BUF_STATE_PREPARING:
>> +	case VB2_BUF_STATE_DEQUEUED:
>> +		/* nothing */
>> +		break;
>> +	}
>> +
>> +	if (vb2_buffer_in_use(q, vb))
>> +		b->flags |= V4L2_BUF_FLAG_MAPPED;
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * __verify_length() - Verify that the bytesused value for each plane fits in
>> + * the plane length and that the data offset doesn't exceed the bytesused value.
>> + */
>> +static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +{
>> +	unsigned int length;
>> +	unsigned int bytesused;
>> +	unsigned int plane;
>> +
>> +	if (!V4L2_TYPE_IS_OUTPUT(b->type))
>> +		return 0;
>> +
>> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>> +		for (plane = 0; plane < vb->num_planes; ++plane) {
>> +			length = (b->memory == V4L2_MEMORY_USERPTR ||
>> +				b->memory == V4L2_MEMORY_DMABUF)
>> +				? b->m.planes[plane].length
>> +				: vb->planes[plane].length;
>> +			bytesused = b->m.planes[plane].bytesused
>> +				? b->m.planes[plane].bytesused : length;
>> +
>> +			if (b->m.planes[plane].bytesused > length)
>> +				return -EINVAL;
>> +
>> +			if (b->m.planes[plane].data_offset > 0 &&
>> +				b->m.planes[plane].data_offset >= bytesused)
>> +				return -EINVAL;
>> +		}
>> +	} else {
>> +		length = (b->memory == V4L2_MEMORY_USERPTR)
>> +			? b->length : vb->planes[0].length;
>> +
>> +		if (b->bytesused > length)
>> +			return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
>> + * v4l2_buffer by the userspace. It also verifies that struct
>> + * v4l2_buffer has a valid number of planes.
>> + */
>> +static int __fill_vb2_buffer(struct vb2_buffer *vb, void *pb,
>> +				struct vb2_plane *planes)
>> +{
>> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +	unsigned int plane;
>> +	int ret;
>> +
>> +	ret = __verify_length(vb, b);
>> +	if (ret < 0) {
>> +		dprintk(1, "plane parameters verification failed: %d\n", ret);
>> +		return ret;
>> +	}
>> +	vb->state = VB2_BUF_STATE_PREPARING;
>> +	vbuf->timestamp.tv_sec = 0;
>> +	vbuf->timestamp.tv_usec = 0;
>> +	vbuf->sequence = 0;
>> +
>> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>> +		if (b->memory == V4L2_MEMORY_USERPTR) {
>> +			for (plane = 0; plane < vb->num_planes; ++plane) {
>> +				planes[plane].m.userptr =
>> +					b->m.planes[plane].m.userptr;
>> +				planes[plane].length =
>> +					b->m.planes[plane].length;
>> +			}
>> +		}
>> +		if (b->memory == V4L2_MEMORY_DMABUF) {
>> +			for (plane = 0; plane < vb->num_planes; ++plane) {
>> +				planes[plane].m.fd =
>> +					b->m.planes[plane].m.fd;
>> +				planes[plane].length =
>> +					b->m.planes[plane].length;
>> +			}
>> +		}
>> +
>> +		/* Fill in driver-provided information for OUTPUT types */
>> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> +			/*
>> +			 * Will have to go up to b->length when API starts
>> +			 * accepting variable number of planes.
>> +			 *
>> +			 * If bytesused == 0 for the output buffer, then fall
>> +			 * back to the full buffer size. In that case
>> +			 * userspace clearly never bothered to set it and
>> +			 * it's a safe assumption that they really meant to
>> +			 * use the full plane sizes.
>> +			 *
>> +			 * Some drivers, e.g. old codec drivers, use bytesused == 0
>> +			 * as a way to indicate that streaming is finished.
>> +			 * In that case, the driver should use the
>> +			 * allow_zero_bytesused flag to keep old userspace
>> +			 * applications working.
>> +			 */
>> +			for (plane = 0; plane < vb->num_planes; ++plane) {
>> +				struct vb2_plane *pdst = &planes[plane];
>> +				struct v4l2_plane *psrc = &b->m.planes[plane];
>> +
>> +				if (psrc->bytesused == 0)
>> +					vb2_warn_zero_bytesused(vb);
>> +
>> +				if (vb->vb2_queue->allow_zero_bytesused)
>> +					pdst->bytesused = psrc->bytesused;
>> +				else
>> +					pdst->bytesused = psrc->bytesused ?
>> +						psrc->bytesused : pdst->length;
>> +				pdst->data_offset = psrc->data_offset;
>> +			}
>> +		}
>> +	} else {
>> +		/*
>> +		 * Single-planar buffers do not use planes array,
>> +		 * so fill in relevant v4l2_buffer struct fields instead.
>> +		 * In videobuf we use our internal V4l2_planes struct for
>> +		 * single-planar buffers as well, for simplicity.
>> +		 *
>> +		 * If bytesused == 0 for the output buffer, then fall back
>> +		 * to the full buffer size as that's a sensible default.
>> +		 *
>> +		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
>> +		 * a way to indicate that streaming is finished. In that case,
>> +		 * the driver should use the allow_zero_bytesused flag to keep
>> +		 * old userspace applications working.
>> +		 */
>> +		if (b->memory == V4L2_MEMORY_USERPTR) {
>> +			planes[0].m.userptr = b->m.userptr;
>> +			planes[0].length = b->length;
>> +		}
>> +
>> +		if (b->memory == V4L2_MEMORY_DMABUF) {
>> +			planes[0].m.fd = b->m.fd;
>> +			planes[0].length = b->length;
>> +		}
>> +
>> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> +			if (b->bytesused == 0)
>> +				vb2_warn_zero_bytesused(vb);
>> +
>> +			if (vb->vb2_queue->allow_zero_bytesused)
>> +				planes[0].bytesused = b->bytesused;
>> +			else
>> +				planes[0].bytesused = b->bytesused ?
>> +					b->bytesused : planes[0].length;
>> +		} else
>> +			planes[0].bytesused = 0;
>> +
>> +	}
>> +
>> +	/* Zero flags that the vb2 core handles */
>> +	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
>> +	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
>> +			!V4L2_TYPE_IS_OUTPUT(b->type)) {
>> +		/*
>> +		 * Non-COPY timestamps and non-OUTPUT queues will get
>> +		 * their timestamp and timestamp source flags from the
>> +		 * queue.
>> +		 */
>> +		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> +	}
>> +
>> +	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> +		/*
>> +		 * For output buffers mask out the timecode flag:
>> +		 * this will be handled later in vb2_internal_qbuf().
>> +		 * The 'field' is valid metadata for this output buffer
>> +		 * and so that needs to be copied here.
>> +		 */
>> +		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
>> +		vbuf->field = b->field;
>> +	} else {
>> +		/* Zero any output buffer flags as this is a capture buffer */
>> +		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int __fill_vb2_timestamp(struct vb2_buffer *vb, void *pb)
>> +{
>> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +	struct vb2_queue *q = vb->vb2_queue;
>> +
>> +	/*
>> +	 * For output buffers copy the timestamp if needed,
>> +	 * and the timecode field and flag if needed.
>> +	 */
>> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY)
>> +		vbuf->timestamp = b->timestamp;
>> +	vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
>> +	if (b->flags & V4L2_BUF_FLAG_TIMECODE)
>> +		vbuf->timecode = b->timecode;
>> +
>> +	return 0;
>> +};
>> +
>> +static int __is_last(struct vb2_buffer *vb)
>> +{
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +
>> +	return (vbuf->flags & V4L2_BUF_FLAG_LAST);
>> +}
>> +
>> +const struct vb2_buf_ops v4l2_buf_ops = {
>> +	.fill_user_buffer	= __fill_v4l2_buffer,
>> +	.fill_vb2_buffer	= __fill_vb2_buffer,
>> +	.fill_vb2_timestamp	= __fill_vb2_timestamp,
>> +	.is_last		= __is_last,
>> +};
>> +
>> +/**
>> + * vb2_querybuf() - query video buffer information
>> + * @q:		videobuf queue
>> + * @b:		buffer struct passed from userspace to vidioc_querybuf handler
>> + *		in driver
>> + *
>> + * Should be called from vidioc_querybuf ioctl handler in driver.
>> + * This function will verify the passed v4l2_buffer structure and fill the
>> + * relevant information for the userspace.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_querybuf handler in driver.
>> + */
>> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +{
>> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
>> +			b->length, b->m.planes, "querybuf");
>> +
>> +	return ret ? ret : vb2_core_querybuf(q, b->index, b);
>> +}
>> +EXPORT_SYMBOL(vb2_querybuf);
>> +
>> +/**
>> + * vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies
>> + * the memory and type values.
>> + * @q:		videobuf2 queue
>> + * @req:	struct passed from userspace to vidioc_reqbufs handler
>> + *		in driver
>> + */
>> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>> +{
>> +	int ret = vb2_verify_memory_type(q, req->memory, req->type);
>> +
>> +	if (ret)
>> +		return ret;
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_core_reqbufs(q, req->memory, &req->count);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_reqbufs);
>> +
>> +/**
>> + * vb2_create_bufs() - Wrapper for vb2_core_create_bufs() that also verifies
>> + * the memory and type values.
>> + * @q:		videobuf2 queue
>> + * @create:	creation parameters, passed from userspace to vidioc_create_bufs
>> + *		handler in driver
>> + */
>> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
>> +{
>> +	int ret = vb2_verify_memory_type(q, create->memory, create->format.type);
>> +
>> +	if (ret)
>> +		return ret;
>> +	if (create->count && vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +	return vb2_core_create_bufs(q, create->memory, &create->count, &create->format);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_create_bufs);
>> +
>> +/**
>> + * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
>> + * @q:		videobuf2 queue
>> + * @b:		buffer structure passed from userspace to vidioc_prepare_buf
>> + *		handler in driver
>> + *
>> + * Should be called from vidioc_prepare_buf ioctl handler of a driver.
>> + * This function:
>> + * 1) verifies the passed buffer,
>> + * 2) calls buf_prepare callback in the driver (if provided), in which
>> + *    driver-specific buffer initialization can be performed,
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_prepare_buf handler in driver.
>> + */
>> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +{
>> +	int ret;
>> +
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
>> +			b->length, b->m.planes, "prepare_buf");
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
>> +		/*
>> +		 * If the format's field is ALTERNATE, then the buffer's field
>> +		 * should be either TOP or BOTTOM, not ALTERNATE since that
>> +		 * makes no sense. The driver has to know whether the
>> +		 * buffer represents a top or a bottom field in order to
>> +		 * program any DMA correctly. Using ALTERNATE is wrong, since
>> +		 * that just says that it is either a top or a bottom field,
>> +		 * but not which of the two it is.
>> +		 */
>> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
>> +				"for an output buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	return vb2_core_prepare_buf(q, b->index, b);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_prepare_buf);
>> +
>> +static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +{
>> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
>> +			b->length, b->m.planes, "qbuf");
>> +	struct vb2_buffer *vb;
>> +
>> +	if (ret)
>> +		return ret;
>> +
>> +	vb = q->bufs[b->index];
>> +
>> +	if (vb->state == VB2_BUF_STATE_DEQUEUED
>> +			&& b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
>> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
>> +				"for an output buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	return ret ? ret : vb2_core_qbuf(q, b->index, b);
>> +}
>> +
>> +/**
>> + * vb2_qbuf() - Queue a buffer from userspace
>> + * @q:		videobuf2 queue
>> + * @b:		buffer structure passed from userspace to vidioc_qbuf handler
>> + *		in driver
>> + *
>> + * Should be called from vidioc_qbuf ioctl handler of a driver.
>> + * This function:
>> + * 1) verifies the passed buffer,
>> + * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
>> + *    which driver-specific buffer initialization can be performed,
>> + * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
>> + *    callback for processing.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_qbuf handler in driver.
>> + */
>> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_internal_qbuf(q, b);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_qbuf);
>> +
>> +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>> +			bool nonblocking)
>> +{
>> +	if (b->type != q->type) {
>> +		dprintk(1, "invalid buffer type\n");
>> +		return -EINVAL;
>> +	}
>> +	return vb2_core_dqbuf(q, b, nonblocking);
>> +}
>> +
>> +/**
>> + * vb2_dqbuf() - Dequeue a buffer to the userspace
>> + * @q:		videobuf2 queue
>> + * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
>> + *		in driver
>> + * @nonblocking: if true, this call will not sleep waiting for a buffer if no
>> + *		 buffers ready for dequeuing are present. Normally the driver
>> + *		 would be passing (file->f_flags & O_NONBLOCK) here
>> + *
>> + * Should be called from vidioc_dqbuf ioctl handler of a driver.
>> + * This function:
>> + * 1) verifies the passed buffer,
>> + * 2) calls buf_finish callback in the driver (if provided), in which
>> + *    driver can perform any additional operations that may be required before
>> + *    returning the buffer to userspace, such as cache sync,
>> + * 3) the buffer struct members are filled with relevant information for
>> + *    the userspace.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_dqbuf handler in driver.
>> + */
>> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +	return vb2_internal_dqbuf(q, b, nonblocking);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_dqbuf);
>> +
>> +/**
>> + * vb2_expbuf() - Export a buffer as a file descriptor
>> + * @q:		videobuf2 queue
>> + * @eb:		export buffer structure passed from userspace to vidioc_expbuf
>> + *		handler in driver
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_expbuf handler in driver.
>> + */
>> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index,
>> +				eb->plane, eb->flags);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_expbuf);
>> +
>> +static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>> +{
>> +	if (type != q->type) {
>> +		dprintk(1, "invalid stream type\n");
>> +		return -EINVAL;
>> +	}
>> +	return vb2_core_streamon(q);
>> +}
>> +
>> +/**
>> + * vb2_streamon - start streaming
>> + * @q:		videobuf2 queue
>> + * @type:	type argument passed from userspace to vidioc_streamon handler
>> + *
>> + * Should be called from vidioc_streamon handler of a driver.
>> + * This function:
>> + * 1) verifies current state
>> + * 2) passes any previously queued buffers to the driver and starts streaming
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_streamon handler in the driver.
>> + */
>> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +	return vb2_internal_streamon(q, type);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_streamon);
>> +
>> +static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>> +{
>> +	if (type != q->type) {
>> +		dprintk(1, "invalid stream type\n");
>> +		return -EINVAL;
>> +	}
>> +	return vb2_core_streamoff(q);
>> +}
>> +
>> +/**
>> + * vb2_streamoff - stop streaming
>> + * @q:		videobuf2 queue
>> + * @type:	type argument passed from userspace to vidioc_streamoff handler
>> + *
>> + * Should be called from vidioc_streamoff handler of a driver.
>> + * This function:
>> + * 1) verifies current state,
>> + * 2) stop streaming and dequeues any queued buffers, including those previously
>> + *    passed to the driver (after waiting for the driver to finish).
>> + *
>> + * This call can be used for pausing playback.
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_streamoff handler in the driver
>> + */
>> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +	return vb2_internal_streamoff(q, type);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_streamoff);
>> +
>> +/**
>> + * vb2_mmap() - map video buffers into application address space
>> + * @q:		videobuf2 queue
>> + * @vma:	vma passed to the mmap file operation handler in the driver
>> + *
>> + * Should be called from mmap file operation handler of a driver.
>> + * This function maps one plane of one of the available video buffers to
>> + * userspace. To map whole video memory allocated on reqbufs, this function
>> + * has to be called once per each plane per each buffer previously allocated.
>> + *
>> + * When the userspace application calls mmap, it passes to it an offset returned
>> + * to it earlier by the means of vidioc_querybuf handler. That offset acts as
>> + * a "cookie", which is then used to identify the plane to be mapped.
>> + * This function finds a plane with a matching offset and a mapping is performed
>> + * by the means of a provided memory operation.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from the mmap handler in driver.
>> + */
>> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "mmap: file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_core_mmap(q, vma);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_mmap);
>> +
>> +static int __vb2_init_fileio(struct vb2_queue *q, int read);
>> +static int __vb2_cleanup_fileio(struct vb2_queue *q);
>> +
>> +/**
>> + * vb2_poll() - implements poll userspace operation
>> + * @q:		videobuf2 queue
>> + * @file:	file argument passed to the poll file operation handler
>> + * @wait:	wait argument passed to the poll file operation handler
>> + *
>> + * This function implements poll file operation handler for a driver.
>> + * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
>> + * be informed that the file descriptor of a video device is available for
>> + * reading.
>> + * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
>> + * will be reported as available for writing.
>> + *
>> + * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
>> + * pending events.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from poll handler in driver.
>> + */
>> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
>> +{
>> +	struct video_device *vfd = video_devdata(file);
>> +	unsigned long req_events = poll_requested_events(wait);
>> +	struct vb2_buffer *vb = NULL;
>> +	unsigned int res = 0;
>> +	unsigned long flags;
>> +
>> +	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
>> +		struct v4l2_fh *fh = file->private_data;
>> +
>> +		if (v4l2_event_pending(fh))
>> +			res = POLLPRI;
>> +		else if (req_events & POLLPRI)
>> +			poll_wait(file, &fh->wait, wait);
>> +	}
>> +
>> +	if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
>> +		return res;
>> +	if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
>> +		return res;
>> +
>> +	/*
>> +	 * Start file I/O emulator only if streaming API has not been used yet.
>> +	 */
>> +	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
>> +		if (!q->is_output && (q->io_modes & VB2_READ) &&
>> +				(req_events & (POLLIN | POLLRDNORM))) {
>> +			if (__vb2_init_fileio(q, 1))
>> +				return res | POLLERR;
>> +		}
>> +		if (q->is_output && (q->io_modes & VB2_WRITE) &&
>> +				(req_events & (POLLOUT | POLLWRNORM))) {
>> +			if (__vb2_init_fileio(q, 0))
>> +				return res | POLLERR;
>> +			/*
>> +			 * Write to OUTPUT queue can be done immediately.
>> +			 */
>> +			return res | POLLOUT | POLLWRNORM;
>> +		}
>> +	}
>> +
>> +	/*
>> +	 * There is nothing to wait for if the queue isn't streaming, or if the
>> +	 * error flag is set.
>> +	 */
>> +	if (!vb2_is_streaming(q) || q->error)
>> +		return res | POLLERR;
>> +	/*
>> +	 * For compatibility with vb1: if QBUF hasn't been called yet, then
>> +	 * return POLLERR as well. This only affects capture queues, output
>> +	 * queues will always initialize waiting_for_buffers to false.
>> +	 */
>> +	if (q->waiting_for_buffers)
>> +		return res | POLLERR;
>> +
>> +	/*
>> +	 * For output streams you can write as long as there are fewer buffers
>> +	 * queued than there are buffers available.
>> +	 */
>> +	if (q->is_output && q->queued_count < q->num_buffers)
>> +		return res | POLLOUT | POLLWRNORM;
>> +
>> +	if (list_empty(&q->done_list)) {
>> +		/*
>> +		 * If the last buffer was dequeued from a capture queue,
>> +		 * return immediately. DQBUF will return -EPIPE.
>> +		 */
>> +		if (q->last_buffer_dequeued)
>> +			return res | POLLIN | POLLRDNORM;
>> +
>> +		poll_wait(file, &q->done_wq, wait);
>> +	}
>> +
>> +	/*
>> +	 * Take first buffer available for dequeuing.
>> +	 */
>> +	spin_lock_irqsave(&q->done_lock, flags);
>> +	if (!list_empty(&q->done_list))
>> +		vb = list_first_entry(&q->done_list, struct vb2_buffer,
>> +					done_entry);
>> +	spin_unlock_irqrestore(&q->done_lock, flags);
>> +
>> +	if (vb && (vb->state == VB2_BUF_STATE_DONE
>> +			|| vb->state == VB2_BUF_STATE_ERROR)) {
>> +		return (q->is_output) ?
>> +				res | POLLOUT | POLLWRNORM :
>> +				res | POLLIN | POLLRDNORM;
>> +	}
>> +	return res;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_poll);
>> +
>> +/**
>> + * vb2_queue_init() - initialize a videobuf2 queue
>> + * @q:		videobuf2 queue; this structure should be allocated in driver
>> + *
>> + * The vb2_queue structure should be allocated by the driver. The driver is
>> + * responsible of clearing it's content and setting initial values for some
>> + * required entries before calling this function.
>> + * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
>> + * to the struct vb2_queue description in include/media/videobuf2-core.h
>> + * for more information.
>> + */
>> +int vb2_queue_init(struct vb2_queue *q)
>> +{
>> +	if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
>> +		|| WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
>> +		|| WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
>> +		return -EINVAL;
>> +	/*
>> +	 * Sanity check
>> +	 */
>> +	if (WARN_ON(!q)	|| WARN_ON(!q->type))
>> +		return -EINVAL;
>> +
>> +	if (WARN_ON(q->timestamp_flags &
>> +		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
>> +		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
>> +		return -EINVAL;
>> +
>> +	/* Warn that the driver should choose an appropriate timestamp type */
>> +	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> +		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
>> +
>> +	if (q->buf_struct_size == 0)
>> +		q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
>> +
>> +	q->buf_ops = &v4l2_buf_ops;
>> +	q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
>> +	q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
>> +
>> +	return vb2_core_queue_init(q);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_queue_init);
>> +
>> +/**
>> + * vb2_queue_release() - stop streaming, release the queue and free memory
>> + * @q:		videobuf2 queue
>> + *
>> + * This function stops streaming and performs necessary clean ups, including
>> + * freeing video buffer memory. The driver is responsible for freeing
>> + * the vb2_queue structure itself.
>> + */
>> +void vb2_queue_release(struct vb2_queue *q)
>> +{
>> +	__vb2_cleanup_fileio(q);
>> +	vb2_core_queue_release(q);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_queue_release);
>> +
>> +/**
>> + * struct vb2_fileio_buf - buffer context used by file io emulator
>> + *
>> + * vb2 provides a compatibility layer and emulator of file io (read and
>> + * write) calls on top of streaming API. This structure is used for
>> + * tracking context related to the buffers.
>> + */
>> +struct vb2_fileio_buf {
>> +	void *vaddr;
>> +	unsigned int size;
>> +	unsigned int pos;
>> +	unsigned int queued:1;
>> +};
>> +
>> +/**
>> + * struct vb2_fileio_data - queue context used by file io emulator
>> + *
>> + * @cur_index:	the index of the buffer currently being read from or
>> + *		written to. If equal to q->num_buffers then a new buffer
>> + *		must be dequeued.
>> + * @initial_index: in the read() case all buffers are queued up immediately
>> + *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
>> + *		buffers. However, in the write() case no buffers are initially
>> + *		queued, instead whenever a buffer is full it is queued up by
>> + *		__vb2_perform_fileio(). Only once all available buffers have
>> + *		been queued up will __vb2_perform_fileio() start to dequeue
>> + *		buffers. This means that initially __vb2_perform_fileio()
>> + *		needs to know what buffer index to use when it is queuing up
>> + *		the buffers for the first time. That initial index is stored
>> + *		in this field. Once it is equal to q->num_buffers all
>> + *		available buffers have been queued and __vb2_perform_fileio()
>> + *		should start the normal dequeue/queue cycle.
>> + *
>> + * vb2 provides a compatibility layer and emulator of file io (read and
>> + * write) calls on top of streaming API. For proper operation it required
>> + * this structure to save the driver state between each call of the read
>> + * or write function.
>> + */
>> +struct vb2_fileio_data {
>> +	struct v4l2_requestbuffers req;
>> +	struct v4l2_plane p;
>> +	struct v4l2_buffer b;
>> +	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
>> +	unsigned int cur_index;
>> +	unsigned int initial_index;
>> +	unsigned int q_count;
>> +	unsigned int dq_count;
>> +	unsigned read_once:1;
>> +	unsigned write_immediately:1;
>> +};
>> +
>> +/**
>> + * __vb2_init_fileio() - initialize file io emulator
>> + * @q:		videobuf2 queue
>> + * @read:	mode selector (1 means read, 0 means write)
>> + */
>> +static int __vb2_init_fileio(struct vb2_queue *q, int read)
>> +{
>> +	struct vb2_fileio_data *fileio;
>> +	int i, ret;
>> +	unsigned int count = 0;
>> +
>> +	/*
>> +	 * Sanity check
>> +	 */
>> +	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
>> +			(!read && !(q->io_modes & VB2_WRITE))))
>> +		return -EINVAL;
>> +
>> +	/*
>> +	 * Check if device supports mapping buffers to kernel virtual space.
>> +	 */
>> +	if (!q->mem_ops->vaddr)
>> +		return -EBUSY;
>> +
>> +	/*
>> +	 * Check if streaming api has not been already activated.
>> +	 */
>> +	if (q->streaming || q->num_buffers > 0)
>> +		return -EBUSY;
>> +
>> +	/*
>> +	 * Start with count 1, driver can increase it in queue_setup()
>> +	 */
>> +	count = 1;
>> +
>> +	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, "
>> +		"write_immediately %d\n",
>> +		(read) ? "read" : "write", count, q->fileio_read_once,
>> +		q->fileio_write_immediately);
>> +
>> +	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
>> +	if (fileio == NULL)
>> +		return -ENOMEM;
>> +
>> +	fileio->read_once = q->fileio_read_once;
>> +	fileio->write_immediately = q->fileio_write_immediately;
>> +
>> +	/*
>> +	 * Request buffers and use MMAP type to force driver
>> +	 * to allocate buffers by itself.
>> +	 */
>> +	fileio->req.count = count;
>> +	fileio->req.memory = V4L2_MEMORY_MMAP;
>> +	fileio->req.type = q->type;
>> +	q->fileio = fileio;
>> +	ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
>> +	if (ret)
>> +		goto err_kfree;
>> +
>> +	/*
>> +	 * Check if plane_count is correct
>> +	 * (multiplane buffers are not supported).
>> +	 */
>> +	if (q->bufs[0]->num_planes != 1) {
>> +		ret = -EBUSY;
>> +		goto err_reqbufs;
>> +	}
>> +
>> +	/*
>> +	 * Get kernel address of each buffer.
>> +	 */
>> +	for (i = 0; i < q->num_buffers; i++) {
>> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>> +		if (fileio->bufs[i].vaddr == NULL) {
>> +			ret = -EINVAL;
>> +			goto err_reqbufs;
>> +		}
>> +		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>> +	}
>> +
>> +	/*
>> +	 * Read mode requires pre queuing of all buffers.
>> +	 */
>> +	if (read) {
>> +		bool is_multiplanar = q->is_multiplanar;
>> +
>> +		/*
>> +		 * Queue all buffers.
>> +		 */
>> +		for (i = 0; i < q->num_buffers; i++) {
>> +			struct v4l2_buffer *b = &fileio->b;
>> +
>> +			memset(b, 0, sizeof(*b));
>> +			b->type = q->type;
>> +			if (is_multiplanar) {
>> +				memset(&fileio->p, 0, sizeof(fileio->p));
>> +				b->m.planes = &fileio->p;
>> +				b->length = 1;
>> +			}
>> +			b->memory = q->memory;
>> +			b->index = i;
>> +			ret = vb2_internal_qbuf(q, b);
>> +			if (ret)
>> +				goto err_reqbufs;
>> +			fileio->bufs[i].queued = 1;
>> +		}
>> +		/*
>> +		 * All buffers have been queued, so mark that by setting
>> +		 * initial_index to q->num_buffers
>> +		 */
>> +		fileio->initial_index = q->num_buffers;
>> +		fileio->cur_index = q->num_buffers;
>> +	}
>> +
>> +	/*
>> +	 * Start streaming.
>> +	 */
>> +	ret = vb2_internal_streamon(q, q->type);
>> +	if (ret)
>> +		goto err_reqbufs;
>> +
>> +	return ret;
>> +
>> +err_reqbufs:
>> +	fileio->req.count = 0;
>> +	vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
>> +
>> +err_kfree:
>> +	q->fileio = NULL;
>> +	kfree(fileio);
>> +	return ret;
>> +}
>> +
>> +/**
>> + * __vb2_cleanup_fileio() - free resourced used by file io emulator
>> + * @q:		videobuf2 queue
>> + */
>> +static int __vb2_cleanup_fileio(struct vb2_queue *q)
>> +{
>> +	struct vb2_fileio_data *fileio = q->fileio;
>> +
>> +	if (fileio) {
>> +		vb2_internal_streamoff(q, q->type);
>> +		q->fileio = NULL;
>> +		fileio->req.count = 0;
>> +		vb2_reqbufs(q, &fileio->req);
>> +		kfree(fileio);
>> +		dprintk(3, "file io emulator closed\n");
>> +	}
>> +	return 0;
>> +}
>> +
>> +/**
>> + * __vb2_perform_fileio() - perform a single file io (read or write) operation
>> + * @q:		videobuf2 queue
>> + * @data:	pointed to target userspace buffer
>> + * @count:	number of bytes to read or write
>> + * @ppos:	file handle position tracking pointer
>> + * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
>> + * @read:	access mode selector (1 means read, 0 means write)
>> + */
>> +static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data,
>> +		size_t count, loff_t *ppos, int nonblock, int read)
>> +{
>> +	struct vb2_fileio_data *fileio;
>> +	struct vb2_fileio_buf *buf;
>> +	bool is_multiplanar = q->is_multiplanar;
>> +	/*
>> +	 * When using write() to write data to an output video node the vb2 core
>> +	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
>> +	 * else is able to provide this information with the write() operation.
>> +	 */
>> +	bool set_timestamp = !read &&
>> +		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> +		V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> +	int ret, index;
>> +
>> +	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
>> +		read ? "read" : "write", (long)*ppos, count,
>> +		nonblock ? "non" : "");
>> +
>> +	if (!data)
>> +		return -EINVAL;
>> +
>> +	/*
>> +	 * Initialize emulator on first call.
>> +	 */
>> +	if (!vb2_fileio_is_active(q)) {
>> +		ret = __vb2_init_fileio(q, read);
>> +		dprintk(3, "vb2_init_fileio result: %d\n", ret);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +	fileio = q->fileio;
>> +
>> +	/*
>> +	 * Check if we need to dequeue the buffer.
>> +	 */
>> +	index = fileio->cur_index;
>> +	if (index >= q->num_buffers) {
>> +		/*
>> +		 * Call vb2_dqbuf to get buffer back.
>> +		 */
>> +		memset(&fileio->b, 0, sizeof(fileio->b));
>> +		fileio->b.type = q->type;
>> +		fileio->b.memory = q->memory;
>> +		if (is_multiplanar) {
>> +			memset(&fileio->p, 0, sizeof(fileio->p));
>> +			fileio->b.m.planes = &fileio->p;
>> +			fileio->b.length = 1;
>> +		}
>> +		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
>> +		dprintk(5, "vb2_dqbuf result: %d\n", ret);
>> +		if (ret)
>> +			return ret;
>> +		fileio->dq_count += 1;
>> +
>> +		fileio->cur_index = index = fileio->b.index;
>> +		buf = &fileio->bufs[index];
>> +
>> +		/*
>> +		 * Get number of bytes filled by the driver
>> +		 */
>> +		buf->pos = 0;
>> +		buf->queued = 0;
>> +		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>> +				 : vb2_plane_size(q->bufs[index], 0);
>> +
>> +		/*
>> +		 * Compensate for data_offset on read
>> +		 * in the multiplanar case.
>> +		 */
>> +		if (is_multiplanar && read &&
>> +			fileio->b.m.planes[0].data_offset < buf->size) {
>> +			buf->pos = fileio->b.m.planes[0].data_offset;
>> +			buf->size -= buf->pos;
>> +		}
>> +	} else {
>> +		buf = &fileio->bufs[index];
>> +	}
>> +
>> +	/*
>> +	 * Limit count on last few bytes of the buffer.
>> +	 */
>> +	if (buf->pos + count > buf->size) {
>> +		count = buf->size - buf->pos;
>> +		dprintk(5, "reducing read count: %zd\n", count);
>> +	}
>> +
>> +	/*
>> +	 * Transfer data to userspace.
>> +	 */
>> +	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
>> +		count, index, buf->pos);
>> +	if (read)
>> +		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
>> +	else
>> +		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
>> +	if (ret) {
>> +		dprintk(3, "error copying data\n");
>> +		return -EFAULT;
>> +	}
>> +
>> +	/*
>> +	 * Update counters.
>> +	 */
>> +	buf->pos += count;
>> +	*ppos += count;
>> +
>> +	/*
>> +	 * Queue next buffer if required.
>> +	 */
>> +	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>> +		/*
>> +		 * Check if this is the last buffer to read.
>> +		 */
>> +		if (read && fileio->read_once && fileio->dq_count == 1) {
>> +			dprintk(3, "read limit reached\n");
>> +			return __vb2_cleanup_fileio(q);
>> +		}
>> +
>> +		/*
>> +		 * Call vb2_qbuf and give buffer to the driver.
>> +		 */
>> +		memset(&fileio->b, 0, sizeof(fileio->b));
>> +		fileio->b.type = q->type;
>> +		fileio->b.memory = q->memory;
>> +		fileio->b.index = index;
>> +		fileio->b.bytesused = buf->pos;
>> +		if (is_multiplanar) {
>> +			memset(&fileio->p, 0, sizeof(fileio->p));
>> +			fileio->p.bytesused = buf->pos;
>> +			fileio->b.m.planes = &fileio->p;
>> +			fileio->b.length = 1;
>> +		}
>> +		if (set_timestamp)
>> +			v4l2_get_timestamp(&fileio->b.timestamp);
>> +		ret = vb2_internal_qbuf(q, &fileio->b);
>> +		dprintk(5, "vb2_dbuf result: %d\n", ret);
>> +		if (ret)
>> +			return ret;
>> +
>> +		/*
>> +		 * Buffer has been queued, update the status
>> +		 */
>> +		buf->pos = 0;
>> +		buf->queued = 1;
>> +		buf->size = vb2_plane_size(q->bufs[index], 0);
>> +		fileio->q_count += 1;
>> +		/*
>> +		 * If we are queuing up buffers for the first time, then
>> +		 * increase initial_index by one.
>> +		 */
>> +		if (fileio->initial_index < q->num_buffers)
>> +			fileio->initial_index++;
>> +		/*
>> +		 * The next buffer to use is either a buffer that's going to be
>> +		 * queued for the first time (initial_index < q->num_buffers)
>> +		 * or it is equal to q->num_buffers, meaning that the next
>> +		 * time we need to dequeue a buffer since we've now queued up
>> +		 * all the 'first time' buffers.
>> +		 */
>> +		fileio->cur_index = fileio->initial_index;
>> +	}
>> +
>> +	/*
>> +	 * Return proper number of bytes processed.
>> +	 */
>> +	if (ret == 0)
>> +		ret = count;
>> +	return ret;
>> +}
>> +
>> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
>> +		loff_t *ppos, int nonblocking)
>> +{
>> +	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_read);
>> +
>> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
>> +		loff_t *ppos, int nonblocking)
>> +{
>> +	return __vb2_perform_fileio(q, (char __user *) data, count,
>> +							ppos, nonblocking, 0);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_write);
>> +
>> +struct vb2_threadio_data {
>> +	struct task_struct *thread;
>> +	vb2_thread_fnc fnc;
>> +	void *priv;
>> +	bool stop;
>> +};
>> +
>> +static int vb2_thread(void *data)
>> +{
>> +	struct vb2_queue *q = data;
>> +	struct vb2_threadio_data *threadio = q->threadio;
>> +	struct vb2_fileio_data *fileio = q->fileio;
>> +	bool set_timestamp = false;
>> +	int prequeue = 0;
>> +	int index = 0;
>> +	int ret = 0;
>> +
>> +	if (q->is_output) {
>> +		prequeue = q->num_buffers;
>> +		set_timestamp =
>> +			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> +	}
>> +
>> +	set_freezable();
>> +
>> +	for (;;) {
>> +		struct vb2_buffer *vb;
>> +
>> +		/*
>> +		 * Call vb2_dqbuf to get buffer back.
>> +		 */
>> +		memset(&fileio->b, 0, sizeof(fileio->b));
>> +		fileio->b.type = q->type;
>> +		fileio->b.memory = q->memory;
>> +		if (prequeue) {
>> +			fileio->b.index = index++;
>> +			prequeue--;
>> +		} else {
>> +			call_void_qop(q, wait_finish, q);
>> +			if (!threadio->stop)
>> +				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
>> +			call_void_qop(q, wait_prepare, q);
>> +			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
>> +		}
>> +		if (ret || threadio->stop)
>> +			break;
>> +		try_to_freeze();
>> +
>> +		vb = q->bufs[fileio->b.index];
>> +		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
>> +			if (threadio->fnc(vb, threadio->priv))
>> +				break;
>> +		call_void_qop(q, wait_finish, q);
>> +		if (set_timestamp)
>> +			v4l2_get_timestamp(&fileio->b.timestamp);
>> +		if (!threadio->stop)
>> +			ret = vb2_internal_qbuf(q, &fileio->b);
>> +		call_void_qop(q, wait_prepare, q);
>> +		if (ret || threadio->stop)
>> +			break;
>> +	}
>> +
>> +	/* Hmm, linux becomes *very* unhappy without this ... */
>> +	while (!kthread_should_stop()) {
>> +		set_current_state(TASK_INTERRUPTIBLE);
>> +		schedule();
>> +	}
>> +	return 0;
>> +}
>> +
>> +/*
>> + * This function should not be used for anything else but the videobuf2-dvb
>> + * support. If you think you have another good use-case for this, then please
>> + * contact the linux-media mailinglist first.
>> + */
>> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
>> +			const char *thread_name)
>> +{
>> +	struct vb2_threadio_data *threadio;
>> +	int ret = 0;
>> +
>> +	if (q->threadio)
>> +		return -EBUSY;
>> +	if (vb2_is_busy(q))
>> +		return -EBUSY;
>> +	if (WARN_ON(q->fileio))
>> +		return -EBUSY;
>> +
>> +	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
>> +	if (threadio == NULL)
>> +		return -ENOMEM;
>> +	threadio->fnc = fnc;
>> +	threadio->priv = priv;
>> +
>> +	ret = __vb2_init_fileio(q, !q->is_output);
>> +	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
>> +	if (ret)
>> +		goto nomem;
>> +	q->threadio = threadio;
>> +	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
>> +	if (IS_ERR(threadio->thread)) {
>> +		ret = PTR_ERR(threadio->thread);
>> +		threadio->thread = NULL;
>> +		goto nothread;
>> +	}
>> +	return 0;
>> +
>> +nothread:
>> +	__vb2_cleanup_fileio(q);
>> +nomem:
>> +	kfree(threadio);
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_thread_start);
>> +
>> +int vb2_thread_stop(struct vb2_queue *q)
>> +{
>> +	struct vb2_threadio_data *threadio = q->threadio;
>> +	int err;
>> +
>> +	if (threadio == NULL)
>> +		return 0;
>> +	threadio->stop = true;
>> +	/* Wake up all pending sleeps in the thread */
>> +	vb2_queue_error(q);
>> +	err = kthread_stop(threadio->thread);
>> +	__vb2_cleanup_fileio(q);
>> +	threadio->thread = NULL;
>> +	kfree(threadio);
>> +	q->threadio = NULL;
>> +	return err;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_thread_stop);
>> +
>> +/*
>> + * The following functions are not part of the vb2 core API, but are helper
>> + * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
>> + * and struct vb2_ops.
>> + * They contain boilerplate code that most if not all drivers have to do
>> + * and so they simplify the driver code.
>> + */
>> +
>> +/* The queue is busy if there is a owner and you are not that owner. */
>> +static inline
>> +bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
>> +{
>> +	return vdev->queue->owner && vdev->queue->owner != file->private_data;
>> +}
>> +
>> +/* vb2 ioctl helpers */
>> +
>> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
>> +			  struct v4l2_requestbuffers *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
>> +
>> +	if (res)
>> +		return res;
>> +	if (vb2_fileio_is_active(vdev->queue))
>> +		return -EBUSY;
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count);
>> +	/* If count == 0, then the owner has released all buffers and he
>> +	   is no longer owner of the queue. Otherwise we have a new owner. */
>> +	if (res == 0)
>> +		vdev->queue->owner = p->count ? file->private_data : NULL;
>> +	return res;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
>> +
>> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
>> +			  struct v4l2_create_buffers *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	int res = vb2_verify_memory_type(vdev->queue,
>> +				p->memory, p->format.type);
>> +
>> +	if (vb2_fileio_is_active(vdev->queue))
>> +		return -EBUSY;
>> +	p->index = vdev->queue->num_buffers;
>> +	/* If count == 0, then just check if memory and type are valid.
>> +	   Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. */
>> +	if (p->count == 0)
>> +		return res != -EBUSY ? res : 0;
>> +	if (res)
>> +		return res;
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	res = vb2_core_create_bufs(vdev->queue,
>> +				p->memory, &p->count, &p->format);
>> +	if (res == 0)
>> +		vdev->queue->owner = file->private_data;
>> +	return res;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
>> +
>> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
>> +			  struct v4l2_buffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_prepare_buf(vdev->queue, p);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
>> +
>> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
>> +	return vb2_querybuf(vdev->queue, p);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
>> +
>> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_qbuf(vdev->queue, p);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
>> +
>> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
>> +
>> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_streamon(vdev->queue, i);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
>> +
>> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_streamoff(vdev->queue, i);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
>> +
>> +int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_expbuf(vdev->queue, p);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
>> +
>> +/* v4l2_file_operations helpers */
>> +
>> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_fileio_is_active(vdev->queue)) {
>> +		dprintk(1, "mmap: file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_mmap(vdev->queue, vma);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_mmap);
>> +
>> +int _vb2_fop_release(struct file *file, struct mutex *lock)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (lock)
>> +		mutex_lock(lock);
>> +	if (file->private_data == vdev->queue->owner) {
>> +		vb2_queue_release(vdev->queue);
>> +		vdev->queue->owner = NULL;
>> +	}
>> +	if (lock)
>> +		mutex_unlock(lock);
>> +	return v4l2_fh_release(file);
>> +}
>> +EXPORT_SYMBOL_GPL(_vb2_fop_release);
>> +
>> +int vb2_fop_release(struct file *file)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> +
>> +	return _vb2_fop_release(file, lock);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_release);
>> +
>> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>> +		size_t count, loff_t *ppos)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> +	int err = -EBUSY;
>> +
>> +	if (!(vdev->queue->io_modes & VB2_WRITE))
>> +		return -EINVAL;
>> +	if (lock && mutex_lock_interruptible(lock))
>> +		return -ERESTARTSYS;
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		goto exit;
>> +	err = vb2_write(vdev->queue, buf, count, ppos,
>> +			file->f_flags & O_NONBLOCK);
>> +	if (vdev->queue->fileio)
>> +		vdev->queue->owner = file->private_data;
>> +exit:
>> +	if (lock)
>> +		mutex_unlock(lock);
>> +	return err;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_write);
>> +
>> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
>> +		size_t count, loff_t *ppos)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> +	int err = -EBUSY;
>> +
>> +	if (!(vdev->queue->io_modes & VB2_READ))
>> +		return -EINVAL;
>> +	if (lock && mutex_lock_interruptible(lock))
>> +		return -ERESTARTSYS;
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		goto exit;
>> +	err = vb2_read(vdev->queue, buf, count, ppos,
>> +			file->f_flags & O_NONBLOCK);
>> +	if (vdev->queue->fileio)
>> +		vdev->queue->owner = file->private_data;
>> +exit:
>> +	if (lock)
>> +		mutex_unlock(lock);
>> +	return err;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_read);
>> +
>> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	struct vb2_queue *q = vdev->queue;
>> +	struct mutex *lock = q->lock ? q->lock : vdev->lock;
>> +	unsigned res;
>> +	void *fileio;
>> +
>> +	/*
>> +	 * If this helper doesn't know how to lock, then you shouldn't be using
>> +	 * it but you should write your own.
>> +	 */
>> +	WARN_ON(!lock);
>> +
>> +	if (lock && mutex_lock_interruptible(lock))
>> +		return POLLERR;
>> +
>> +	fileio = q->fileio;
>> +
>> +	res = vb2_poll(vdev->queue, file, wait);
>> +
>> +	/* If fileio was started, then we have a new queue owner. */
>> +	if (!fileio && q->fileio)
>> +		q->owner = file->private_data;
>> +	if (lock)
>> +		mutex_unlock(lock);
>> +	return res;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_poll);
>> +
>> +#ifndef CONFIG_MMU
>> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>> +		unsigned long len, unsigned long pgoff, unsigned long flags)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
>> +#endif
>> +
>> +/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
>> +
>> +void vb2_ops_wait_prepare(struct vb2_queue *vq)
>> +{
>> +	mutex_unlock(vq->lock);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
>> +
>> +void vb2_ops_wait_finish(struct vb2_queue *vq)
>> +{
>> +	mutex_lock(vq->lock);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
>> +
>>   MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
>>   MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
>>   MODULE_LICENSE("GPL");
>> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
>> index 09d7529..4044bed 100644
>> --- a/include/media/videobuf2-core.h
>> +++ b/include/media/videobuf2-core.h
>> @@ -15,9 +15,18 @@
>>   #include <linux/mm_types.h>
>>   #include <linux/mutex.h>
>>   #include <linux/poll.h>
>> -#include <linux/videodev2.h>
>>   #include <linux/dma-buf.h>
>>
>> +#define VB2_MAX_FRAME	(32)
>> +#define VB2_MAX_PLANES	(8)
>> +
>> +enum vb2_memory {
>> +	VB2_MEMORY_UNKNOWN	= 0,
>> +	VB2_MEMORY_MMAP		= 1,
>> +	VB2_MEMORY_USERPTR	= 2,
>> +	VB2_MEMORY_DMABUF	= 4,
>> +};
>> +
>>   struct vb2_alloc_ctx;
>>   struct vb2_fileio_data;
>>   struct vb2_threadio_data;
>> @@ -198,7 +207,7 @@ struct vb2_buffer {
>>   	unsigned int		type;
>>   	unsigned int		memory;
>>   	unsigned int		num_planes;
>> -	struct vb2_plane	planes[VIDEO_MAX_PLANES];
>> +	struct vb2_plane	planes[VB2_MAX_PLANES];
>>
>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>>   	/*
>> @@ -330,18 +339,24 @@ struct vb2_ops {
>>   	void (*buf_queue)(struct vb2_buffer *vb);
>>   };
>>
>> -struct v4l2_fh;
>> +struct vb2_buf_ops {
>> +	int (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
>> +	int (*fill_vb2_buffer)(struct vb2_buffer *vb, void *pb,
>> +				struct vb2_plane *planes);
>> +	int (*fill_vb2_timestamp)(struct vb2_buffer *vb, void *pb);
>> +	int (*is_last)(struct vb2_buffer *vb);
>> +};
>>
>>   /**
>>    * struct vb2_queue - a videobuf queue
>>    *
>> - * @type:	queue type (see V4L2_BUF_TYPE_* in linux/videodev2.h
>> + * @type:	queue type (see VB2_BUF_TYPE_*)
>>    * @io_modes:	supported io methods (see vb2_io_modes enum)
>>    * @fileio_read_once:		report EOF after reading the first buffer
>>    * @fileio_write_immediately:	queue buffer after each write() call
>>    * @allow_zero_bytesused:	allow bytesused == 0 to be passed to the driver
>>    * @lock:	pointer to a mutex that protects the vb2_queue struct. The
>> - *		driver can set this to a mutex to let the v4l2 core serialize
>> + *		driver can set this to a mutex to let the vb2 core serialize
>>    *		the queuing ioctls. If the driver wants to handle locking
>>    *		itself, then this should be set to NULL. This lock is not used
>>    *		by the videobuf2 core API.
>> @@ -351,10 +366,13 @@ struct v4l2_fh;
>>    *		drivers to easily associate an owner filehandle with the queue.
>>    * @ops:	driver-specific callbacks
>>    * @mem_ops:	memory allocator specific callbacks
>> + * @buf_ops:	callbacks to deliver buffer information
>> + *		between user-space and kernel-space
>>    * @drv_priv:	driver private data
>>    * @buf_struct_size: size of the driver-specific buffer structure;
>>    *		"0" indicates the driver doesn't want to use a custom buffer
>> - *		structure type, so sizeof(struct vb2_buffer) will is used
>> + *		structure type, so, sizeof(struct vb2_v4l2_buffer) will is used
>> + *		in case of v4l2.
>>    * @timestamp_flags: Timestamp flags; V4L2_BUF_FLAG_TIMESTAMP_* and
>>    *		V4L2_BUF_FLAG_TSTAMP_SRC_*
>>    * @gfp_flags:	additional gfp flags used when allocating the buffers.
>> @@ -385,6 +403,8 @@ struct v4l2_fh;
>>    * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
>>    *		buffers. Only set for capture queues if qbuf has not yet been
>>    *		called since poll() needs to return POLLERR in that situation.
>> + * @is_multiplanar: set if buffer type is multiplanar
>> + * @is_output:	set if buffer type is output
>>    * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
>>    *		last decoded buffer was already dequeued. Set for capture queues
>>    *		when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
>> @@ -399,10 +419,12 @@ struct vb2_queue {
>>   	unsigned			allow_zero_bytesused:1;
>>
>>   	struct mutex			*lock;
>> -	struct v4l2_fh			*owner;
>> +	void				*owner;
>>
>>   	const struct vb2_ops		*ops;
>>   	const struct vb2_mem_ops	*mem_ops;
>> +	const struct vb2_buf_ops	*buf_ops;
>> +
>>   	void				*drv_priv;
>>   	unsigned int			buf_struct_size;
>>   	u32				timestamp_flags;
>> @@ -412,7 +434,7 @@ struct vb2_queue {
>>   	/* private: internal use only */
>>   	struct mutex			mmap_lock;
>>   	unsigned int			memory;
>> -	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
>> +	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
>>   	unsigned int			num_buffers;
>>
>>   	struct list_head		queued_list;
>> @@ -423,13 +445,15 @@ struct vb2_queue {
>>   	spinlock_t			done_lock;
>>   	wait_queue_head_t		done_wq;
>>
>> -	void				*alloc_ctx[VIDEO_MAX_PLANES];
>> -	unsigned int			plane_sizes[VIDEO_MAX_PLANES];
>> +	void				*alloc_ctx[VB2_MAX_PLANES];
>> +	unsigned int			plane_sizes[VB2_MAX_PLANES];
>>
>>   	unsigned int			streaming:1;
>>   	unsigned int			start_streaming_called:1;
>>   	unsigned int			error:1;
>>   	unsigned int			waiting_for_buffers:1;
>> +	unsigned int			is_multiplanar:1;
>> +	unsigned int			is_output:1;
>>   	unsigned int			last_buffer_dequeued:1;
>>
>>   	struct vb2_fileio_data		*fileio;
>> @@ -455,25 +479,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
>>   void vb2_discard_done(struct vb2_queue *q);
>>   int vb2_wait_for_all_buffers(struct vb2_queue *q);
>>
>> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
>> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
>> -
>> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
>> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
>> -
>> -int __must_check vb2_queue_init(struct vb2_queue *q);
>> -
>> -void vb2_queue_release(struct vb2_queue *q);
>>   void vb2_queue_error(struct vb2_queue *q);
>> -
>> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
>> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
>> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
>> -
>> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
>> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
>> -
>> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
>>   #ifndef CONFIG_MMU
>>   unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>   				    unsigned long addr,
>> @@ -481,41 +487,6 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>   				    unsigned long pgoff,
>>   				    unsigned long flags);
>>   #endif
>> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
>> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
>> -		loff_t *ppos, int nonblock);
>> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
>> -		loff_t *ppos, int nonblock);
>> -
>> -/*
>> - * vb2_thread_fnc - callback function for use with vb2_thread
>> - *
>> - * This is called whenever a buffer is dequeued in the thread.
>> - */
>> -typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
>> -
>> -/**
>> - * vb2_thread_start() - start a thread for the given queue.
>> - * @q:		videobuf queue
>> - * @fnc:	callback function
>> - * @priv:	priv pointer passed to the callback function
>> - * @thread_name:the name of the thread. This will be prefixed with "vb2-".
>> - *
>> - * This starts a thread that will queue and dequeue until an error occurs
>> - * or @vb2_thread_stop is called.
>> - *
>> - * This function should not be used for anything else but the videobuf2-dvb
>> - * support. If you think you have another good use-case for this, then please
>> - * contact the linux-media mailinglist first.
>> - */
>> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
>> -		     const char *thread_name);
>> -
>> -/**
>> - * vb2_thread_stop() - stop the thread for the given queue.
>> - * @q:		videobuf queue
>> - */
>> -int vb2_thread_stop(struct vb2_queue *q);
>>
>>   /**
>>    * vb2_is_streaming() - return streaming status of the queue
>> @@ -527,23 +498,6 @@ static inline bool vb2_is_streaming(struct vb2_queue *q)
>>   }
>>
>>   /**
>> - * vb2_fileio_is_active() - return true if fileio is active.
>> - * @q:		videobuf queue
>> - *
>> - * This returns true if read() or write() is used to stream the data
>> - * as opposed to stream I/O. This is almost never an important distinction,
>> - * except in rare cases. One such case is that using read() or write() to
>> - * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
>> - * is no way you can pass the field information of each buffer to/from
>> - * userspace. A driver that supports this field format should check for
>> - * this in the queue_setup op and reject it if this function returns true.
>> - */
>> -static inline bool vb2_fileio_is_active(struct vb2_queue *q)
>> -{
>> -	return q->fileio;
>> -}
>> -
>> -/**
>>    * vb2_is_busy() - return busy status of the queue
>>    * @q:		videobuf queue
>>    *
>> @@ -620,47 +574,4 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q)
>>   	q->last_buffer_dequeued = false;
>>   }
>>
>> -/*
>> - * The following functions are not part of the vb2 core API, but are simple
>> - * helper functions that you can use in your struct v4l2_file_operations,
>> - * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock
>> - * or video_device->lock is set, and they will set and test vb2_queue->owner
>> - * to check if the calling filehandle is permitted to do the queuing operation.
>> - */
>> -
>> -/* struct v4l2_ioctl_ops helpers */
>> -
>> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
>> -			  struct v4l2_requestbuffers *p);
>> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
>> -			  struct v4l2_create_buffers *p);
>> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
>> -			  struct v4l2_buffer *p);
>> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
>> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
>> -int vb2_ioctl_expbuf(struct file *file, void *priv,
>> -	struct v4l2_exportbuffer *p);
>> -
>> -/* struct v4l2_file_operations helpers */
>> -
>> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
>> -int vb2_fop_release(struct file *file);
>> -int _vb2_fop_release(struct file *file, struct mutex *lock);
>> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>> -		size_t count, loff_t *ppos);
>> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
>> -		size_t count, loff_t *ppos);
>> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
>> -#ifndef CONFIG_MMU
>> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>> -		unsigned long len, unsigned long pgoff, unsigned long flags);
>> -#endif
>> -
>> -/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
>> -
>> -void vb2_ops_wait_prepare(struct vb2_queue *vq);
>> -void vb2_ops_wait_finish(struct vb2_queue *vq);
>>   #endif /* _MEDIA_VIDEOBUF2_CORE_H */
>> diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
>> index fc2dbe9..790cb7a 100644
>> --- a/include/media/videobuf2-v4l2.h
>> +++ b/include/media/videobuf2-v4l2.h
>> @@ -40,4 +40,120 @@ struct vb2_v4l2_buffer {
>>   #define to_vb2_v4l2_buffer(vb) \
>>   	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
>>
>> +
>> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
>> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
>> +
>> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
>> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
>> +
>> +int __must_check vb2_queue_init(struct vb2_queue *q);
>> +
>> +void vb2_queue_release(struct vb2_queue *q);
>> +
>> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
>> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
>> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
>> +
>> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
>> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
>> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
>> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
>> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
>> +		loff_t *ppos, int nonblock);
>> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
>> +		loff_t *ppos, int nonblock);
>> +
>> +/*
>> + * vb2_thread_fnc - callback function for use with vb2_thread
>> + *
>> + * This is called whenever a buffer is dequeued in the thread.
>> + */
>> +typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
>> +
>> +/**
>> + * vb2_thread_start() - start a thread for the given queue.
>> + * @q:		videobuf queue
>> + * @fnc:	callback function
>> + * @priv:	priv pointer passed to the callback function
>> + * @thread_name:the name of the thread. This will be prefixed with "vb2-".
>> + *
>> + * This starts a thread that will queue and dequeue until an error occurs
>> + * or @vb2_thread_stop is called.
>> + *
>> + * This function should not be used for anything else but the videobuf2-dvb
>> + * support. If you think you have another good use-case for this, then please
>> + * contact the linux-media mailinglist first.
>> + */
>> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
>> +		     const char *thread_name);
>> +
>> +/**
>> + * vb2_thread_stop() - stop the thread for the given queue.
>> + * @q:		videobuf queue
>> + */
>> +int vb2_thread_stop(struct vb2_queue *q);
>> +
>> +/**
>> + * vb2_fileio_is_active() - return true if fileio is active.
>> + * @q:		videobuf queue
>> + *
>> + * This returns true if read() or write() is used to stream the data
>> + * as opposed to stream I/O. This is almost never an important distinction,
>> + * except in rare cases. One such case is that using read() or write() to
>> + * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
>> + * is no way you can pass the field information of each buffer to/from
>> + * userspace. A driver that supports this field format should check for
>> + * this in the queue_setup op and reject it if this function returns true.
>> + */
>> +static inline bool vb2_fileio_is_active(struct vb2_queue *q)
>> +{
>> +	return q->fileio;
>> +}
>> +
>> +/*
>> + * The following functions are not part of the vb2 core API, but are simple
>> + * helper functions that you can use in your struct v4l2_file_operations,
>> + * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize
>> + * if vb2_queue->lock or video_device->lock is set, and they will set
>> + * and test vb2_queue->owner to check if the calling filehandle is permitted
>> + * to do the queuing operation.
>> + */
>> +
>> +/* struct v4l2_ioctl_ops helpers */
>> +
>> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
>> +			  struct v4l2_requestbuffers *p);
>> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
>> +			  struct v4l2_create_buffers *p);
>> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
>> +			  struct v4l2_buffer *p);
>> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
>> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
>> +int vb2_ioctl_expbuf(struct file *file, void *priv,
>> +	struct v4l2_exportbuffer *p);
>> +
>> +/* struct v4l2_file_operations helpers */
>> +
>> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
>> +int vb2_fop_release(struct file *file);
>> +int _vb2_fop_release(struct file *file, struct mutex *lock);
>> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>> +		size_t count, loff_t *ppos);
>> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
>> +		size_t count, loff_t *ppos);
>> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
>> +#ifndef CONFIG_MMU
>> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>> +		unsigned long len, unsigned long pgoff, unsigned long flags);
>> +#endif
>> +
>> +/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
>> +
>> +void vb2_ops_wait_prepare(struct vb2_queue *vq);
>> +void vb2_ops_wait_finish(struct vb2_queue *vq);
>> +
>>   #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
>> diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
>> index b015b38..f31b258 100644
>> --- a/include/trace/events/v4l2.h
>> +++ b/include/trace/events/v4l2.h
>> @@ -5,6 +5,7 @@
>>   #define _TRACE_V4L2_H
>>
>>   #include <linux/tracepoint.h>
>> +#include <media/videobuf2-v4l2.h>
>>
>>   /* Enums require being exported to userspace, for user tool parsing */
>>   #undef EM
>> @@ -203,7 +204,8 @@ DECLARE_EVENT_CLASS(vb2_event_class,
>>
>>   	TP_fast_assign(
>>   		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> -		__entry->minor = q->owner ? q->owner->vdev->minor : -1;
>> +		struct v4l2_fh *owner = (struct v4l2_fh *) q->owner;
>> +		__entry->minor = owner ? owner->vdev->minor : -1;
>>   		__entry->queued_count = q->queued_count;
>>   		__entry->owned_by_drv_count =
>>   			atomic_read(&q->owned_by_drv_count);
>
> Regards,
> Mauro
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts
  2015-08-28  6:50     ` Junghak Sung
@ 2015-08-28  9:05       ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2015-08-28  9:05 UTC (permalink / raw)
  To: Junghak Sung
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Em Fri, 28 Aug 2015 15:50:30 +0900
Junghak Sung <jh1009.sung@samsung.com> escreveu:

> 
> 
> On 08/27/2015 08:43 PM, Mauro Carvalho Chehab wrote:
> > Em Wed, 26 Aug 2015 20:59:32 +0900
> > Junghak Sung <jh1009.sung@samsung.com> escreveu:
> >
> >> Divide videobuf2-core into core part and v4l2-specific part
> >> - core part: videobuf2 core related with buffer management & memory
> >>   allocation
> >> - v4l2-specific part: v4l2-specific stuff
> >
> > This patch is really hard to review, as the diff changes are too high to
> > be useful. I did a patch before this one doing a:
> > 	cp drivers/media/v4l2-core/videobuf2-core.c drivers/media/v4l2-core/videobuf2-v4l2.c
> >
> > still, to properly be able to review it, we'll need to compile and
> > do some tests, but, as patch 2 and 3 broke compilation, we can't do
> > it :(
> >
> > So, I'll point for the things I found so far. I'll do a better review
> > on your next submission, after being able to compile all drivers, and
> > testing it with a few different devices to see how this works.
> >
> 
> Ok, I got your point. I will focus on solving the compilation problem
> at next round.

Thanks,

> And.. if possible, I will divide this patch into several
> pieces for easier review.

>From my side, no need to spend much time breaking it into pieces.
I doubt it would get any better.

> 
> >>
> >> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> >> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> >> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> >> Acked-by: Inki Dae <inki.dae@samsung.com>
> >> ---
> >>   drivers/media/v4l2-core/videobuf2-core.c     | 1933 +++-----------------------
> >>   drivers/media/v4l2-core/videobuf2-internal.h |  184 +++
> >>   drivers/media/v4l2-core/videobuf2-v4l2.c     | 1640 ++++++++++++++++++++++
> >>   include/media/videobuf2-core.h               |  157 +--
> >>   include/media/videobuf2-v4l2.h               |  116 ++
> >>   include/trace/events/v4l2.h                  |    4 +-
> >>   6 files changed, 2154 insertions(+), 1880 deletions(-)
> >>   create mode 100644 drivers/media/v4l2-core/videobuf2-internal.h
> >>
> >> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> >> index 9266d50..2cd4241 100644
> >> --- a/drivers/media/v4l2-core/videobuf2-core.c
> >> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> >> @@ -6,9 +6,6 @@
> >>    * Author: Pawel Osciak <pawel@osciak.com>
> >>    *	   Marek Szyprowski <m.szyprowski@samsung.com>
> >>    *
> >> - * The vb2_thread implementation was based on code from videobuf-dvb.c:
> >> - *	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
> >> - *
> >
> > Please keep the credits here. The entire videobuf stuff was actually
> > started with the first implementation done by Gerd.
> >
> 
> I removed the comment because videobuf2-core would not have vb2_thread,
> which is moved to videobuf2-v4l2.
> For this reason, I would like to modify this credits like:
> 
>   * Copyright (C) 2010 Samsung Electronics
>   *
>   * Author: Pawel Osciak <pawel@osciak.com>
>   *	   Marek Szyprowski <m.szyprowski@samsung.com>
>   *
>   * Copyright (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]

I would, instead, add this as:
	Based on code from videobuf-dvb.c by:
		(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]

> Is it ok? Or just leave it as it is.
> 
> 
> >>    * This program is free software; you can redistribute it and/or modify
> >>    * it under the terms of the GNU General Public License as published by
> >>    * the Free Software Foundation.
> >> @@ -24,164 +21,14 @@
> >>   #include <linux/freezer.h>
> >>   #include <linux/kthread.h>
> >>
> >> -#include <media/v4l2-dev.h>
> >> -#include <media/v4l2-fh.h>
> >> -#include <media/v4l2-event.h>
> >> -#include <media/v4l2-common.h>
> >> -#include <media/videobuf2-v4l2.h>
> >> +#include <media/videobuf2-core.h>
> >> +#include "videobuf2-internal.h"
> >>
> >>   #include <trace/events/v4l2.h>
> >>
> >> -static int debug;
> >> -module_param(debug, int, 0644);
> >> -
> >> -#define dprintk(level, fmt, arg...)					\
> >> -	do {								\
> >> -		if (debug >= level)					\
> >> -			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
> >> -	} while (0)
> >> -
> >> -#ifdef CONFIG_VIDEO_ADV_DEBUG
> >> -
> >> -/*
> >> - * If advanced debugging is on, then count how often each op is called
> >> - * successfully, which can either be per-buffer or per-queue.
> >> - *
> >> - * This makes it easy to check that the 'init' and 'cleanup'
> >> - * (and variations thereof) stay balanced.
> >> - */
> >> -
> >> -#define log_memop(vb, op)						\
> >> -	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
> >> -		(vb)->vb2_queue, (vb)->index, #op,			\
> >> -		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
> >> -
> >> -#define call_memop(vb, op, args...)					\
> >> -({									\
> >> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
> >> -	int err;							\
> >> -									\
> >> -	log_memop(vb, op);						\
> >> -	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
> >> -	if (!err)							\
> >> -		(vb)->cnt_mem_ ## op++;					\
> >> -	err;								\
> >> -})
> >> -
> >> -#define call_ptr_memop(vb, op, args...)					\
> >> -({									\
> >> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
> >> -	void *ptr;							\
> >> -									\
> >> -	log_memop(vb, op);						\
> >> -	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
> >> -	if (!IS_ERR_OR_NULL(ptr))					\
> >> -		(vb)->cnt_mem_ ## op++;					\
> >> -	ptr;								\
> >> -})
> >> -
> >> -#define call_void_memop(vb, op, args...)				\
> >> -({									\
> >> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
> >> -									\
> >> -	log_memop(vb, op);						\
> >> -	if (_q->mem_ops->op)						\
> >> -		_q->mem_ops->op(args);					\
> >> -	(vb)->cnt_mem_ ## op++;						\
> >> -})
> >> -
> >> -#define log_qop(q, op)							\
> >> -	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
> >> -		(q)->ops->op ? "" : " (nop)")
> >> -
> >> -#define call_qop(q, op, args...)					\
> >> -({									\
> >> -	int err;							\
> >> -									\
> >> -	log_qop(q, op);							\
> >> -	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
> >> -	if (!err)							\
> >> -		(q)->cnt_ ## op++;					\
> >> -	err;								\
> >> -})
> >> -
> >> -#define call_void_qop(q, op, args...)					\
> >> -({									\
> >> -	log_qop(q, op);							\
> >> -	if ((q)->ops->op)						\
> >> -		(q)->ops->op(args);					\
> >> -	(q)->cnt_ ## op++;						\
> >> -})
> >> -
> >> -#define log_vb_qop(vb, op, args...)					\
> >> -	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
> >> -		(vb)->vb2_queue, (vb)->index, #op,			\
> >> -		(vb)->vb2_queue->ops->op ? "" : " (nop)")
> >> -
> >> -#define call_vb_qop(vb, op, args...)					\
> >> -({									\
> >> -	int err;							\
> >> -									\
> >> -	log_vb_qop(vb, op);						\
> >> -	err = (vb)->vb2_queue->ops->op ?				\
> >> -		(vb)->vb2_queue->ops->op(args) : 0;			\
> >> -	if (!err)							\
> >> -		(vb)->cnt_ ## op++;					\
> >> -	err;								\
> >> -})
> >> -
> >> -#define call_void_vb_qop(vb, op, args...)				\
> >> -({									\
> >> -	log_vb_qop(vb, op);						\
> >> -	if ((vb)->vb2_queue->ops->op)					\
> >> -		(vb)->vb2_queue->ops->op(args);				\
> >> -	(vb)->cnt_ ## op++;						\
> >> -})
> >> -
> >> -#else
> >> -
> >> -#define call_memop(vb, op, args...)					\
> >> -	((vb)->vb2_queue->mem_ops->op ?					\
> >> -		(vb)->vb2_queue->mem_ops->op(args) : 0)
> >> -
> >> -#define call_ptr_memop(vb, op, args...)					\
> >> -	((vb)->vb2_queue->mem_ops->op ?					\
> >> -		(vb)->vb2_queue->mem_ops->op(args) : NULL)
> >> -
> >> -#define call_void_memop(vb, op, args...)				\
> >> -	do {								\
> >> -		if ((vb)->vb2_queue->mem_ops->op)			\
> >> -			(vb)->vb2_queue->mem_ops->op(args);		\
> >> -	} while (0)
> >> -
> >> -#define call_qop(q, op, args...)					\
> >> -	((q)->ops->op ? (q)->ops->op(args) : 0)
> >> -
> >> -#define call_void_qop(q, op, args...)					\
> >> -	do {								\
> >> -		if ((q)->ops->op)					\
> >> -			(q)->ops->op(args);				\
> >> -	} while (0)
> >> -
> >> -#define call_vb_qop(vb, op, args...)					\
> >> -	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
> >> -
> >> -#define call_void_vb_qop(vb, op, args...)				\
> >> -	do {								\
> >> -		if ((vb)->vb2_queue->ops->op)				\
> >> -			(vb)->vb2_queue->ops->op(args);			\
> >> -	} while (0)
> >> -
> >> -#endif
> >> -
> >> -/* Flags that are set by the vb2 core */
> >> -#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
> >> -				 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
> >> -				 V4L2_BUF_FLAG_PREPARED | \
> >> -				 V4L2_BUF_FLAG_TIMESTAMP_MASK)
> >> -/* Output buffer flags that should be passed on to the driver */
> >> -#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
> >> -				 V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
> >> +int vb2_debug;
> >> +module_param_named(debug, vb2_debug, int, 0644);
> >> +EXPORT_SYMBOL_GPL(vb2_debug);
> >>
> >>   static void __vb2_queue_cancel(struct vb2_queue *q);
> >>   static void __enqueue_in_driver(struct vb2_buffer *vb);
> >> @@ -193,7 +40,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
> >>   {
> >>   	struct vb2_queue *q = vb->vb2_queue;
> >>   	enum dma_data_direction dma_dir =
> >> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> >> +			q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> >>   	void *mem_priv;
> >>   	int plane;
> >>
> >> @@ -249,7 +96,8 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
> >>
> >>   	for (plane = 0; plane < vb->num_planes; ++plane) {
> >>   		if (vb->planes[plane].mem_priv)
> >> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
> >> +			call_void_memop(vb, put_userptr,
> >> +					vb->planes[plane].mem_priv);
> >>   		vb->planes[plane].mem_priv = NULL;
> >>   	}
> >>   }
> >> @@ -347,7 +195,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
> >>    *
> >>    * Returns the number of buffers successfully allocated.
> >>    */
> >> -static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
> >> +static int __vb2_queue_alloc(struct vb2_queue *q, unsigned int memory,
> >>   			unsigned int num_buffers, unsigned int num_planes)
> >>   {
> >>   	unsigned int buffer;
> >> @@ -370,7 +218,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
> >>   		vb->memory = memory;
> >>
> >>   		/* Allocate video buffer memory for the MMAP type */
> >> -		if (memory == V4L2_MEMORY_MMAP) {
> >> +		if (memory == VB2_MEMORY_MMAP) {
> >
> > Ok, that answers my implicit question on patch 2/5: you're actually
> > defining a new enum for VB2.
> >
> > The right thing to do is to replace the
> > 	unsigned int			memory;
> >
> > at struct vb2_queue by the right type, in order to enforce the type.
> > The vb2_buffer comment then needs to be changed, as it currently
> > references the types defined at videodev2.h.
> >
> 
> OK, according to your comment, I will change memory field
> at struct vb2_queue and struct vb2_buffer like:
> 
> 	enum vb2_memory			memory;

Ok.

> As a member variable of vb2_queue and vb2_buffer, memory field will
> be used by only videobuf2-core. The memory field will be translated in
> videobuf2-v4l2. e.g V4L2_MEMORY_MMAP -> VB2_MEMORY_MMAP.
> Actually, translation is not needed because the real values correspond 
> with v4l2's values, and that is confirmed at vb2_queue_init().

> int vb2_queue_init(struct vb2_queue *q)
> {
> 	if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
> 		|| WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
> 		|| WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
> 		return -EINVAL;

Yes, I saw that on my review. Not sure what you'll do with the checks
when you add vb2-dvb but let's postpone it to when it happens.

> 
> 
> >>   			ret = __vb2_buf_mem_alloc(vb);
> >>   			if (ret) {
> >>   				dprintk(1, "failed allocating memory for "
> >> @@ -397,7 +245,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
> >>   	}
> >>
> >>   	__setup_lengths(q, buffer);
> >> -	if (memory == V4L2_MEMORY_MMAP)
> >> +	if (memory == VB2_MEMORY_MMAP)
> >>   		__setup_offsets(q, buffer);
> >>
> >>   	dprintk(1, "allocated %d buffers, %d plane(s) each\n",
> >> @@ -421,9 +269,9 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
> >>   			continue;
> >>
> >>   		/* Free MMAP buffers or release USERPTR buffers */
> >> -		if (q->memory == V4L2_MEMORY_MMAP)
> >> +		if (q->memory == VB2_MEMORY_MMAP)
> >>   			__vb2_buf_mem_free(vb);
> >> -		else if (q->memory == V4L2_MEMORY_DMABUF)
> >> +		else if (q->memory == VB2_MEMORY_DMABUF)
> >>   			__vb2_buf_dmabuf_put(vb);
> >>   		else
> >>   			__vb2_buf_userptr_put(vb);
> >> @@ -547,75 +395,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
> >>   }
> >>
> >>   /**
> >> - * __verify_planes_array() - verify that the planes array passed in struct
> >> - * v4l2_buffer from userspace can be safely used
> >> - */
> >> -static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >> -{
> >> -	if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
> >> -		return 0;
> >> -
> >> -	/* Is memory for copying plane information present? */
> >> -	if (NULL == b->m.planes) {
> >> -		dprintk(1, "multi-planar buffer passed but "
> >> -			   "planes array not provided\n");
> >> -		return -EINVAL;
> >> -	}
> >> -
> >> -	if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
> >> -		dprintk(1, "incorrect planes array length, "
> >> -			   "expected %d, got %d\n", vb->num_planes, b->length);
> >> -		return -EINVAL;
> >> -	}
> >> -
> >> -	return 0;
> >> -}
> >> -
> >> -/**
> >> - * __verify_length() - Verify that the bytesused value for each plane fits in
> >> - * the plane length and that the data offset doesn't exceed the bytesused value.
> >> - */
> >> -static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >> -{
> >> -	unsigned int length;
> >> -	unsigned int bytesused;
> >> -	unsigned int plane;
> >> -
> >> -	if (!V4L2_TYPE_IS_OUTPUT(b->type))
> >> -		return 0;
> >> -
> >> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> >> -		for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -			length = (b->memory == V4L2_MEMORY_USERPTR ||
> >> -				b->memory == V4L2_MEMORY_DMABUF)
> >> -				? b->m.planes[plane].length
> >> -				: vb->planes[plane].length;
> >> -			bytesused = b->m.planes[plane].bytesused
> >> -				? b->m.planes[plane].bytesused : length;
> >> -
> >> -			if (b->m.planes[plane].bytesused > length)
> >> -				return -EINVAL;
> >> -
> >> -			if (b->m.planes[plane].data_offset > 0 &&
> >> -				b->m.planes[plane].data_offset >= bytesused)
> >> -				return -EINVAL;
> >> -		}
> >> -	} else {
> >> -		length = (b->memory == V4L2_MEMORY_USERPTR)
> >> -			? b->length : vb->planes[0].length;
> >> -
> >> -		if (b->bytesused > length)
> >> -			return -EINVAL;
> >> -	}
> >> -
> >> -	return 0;
> >> -}
> >> -
> >> -/**
> >> - * __buffer_in_use() - return true if the buffer is in use and
> >> + * vb2_buffer_in_use() - return true if the buffer is in use and
> >>    * the queue cannot be freed (by the means of REQBUFS(0)) call
> >>    */
> >> -static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
> >> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
> >>   {
> >>   	unsigned int plane;
> >>   	for (plane = 0; plane < vb->num_planes; ++plane) {
> >> @@ -631,6 +414,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
> >>   	}
> >>   	return false;
> >>   }
> >> +EXPORT_SYMBOL_GPL(vb2_buffer_in_use);
> >>
> >>   /**
> >>    * __buffers_in_use() - return true if any buffers on the queue are in use and
> >> @@ -640,142 +424,26 @@ static bool __buffers_in_use(struct vb2_queue *q)
> >>   {
> >>   	unsigned int buffer;
> >>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> >> -		if (__buffer_in_use(q, q->bufs[buffer]))
> >> +		if (vb2_buffer_in_use(q, q->bufs[buffer]))
> >>   			return true;
> >>   	}
> >>   	return false;
> >>   }
> >>
> >>   /**
> >> - * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
> >> - * returned to userspace
> >> - */
> >> -static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
> >> -{
> >> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >> -	struct vb2_queue *q = vb->vb2_queue;
> >> -	unsigned int plane;
> >> -
> >> -	/* Copy back data such as timestamp, flags, etc. */
> >> -	b->index = vb->index;
> >> -	b->type = vb->type;
> >> -	b->memory = vb->memory;
> >> -	b->bytesused = 0;
> >> -
> >> -	b->flags = vbuf->flags;
> >> -	b->field = vbuf->field;
> >> -	b->timestamp = vbuf->timestamp;
> >> -	b->timecode = vbuf->timecode;
> >> -	b->sequence = vbuf->sequence;
> >> -
> >> -	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
> >> -		/*
> >> -		 * Fill in plane-related data if userspace provided an array
> >> -		 * for it. The caller has already verified memory and size.
> >> -		 */
> >> -		b->length = vb->num_planes;
> >> -		for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -			struct v4l2_plane *pdst = &b->m.planes[plane];
> >> -			struct vb2_plane *psrc = &vb->planes[plane];
> >> -
> >> -			pdst->bytesused = psrc->bytesused;
> >> -			pdst->length = psrc->length;
> >> -			if (q->memory == V4L2_MEMORY_MMAP)
> >> -				pdst->m.mem_offset = psrc->m.offset;
> >> -			else if (q->memory == V4L2_MEMORY_USERPTR)
> >> -				pdst->m.userptr = psrc->m.userptr;
> >> -			else if (q->memory == V4L2_MEMORY_DMABUF)
> >> -				pdst->m.fd = psrc->m.fd;
> >> -			pdst->data_offset = psrc->data_offset;
> >> -		}
> >> -	} else {
> >> -		/*
> >> -		 * We use length and offset in v4l2_planes array even for
> >> -		 * single-planar buffers, but userspace does not.
> >> -		 */
> >> -		b->length = vb->planes[0].length;
> >> -		b->bytesused = vb->planes[0].bytesused;
> >> -		if (q->memory == V4L2_MEMORY_MMAP)
> >> -			b->m.offset = vb->planes[0].m.offset;
> >> -		else if (q->memory == V4L2_MEMORY_USERPTR)
> >> -			b->m.userptr = vb->planes[0].m.userptr;
> >> -		else if (q->memory == V4L2_MEMORY_DMABUF)
> >> -			b->m.fd = vb->planes[0].m.fd;
> >> -	}
> >> -
> >> -	/*
> >> -	 * Clear any buffer state related flags.
> >> -	 */
> >> -	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
> >> -	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
> >> -	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> >> -			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> >> -		/*
> >> -		 * For non-COPY timestamps, drop timestamp source bits
> >> -		 * and obtain the timestamp source from the queue.
> >> -		 */
> >> -		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> >> -		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> >> -	}
> >> -
> >> -	switch (vb->state) {
> >> -	case VB2_BUF_STATE_QUEUED:
> >> -	case VB2_BUF_STATE_ACTIVE:
> >> -		b->flags |= V4L2_BUF_FLAG_QUEUED;
> >> -		break;
> >> -	case VB2_BUF_STATE_ERROR:
> >> -		b->flags |= V4L2_BUF_FLAG_ERROR;
> >> -		/* fall through */
> >> -	case VB2_BUF_STATE_DONE:
> >> -		b->flags |= V4L2_BUF_FLAG_DONE;
> >> -		break;
> >> -	case VB2_BUF_STATE_PREPARED:
> >> -		b->flags |= V4L2_BUF_FLAG_PREPARED;
> >> -		break;
> >> -	case VB2_BUF_STATE_PREPARING:
> >> -	case VB2_BUF_STATE_DEQUEUED:
> >> -		/* nothing */
> >> -		break;
> >> -	}
> >> -
> >> -	if (__buffer_in_use(q, vb))
> >> -		b->flags |= V4L2_BUF_FLAG_MAPPED;
> >> -}
> >> -
> >> -/**
> >> - * vb2_querybuf() - query video buffer information
> >> + * vb2_core_querybuf() - query video buffer information
> >>    * @q:		videobuf queue
> >> + * @index:	id number of the buffer
> >>    * @b:		buffer struct passed from userspace to vidioc_querybuf handler
> >>    *		in driver
> >> - *
> >> - * Should be called from vidioc_querybuf ioctl handler in driver.
> >> - * This function will verify the passed v4l2_buffer structure and fill the
> >> - * relevant information for the userspace.
> >> - *
> >> - * The return values from this function are intended to be directly returned
> >> - * from vidioc_querybuf handler in driver.
> >>    */
> >> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
> >>   {
> >> -	struct vb2_buffer *vb;
> >> -	int ret;
> >> -
> >> -	if (b->type != q->type) {
> >> -		dprintk(1, "wrong buffer type\n");
> >> -		return -EINVAL;
> >> -	}
> >> +	call_bufop(q, fill_user_buffer, q->bufs[index], pb);
> >>
> >> -	if (b->index >= q->num_buffers) {
> >> -		dprintk(1, "buffer index out of range\n");
> >> -		return -EINVAL;
> >> -	}
> >> -	vb = q->bufs[b->index];
> >> -	ret = __verify_planes_array(vb, b);
> >> -	if (!ret)
> >> -		__fill_v4l2_buffer(vb, b);
> >> -	return ret;
> >> +	return 0;
> >>   }
> >> -EXPORT_SYMBOL(vb2_querybuf);
> >> +EXPORT_SYMBOL_GPL(vb2_core_querybuf);
> >>
> >>   /**
> >>    * __verify_userptr_ops() - verify that all memory operations required for
> >> @@ -818,14 +486,14 @@ static int __verify_dmabuf_ops(struct vb2_queue *q)
> >>   }
> >>
> >>   /**
> >> - * __verify_memory_type() - Check whether the memory type and buffer type
> >> + * vb2_verify_memory_type() - Check whether the memory type and buffer type
> >>    * passed to a buffer operation are compatible with the queue.
> >>    */
> >> -static int __verify_memory_type(struct vb2_queue *q,
> >> -		enum v4l2_memory memory, enum v4l2_buf_type type)
> >> +int vb2_verify_memory_type(struct vb2_queue *q,
> >> +		unsigned int memory, unsigned int type)
> >>   {
> >> -	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
> >> -			memory != V4L2_MEMORY_DMABUF) {
> >> +	if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
> >> +		memory != VB2_MEMORY_DMABUF) {
> >>   		dprintk(1, "unsupported memory type\n");
> >>   		return -EINVAL;
> >>   	}
> >> @@ -839,37 +507,30 @@ static int __verify_memory_type(struct vb2_queue *q,
> >>   	 * Make sure all the required memory ops for given memory type
> >>   	 * are available.
> >>   	 */
> >> -	if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
> >> +	if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
> >>   		dprintk(1, "MMAP for current setup unsupported\n");
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
> >> +	if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
> >>   		dprintk(1, "USERPTR for current setup unsupported\n");
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
> >> +	if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
> >>   		dprintk(1, "DMABUF for current setup unsupported\n");
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	/*
> >> -	 * Place the busy tests at the end: -EBUSY can be ignored when
> >> -	 * create_bufs is called with count == 0, but count == 0 should still
> >> -	 * do the memory and type validation.
> >> -	 */
> >> -	if (vb2_fileio_is_active(q)) {
> >> -		dprintk(1, "file io in progress\n");
> >> -		return -EBUSY;
> >> -	}
> >>   	return 0;
> >>   }
> >> +EXPORT_SYMBOL_GPL(vb2_verify_memory_type);
> >>
> >>   /**
> >> - * __reqbufs() - Initiate streaming
> >> + * vb2_core_reqbufs() - Initiate streaming
> >>    * @q:		videobuf2 queue
> >> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
> >> + * @memory:
> >> + * @count:
> >>    *
> >>    * Should be called from vidioc_reqbufs ioctl handler of a driver.
> >>    * This function:
> >> @@ -889,7 +550,8 @@ static int __verify_memory_type(struct vb2_queue *q,
> >>    * The return values from this function are intended to be directly returned
> >>    * from vidioc_reqbufs handler in driver.
> >>    */
> >> -static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> >> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
> >> +		unsigned int *count)
> >>   {
> >>   	unsigned int num_buffers, allocated_buffers, num_planes = 0;
> >>   	int ret;
> >> @@ -899,13 +561,13 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> >>   		return -EBUSY;
> >>   	}
> >>
> >> -	if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
> >> +	if (*count == 0 || q->num_buffers != 0 || q->memory != memory) {
> >>   		/*
> >>   		 * We already have buffers allocated, so first check if they
> >>   		 * are not in use and can be freed.
> >>   		 */
> >>   		mutex_lock(&q->mmap_lock);
> >> -		if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) {
> >> +		if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
> >>   			mutex_unlock(&q->mmap_lock);
> >>   			dprintk(1, "memory in use, cannot free\n");
> >>   			return -EBUSY;
> >> @@ -926,18 +588,18 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> >>   		 * In case of REQBUFS(0) return immediately without calling
> >>   		 * driver's queue_setup() callback and allocating resources.
> >>   		 */
> >> -		if (req->count == 0)
> >> +		if (*count == 0)
> >>   			return 0;
> >>   	}
> >>
> >>   	/*
> >>   	 * Make sure the requested values and current defaults are sane.
> >>   	 */
> >> -	num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
> >> +	num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME);
> >>   	num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed);
> >>   	memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
> >>   	memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
> >> -	q->memory = req->memory;
> >> +	q->memory = memory;
> >>
> >>   	/*
> >>   	 * Ask the driver how many buffers and planes per buffer it requires.
> >> @@ -949,7 +611,8 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> >>   		return ret;
> >>
> >>   	/* Finally, allocate buffers and video memory */
> >> -	allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
> >> +	allocated_buffers =
> >> +		__vb2_queue_alloc(q, memory, num_buffers, num_planes);
> >>   	if (allocated_buffers == 0) {
> >>   		dprintk(1, "memory allocation failed\n");
> >>   		return -ENOMEM;
> >> @@ -998,28 +661,15 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> >>   	 * Return the number of successfully allocated buffers
> >>   	 * to the userspace.
> >>   	 */
> >> -	req->count = allocated_buffers;
> >> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
> >> +	*count = allocated_buffers;
> >> +	q->waiting_for_buffers = !q->is_output;
> >>
> >>   	return 0;
> >>   }
> >> +EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
> >>
> >>   /**
> >> - * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and
> >> - * type values.
> >> - * @q:		videobuf2 queue
> >> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
> >> - */
> >> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> >> -{
> >> -	int ret = __verify_memory_type(q, req->memory, req->type);
> >> -
> >> -	return ret ? ret : __reqbufs(q, req);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_reqbufs);
> >> -
> >> -/**
> >> - * __create_bufs() - Allocate buffers and any required auxiliary structs
> >> + * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs
> >>    * @q:		videobuf2 queue
> >>    * @create:	creation parameters, passed from userspace to vidioc_create_bufs
> >>    *		handler in driver
> >> @@ -1033,12 +683,13 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs);
> >>    * The return values from this function are intended to be directly returned
> >>    * from vidioc_create_bufs handler in driver.
> >>    */
> >> -static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
> >> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
> >> +		unsigned int *count, void *parg)
> >>   {
> >>   	unsigned int num_planes = 0, num_buffers, allocated_buffers;
> >>   	int ret;
> >>
> >> -	if (q->num_buffers == VIDEO_MAX_FRAME) {
> >> +	if (q->num_buffers == VB2_MAX_FRAME) {
> >>   		dprintk(1, "maximum number of buffers already allocated\n");
> >>   		return -ENOBUFS;
> >>   	}
> >> @@ -1046,23 +697,23 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
> >>   	if (!q->num_buffers) {
> >>   		memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
> >>   		memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
> >> -		q->memory = create->memory;
> >> -		q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
> >> +		q->memory = memory;
> >> +		q->waiting_for_buffers = !q->is_output;
> >>   	}
> >>
> >> -	num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
> >> +	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
> >>
> >>   	/*
> >>   	 * Ask the driver, whether the requested number of buffers, planes per
> >>   	 * buffer and their sizes are acceptable
> >>   	 */
> >> -	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> >> +	ret = call_qop(q, queue_setup, q, parg, &num_buffers,
> >>   			&num_planes, q->plane_sizes, q->alloc_ctx);
> >>   	if (ret)
> >>   		return ret;
> >>
> >>   	/* Finally, allocate buffers and video memory */
> >> -	allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers,
> >> +	allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
> >>   				num_planes);
> >>   	if (allocated_buffers == 0) {
> >>   		dprintk(1, "memory allocation failed\n");
> >> @@ -1079,7 +730,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
> >>   		 * q->num_buffers contains the total number of buffers, that the
> >>   		 * queue driver has set up
> >>   		 */
> >> -		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> >> +		ret = call_qop(q, queue_setup, q, parg, &num_buffers,
> >>   				&num_planes, q->plane_sizes, q->alloc_ctx);
> >>
> >>   		if (!ret && allocated_buffers < num_buffers)
> >> @@ -1109,28 +760,11 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
> >>   	 * Return the number of successfully allocated buffers
> >>   	 * to the userspace.
> >>   	 */
> >> -	create->count = allocated_buffers;
> >> +	*count = allocated_buffers;
> >>
> >>   	return 0;
> >>   }
> >> -
> >> -/**
> >> - * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the
> >> - * memory and type values.
> >> - * @q:		videobuf2 queue
> >> - * @create:	creation parameters, passed from userspace to vidioc_create_bufs
> >> - *		handler in driver
> >> - */
> >> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
> >> -{
> >> -	int ret = __verify_memory_type(q, create->memory, create->format.type);
> >> -
> >> -	create->index = q->num_buffers;
> >> -	if (create->count == 0)
> >> -		return ret != -EBUSY ? ret : 0;
> >> -	return ret ? ret : __create_bufs(q, create);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_create_bufs);
> >> +EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
> >>
> >>   /**
> >>    * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
> >> @@ -1263,7 +897,7 @@ void vb2_discard_done(struct vb2_queue *q)
> >>   }
> >>   EXPORT_SYMBOL_GPL(vb2_discard_done);
> >>
> >> -static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
> >> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
> >>   {
> >>   	static bool __check_once __read_mostly;
> >>
> >> @@ -1279,162 +913,34 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
> >>   	else
> >>   		pr_warn_once("use the actual size instead.\n");
> >>   }
> >> -
> >> -/**
> >> - * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
> >> - * v4l2_buffer by the userspace. The caller has already verified that struct
> >> - * v4l2_buffer has a valid number of planes.
> >> - */
> >> -static void __fill_vb2_buffer(struct vb2_buffer *vb,
> >> -		const struct v4l2_buffer *b, struct vb2_plane *planes)
> >> -{
> >> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >> -	unsigned int plane;
> >> -
> >> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> >> -		if (b->memory == V4L2_MEMORY_USERPTR) {
> >> -			for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -				planes[plane].m.userptr =
> >> -					b->m.planes[plane].m.userptr;
> >> -				planes[plane].length =
> >> -					b->m.planes[plane].length;
> >> -			}
> >> -		}
> >> -		if (b->memory == V4L2_MEMORY_DMABUF) {
> >> -			for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -				planes[plane].m.fd =
> >> -					b->m.planes[plane].m.fd;
> >> -				planes[plane].length =
> >> -					b->m.planes[plane].length;
> >> -			}
> >> -		}
> >> -
> >> -		/* Fill in driver-provided information for OUTPUT types */
> >> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> -			/*
> >> -			 * Will have to go up to b->length when API starts
> >> -			 * accepting variable number of planes.
> >> -			 *
> >> -			 * If bytesused == 0 for the output buffer, then fall
> >> -			 * back to the full buffer size. In that case
> >> -			 * userspace clearly never bothered to set it and
> >> -			 * it's a safe assumption that they really meant to
> >> -			 * use the full plane sizes.
> >> -			 *
> >> -			 * Some drivers, e.g. old codec drivers, use bytesused == 0
> >> -			 * as a way to indicate that streaming is finished.
> >> -			 * In that case, the driver should use the
> >> -			 * allow_zero_bytesused flag to keep old userspace
> >> -			 * applications working.
> >> -			 */
> >> -			for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -				struct vb2_plane *pdst = &planes[plane];
> >> -				struct v4l2_plane *psrc = &b->m.planes[plane];
> >> -
> >> -				if (psrc->bytesused == 0)
> >> -					vb2_warn_zero_bytesused(vb);
> >> -
> >> -				if (vb->vb2_queue->allow_zero_bytesused)
> >> -					pdst->bytesused = psrc->bytesused;
> >> -				else
> >> -					pdst->bytesused = psrc->bytesused ?
> >> -						psrc->bytesused : pdst->length;
> >> -				pdst->data_offset = psrc->data_offset;
> >> -			}
> >> -		}
> >> -	} else {
> >> -		/*
> >> -		 * Single-planar buffers do not use planes array,
> >> -		 * so fill in relevant v4l2_buffer struct fields instead.
> >> -		 * In videobuf we use our internal V4l2_planes struct for
> >> -		 * single-planar buffers as well, for simplicity.
> >> -		 *
> >> -		 * If bytesused == 0 for the output buffer, then fall back
> >> -		 * to the full buffer size as that's a sensible default.
> >> -		 *
> >> -		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
> >> -		 * a way to indicate that streaming is finished. In that case,
> >> -		 * the driver should use the allow_zero_bytesused flag to keep
> >> -		 * old userspace applications working.
> >> -		 */
> >> -		if (b->memory == V4L2_MEMORY_USERPTR) {
> >> -			planes[0].m.userptr = b->m.userptr;
> >> -			planes[0].length = b->length;
> >> -		}
> >> -
> >> -		if (b->memory == V4L2_MEMORY_DMABUF) {
> >> -			planes[0].m.fd = b->m.fd;
> >> -			planes[0].length = b->length;
> >> -		}
> >> -
> >> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> -			if (b->bytesused == 0)
> >> -				vb2_warn_zero_bytesused(vb);
> >> -
> >> -			if (vb->vb2_queue->allow_zero_bytesused)
> >> -				planes[0].bytesused = b->bytesused;
> >> -			else
> >> -				planes[0].bytesused = b->bytesused ?
> >> -					b->bytesused : planes[0].length;
> >> -		} else
> >> -			planes[0].bytesused = 0;
> >> -
> >> -	}
> >> -
> >> -	/* Zero flags that the vb2 core handles */
> >> -	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> >> -	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> >> -			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
> >> -			!V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> -		/*
> >> -		 * Non-COPY timestamps and non-OUTPUT queues will get
> >> -		 * their timestamp and timestamp source flags from the
> >> -		 * queue.
> >> -		 */
> >> -		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> >> -	}
> >> -
> >> -	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> -		/*
> >> -		 * For output buffers mask out the timecode flag:
> >> -		 * this will be handled later in vb2_internal_qbuf().
> >> -		 * The 'field' is valid metadata for this output buffer
> >> -		 * and so that needs to be copied here.
> >> -		 */
> >> -		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
> >> -		vbuf->field = b->field;
> >> -	} else {
> >> -		/* Zero any output buffer flags as this is a capture buffer */
> >> -		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
> >> -	}
> >> -}
> >> +EXPORT_SYMBOL_GPL(vb2_warn_zero_bytesused);
> >>
> >>   /**
> >>    * __qbuf_mmap() - handle qbuf of an MMAP buffer
> >>    */
> >> -static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >> +static int __qbuf_mmap(struct vb2_buffer *vb, void *pb)
> >>   {
> >> -	__fill_vb2_buffer(vb, b, vb->planes);
> >> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, vb->planes);
> >>   	return call_vb_qop(vb, buf_prepare, vb);
> >>   }
> >>
> >>   /**
> >>    * __qbuf_userptr() - handle qbuf of a USERPTR buffer
> >>    */
> >> -static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >> +static int __qbuf_userptr(struct vb2_buffer *vb, void *pb)
> >>   {
> >> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
> >> +	struct vb2_plane planes[VB2_MAX_PLANES];
> >>   	struct vb2_queue *q = vb->vb2_queue;
> >>   	void *mem_priv;
> >>   	unsigned int plane;
> >>   	int ret;
> >>   	enum dma_data_direction dma_dir =
> >> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> >> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> >>   	bool reacquired = vb->planes[0].mem_priv == NULL;
> >>
> >>   	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
> >>   	/* Copy relevant information provided by the userspace */
> >> -	__fill_vb2_buffer(vb, b, planes);
> >> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
> >>
> >>   	for (plane = 0; plane < vb->num_planes; ++plane) {
> >>   		/* Skip the plane if already verified */
> >> @@ -1462,7 +968,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   				reacquired = true;
> >>   				call_void_vb_qop(vb, buf_cleanup, vb);
> >>   			}
> >> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
> >> +			call_void_memop(vb, put_userptr,
> >> +					vb->planes[plane].mem_priv);
> >>   		}
> >>
> >>   		vb->planes[plane].mem_priv = NULL;
> >> @@ -1533,20 +1040,20 @@ err:
> >>   /**
> >>    * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
> >>    */
> >> -static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >> +static int __qbuf_dmabuf(struct vb2_buffer *vb, void *pb)
> >>   {
> >> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
> >> +	struct vb2_plane planes[VB2_MAX_PLANES];
> >>   	struct vb2_queue *q = vb->vb2_queue;
> >>   	void *mem_priv;
> >>   	unsigned int plane;
> >>   	int ret;
> >>   	enum dma_data_direction dma_dir =
> >> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> >> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> >>   	bool reacquired = vb->planes[0].mem_priv == NULL;
> >>
> >>   	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
> >>   	/* Copy relevant information provided by the userspace */
> >> -	__fill_vb2_buffer(vb, b, planes);
> >> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
> >>
> >>   	for (plane = 0; plane < vb->num_planes; ++plane) {
> >>   		struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
> >> @@ -1591,9 +1098,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   		vb->planes[plane].data_offset = 0;
> >>
> >>   		/* Acquire each plane's memory */
> >> -		mem_priv = call_ptr_memop(vb, attach_dmabuf,
> >> -			q->alloc_ctx[plane], dbuf, planes[plane].length,
> >> -			dma_dir);
> >> +		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
> >> +			dbuf, planes[plane].length, dma_dir);
> >>   		if (IS_ERR(mem_priv)) {
> >>   			dprintk(1, "failed to attach dmabuf\n");
> >>   			ret = PTR_ERR(mem_priv);
> >> @@ -1626,7 +1132,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   	for (plane = 0; plane < vb->num_planes; ++plane) {
> >>   		vb->planes[plane].bytesused = planes[plane].bytesused;
> >>   		vb->planes[plane].length = planes[plane].length;
> >> -		vb->planes[plane].m.fd = planes[plane].m.userptr;
> >> +		vb->planes[plane].m.fd = planes[plane].m.fd;
> >>   		vb->planes[plane].data_offset = planes[plane].data_offset;
> >>   	}
> >>
> >> @@ -1677,52 +1183,27 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
> >>   	call_void_vb_qop(vb, buf_queue, vb);
> >>   }
> >>
> >> -static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >> +static int __buf_prepare(struct vb2_buffer *vb, void *pb)
> >>   {
> >> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >>   	struct vb2_queue *q = vb->vb2_queue;
> >>   	int ret;
> >>
> >> -	ret = __verify_length(vb, b);
> >> -	if (ret < 0) {
> >> -		dprintk(1, "plane parameters verification failed: %d\n", ret);
> >> -		return ret;
> >> -	}
> >> -	if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) {
> >> -		/*
> >> -		 * If the format's field is ALTERNATE, then the buffer's field
> >> -		 * should be either TOP or BOTTOM, not ALTERNATE since that
> >> -		 * makes no sense. The driver has to know whether the
> >> -		 * buffer represents a top or a bottom field in order to
> >> -		 * program any DMA correctly. Using ALTERNATE is wrong, since
> >> -		 * that just says that it is either a top or a bottom field,
> >> -		 * but not which of the two it is.
> >> -		 */
> >> -		dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
> >> -		return -EINVAL;
> >> -	}
> >> -
> >>   	if (q->error) {
> >>   		dprintk(1, "fatal error occurred on queue\n");
> >>   		return -EIO;
> >>   	}
> >>
> >> -	vb->state = VB2_BUF_STATE_PREPARING;
> >> -	vbuf->timestamp.tv_sec = 0;
> >> -	vbuf->timestamp.tv_usec = 0;
> >> -	vbuf->sequence = 0;
> >> -
> >>   	switch (q->memory) {
> >> -	case V4L2_MEMORY_MMAP:
> >> -		ret = __qbuf_mmap(vb, b);
> >> +	case VB2_MEMORY_MMAP:
> >> +		ret = __qbuf_mmap(vb, pb);
> >>   		break;
> >> -	case V4L2_MEMORY_USERPTR:
> >> +	case VB2_MEMORY_USERPTR:
> >>   		down_read(&current->mm->mmap_sem);
> >> -		ret = __qbuf_userptr(vb, b);
> >> +		ret = __qbuf_userptr(vb, pb);
> >>   		up_read(&current->mm->mmap_sem);
> >>   		break;
> >> -	case V4L2_MEMORY_DMABUF:
> >> -		ret = __qbuf_dmabuf(vb, b);
> >> +	case VB2_MEMORY_DMABUF:
> >> +		ret = __qbuf_dmabuf(vb, pb);
> >>   		break;
> >>   	default:
> >>   		WARN(1, "Invalid queue type\n");
> >> @@ -1736,35 +1217,56 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   	return ret;
> >>   }
> >>
> >> -static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
> >> -					const char *opname)
> >> +int vb2_verify_buffer(struct vb2_queue *q,
> >> +			unsigned int memory, unsigned int type,
> >> +			unsigned int index, unsigned int nplanes,
> >> +			void *pplane, const char *opname)
> >>   {
> >> -	if (b->type != q->type) {
> >> +	if (type != q->type) {
> >>   		dprintk(1, "%s: invalid buffer type\n", opname);
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	if (b->index >= q->num_buffers) {
> >> +	if (index >= q->num_buffers) {
> >>   		dprintk(1, "%s: buffer index out of range\n", opname);
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	if (q->bufs[b->index] == NULL) {
> >> +	if (q->bufs[index] == NULL) {
> >>   		/* Should never happen */
> >>   		dprintk(1, "%s: buffer is NULL\n", opname);
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	if (b->memory != q->memory) {
> >> +	if (memory != VB2_MEMORY_UNKNOWN && memory != q->memory) {
> >>   		dprintk(1, "%s: invalid memory type\n", opname);
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	return __verify_planes_array(q->bufs[b->index], b);
> >> +	if (q->is_multiplanar) {
> >> +		struct vb2_buffer *vb = q->bufs[index];
> >> +
> >> +		/* Is memory for copying plane information present? */
> >> +		if (NULL == pplane) {
> >> +			dprintk(1, "%s: multi-planar buffer passed but "
> >> +				"planes array not provided\n", opname);
> >> +			return -EINVAL;
> >> +		}
> >> +
> >> +		if (nplanes < vb->num_planes || nplanes > VB2_MAX_PLANES) {
> >> +			dprintk(1, "%s: incorrect planes array length, "
> >> +				"expected %d, got %d\n",
> >> +				opname, vb->num_planes, nplanes);
> >> +			return -EINVAL;
> >> +		}
> >> +	}
> >> +
> >> +	return 0;
> >>   }
> >> +EXPORT_SYMBOL_GPL(vb2_verify_buffer);
> >>
> >>   /**
> >> - * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
> >> + * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
> >>    * @q:		videobuf2 queue
> >>    * @b:		buffer structure passed from userspace to vidioc_prepare_buf
> >>    *		handler in driver
> >> @@ -1778,37 +1280,28 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
> >>    * The return values from this function are intended to be directly returned
> >>    * from vidioc_prepare_buf handler in driver.
> >>    */
> >> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
> >> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
> >>   {
> >>   	struct vb2_buffer *vb;
> >>   	int ret;
> >>
> >> -	if (vb2_fileio_is_active(q)) {
> >> -		dprintk(1, "file io in progress\n");
> >> -		return -EBUSY;
> >> -	}
> >> -
> >> -	ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
> >> -	if (ret)
> >> -		return ret;
> >> -
> >> -	vb = q->bufs[b->index];
> >> +	vb = q->bufs[index];
> >>   	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
> >>   		dprintk(1, "invalid buffer state %d\n",
> >>   			vb->state);
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	ret = __buf_prepare(vb, b);
> >> +	ret = __buf_prepare(vb, pb);
> >>   	if (!ret) {
> >>   		/* Fill buffer information for the userspace */
> >> -		__fill_v4l2_buffer(vb, b);
> >> +		call_bufop(q, fill_user_buffer, vb, pb);
> >>
> >>   		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
> >>   	}
> >>   	return ret;
> >>   }
> >> -EXPORT_SYMBOL_GPL(vb2_prepare_buf);
> >> +EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
> >>
> >>   /**
> >>    * vb2_start_streaming() - Attempt to start streaming.
> >> @@ -1873,21 +1366,16 @@ static int vb2_start_streaming(struct vb2_queue *q)
> >>   	return ret;
> >>   }
> >>
> >> -static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
> >>   {
> >> -	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
> >> +	int ret;
> >>   	struct vb2_buffer *vb;
> >> -	struct vb2_v4l2_buffer *vbuf;
> >> -
> >> -	if (ret)
> >> -		return ret;
> >>
> >> -	vb = q->bufs[b->index];
> >> -	vbuf = to_vb2_v4l2_buffer(vb);
> >> +	vb = q->bufs[index];
> >>
> >>   	switch (vb->state) {
> >>   	case VB2_BUF_STATE_DEQUEUED:
> >> -		ret = __buf_prepare(vb, b);
> >> +		ret = __buf_prepare(vb, pb);
> >>   		if (ret)
> >>   			return ret;
> >>   		break;
> >> @@ -1909,18 +1397,9 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >>   	q->queued_count++;
> >>   	q->waiting_for_buffers = false;
> >>   	vb->state = VB2_BUF_STATE_QUEUED;
> >> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
> >> -		/*
> >> -		 * For output buffers copy the timestamp if needed,
> >> -		 * and the timecode field and flag if needed.
> >> -		 */
> >> -		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> >> -				V4L2_BUF_FLAG_TIMESTAMP_COPY)
> >> -			vbuf->timestamp = b->timestamp;
> >> -		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> >> -		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> >> -			vbuf->timecode = b->timecode;
> >> -	}
> >> +
> >> +	if (q->is_output)
> >> +		call_bufop(q, fill_vb2_timestamp, vb, pb);
> >>
> >>   	trace_vb2_qbuf(q, vb);
> >>
> >> @@ -1932,7 +1411,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >>   		__enqueue_in_driver(vb);
> >>
> >>   	/* Fill buffer information for the userspace */
> >> -	__fill_v4l2_buffer(vb, b);
> >> +	call_bufop(q, fill_user_buffer, vb, pb);
> >>
> >>   	/*
> >>   	 * If streamon has been called, and we haven't yet called
> >> @@ -1950,34 +1429,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >>   	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
> >>   	return 0;
> >>   }
> >> -
> >> -/**
> >> - * vb2_qbuf() - Queue a buffer from userspace
> >> - * @q:		videobuf2 queue
> >> - * @b:		buffer structure passed from userspace to vidioc_qbuf handler
> >> - *		in driver
> >> - *
> >> - * Should be called from vidioc_qbuf ioctl handler of a driver.
> >> - * This function:
> >> - * 1) verifies the passed buffer,
> >> - * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
> >> - *    which driver-specific buffer initialization can be performed,
> >> - * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
> >> - *    callback for processing.
> >> - *
> >> - * The return values from this function are intended to be directly returned
> >> - * from vidioc_qbuf handler in driver.
> >> - */
> >> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >> -{
> >> -	if (vb2_fileio_is_active(q)) {
> >> -		dprintk(1, "file io in progress\n");
> >> -		return -EBUSY;
> >> -	}
> >> -
> >> -	return vb2_internal_qbuf(q, b);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_qbuf);
> >> +EXPORT_SYMBOL_GPL(vb2_core_qbuf);
> >>
> >>   /**
> >>    * __vb2_wait_for_done_vb() - wait for a buffer to become available
> >> @@ -2061,7 +1513,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
> >>    * Will sleep if required for nonblocking == false.
> >>    */
> >>   static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
> >> -				struct v4l2_buffer *b, int nonblocking)
> >> +				int nonblocking)
> >>   {
> >>   	unsigned long flags;
> >>   	int ret;
> >> @@ -2082,10 +1534,11 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
> >>   	/*
> >>   	 * Only remove the buffer from done_list if v4l2_buffer can handle all
> >>   	 * the planes.
> >> +	 * ret = __verify_planes_array(*vb, pb);
> >> +	 * But, actually that's unnecessary since this is checked already
> >> +	 * before the buffer is queued/prepared. So it can never fails
> >>   	 */
> >> -	ret = __verify_planes_array(*vb, b);
> >> -	if (!ret)
> >> -		list_del(&(*vb)->done_entry);
> >> +	list_del(&(*vb)->done_entry);
> >>   	spin_unlock_irqrestore(&q->done_lock, flags);
> >>
> >>   	return ret;
> >> @@ -2128,27 +1581,22 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
> >>   	vb->state = VB2_BUF_STATE_DEQUEUED;
> >>
> >>   	/* unmap DMABUF buffer */
> >> -	if (q->memory == V4L2_MEMORY_DMABUF)
> >> +	if (q->memory == VB2_MEMORY_DMABUF)
> >>   		for (i = 0; i < vb->num_planes; ++i) {
> >>   			if (!vb->planes[i].dbuf_mapped)
> >>   				continue;
> >> -			call_void_memop(vb, unmap_dmabuf, vb->planes[i].mem_priv);
> >> +			call_void_memop(vb, unmap_dmabuf,
> >> +					vb->planes[i].mem_priv);
> >>   			vb->planes[i].dbuf_mapped = 0;
> >>   		}
> >>   }
> >>
> >> -static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> >> -		bool nonblocking)
> >> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
> >>   {
> >>   	struct vb2_buffer *vb = NULL;
> >> -	struct vb2_v4l2_buffer *vbuf = NULL;
> >>   	int ret;
> >>
> >> -	if (b->type != q->type) {
> >> -		dprintk(1, "invalid buffer type\n");
> >> -		return -EINVAL;
> >> -	}
> >> -	ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
> >> +	ret = __vb2_get_done_vb(q, &vb, nonblocking);
> >>   	if (ret < 0)
> >>   		return ret;
> >>
> >> @@ -2167,16 +1615,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> >>   	call_void_vb_qop(vb, buf_finish, vb);
> >>
> >>   	/* Fill buffer information for the userspace */
> >> -	__fill_v4l2_buffer(vb, b);
> >> +	call_bufop(q, fill_user_buffer, vb, pb);
> >>   	/* Remove from videobuf queue */
> >>   	list_del(&vb->queued_entry);
> >>   	q->queued_count--;
> >>
> >>   	trace_vb2_dqbuf(q, vb);
> >>
> >> -	vbuf = to_vb2_v4l2_buffer(vb);
> >> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
> >> -			vbuf->flags & V4L2_BUF_FLAG_LAST)
> >> +	if (!q->is_output &&
> >> +			call_bufop(q, is_last, vb))
> >>   		q->last_buffer_dequeued = true;
> >>   	/* go back to dequeued state */
> >>   	__vb2_dqbuf(vb);
> >> @@ -2186,37 +1633,7 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> >>
> >>   	return 0;
> >>   }
> >> -
> >> -/**
> >> - * vb2_dqbuf() - Dequeue a buffer to the userspace
> >> - * @q:		videobuf2 queue
> >> - * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
> >> - *		in driver
> >> - * @nonblocking: if true, this call will not sleep waiting for a buffer if no
> >> - *		 buffers ready for dequeuing are present. Normally the driver
> >> - *		 would be passing (file->f_flags & O_NONBLOCK) here
> >> - *
> >> - * Should be called from vidioc_dqbuf ioctl handler of a driver.
> >> - * This function:
> >> - * 1) verifies the passed buffer,
> >> - * 2) calls buf_finish callback in the driver (if provided), in which
> >> - *    driver can perform any additional operations that may be required before
> >> - *    returning the buffer to userspace, such as cache sync,
> >> - * 3) the buffer struct members are filled with relevant information for
> >> - *    the userspace.
> >> - *
> >> - * The return values from this function are intended to be directly returned
> >> - * from vidioc_dqbuf handler in driver.
> >> - */
> >> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
> >> -{
> >> -	if (vb2_fileio_is_active(q)) {
> >> -		dprintk(1, "file io in progress\n");
> >> -		return -EBUSY;
> >> -	}
> >> -	return vb2_internal_dqbuf(q, b, nonblocking);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_dqbuf);
> >> +EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
> >>
> >>   /**
> >>    * __vb2_queue_cancel() - cancel and stop (pause) streaming
> >> @@ -2286,15 +1703,10 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
> >>   	}
> >>   }
> >>
> >> -static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> >> +int vb2_core_streamon(struct vb2_queue *q)
> >>   {
> >>   	int ret;
> >>
> >> -	if (type != q->type) {
> >> -		dprintk(1, "invalid stream type\n");
> >> -		return -EINVAL;
> >> -	}
> >> -
> >>   	if (q->streaming) {
> >>   		dprintk(3, "already streaming\n");
> >>   		return 0;
> >> @@ -2328,6 +1740,7 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> >>   	dprintk(3, "successful\n");
> >>   	return 0;
> >>   }
> >> +EXPORT_SYMBOL_GPL(vb2_core_streamon);
> >>
> >>   /**
> >>    * vb2_queue_error() - signal a fatal error on the queue
> >> @@ -2350,36 +1763,8 @@ void vb2_queue_error(struct vb2_queue *q)
> >>   }
> >>   EXPORT_SYMBOL_GPL(vb2_queue_error);
> >>
> >> -/**
> >> - * vb2_streamon - start streaming
> >> - * @q:		videobuf2 queue
> >> - * @type:	type argument passed from userspace to vidioc_streamon handler
> >> - *
> >> - * Should be called from vidioc_streamon handler of a driver.
> >> - * This function:
> >> - * 1) verifies current state
> >> - * 2) passes any previously queued buffers to the driver and starts streaming
> >> - *
> >> - * The return values from this function are intended to be directly returned
> >> - * from vidioc_streamon handler in the driver.
> >> - */
> >> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> >> -{
> >> -	if (vb2_fileio_is_active(q)) {
> >> -		dprintk(1, "file io in progress\n");
> >> -		return -EBUSY;
> >> -	}
> >> -	return vb2_internal_streamon(q, type);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_streamon);
> >> -
> >> -static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> >> +int vb2_core_streamoff(struct vb2_queue *q)
> >>   {
> >> -	if (type != q->type) {
> >> -		dprintk(1, "invalid stream type\n");
> >> -		return -EINVAL;
> >> -	}
> >> -
> >>   	/*
> >>   	 * Cancel will pause streaming and remove all buffers from the driver
> >>   	 * and videobuf, effectively returning control over them to userspace.
> >> @@ -2390,37 +1775,13 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> >>   	 * their normal dequeued state.
> >>   	 */
> >>   	__vb2_queue_cancel(q);
> >> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
> >> +	q->waiting_for_buffers = !q->is_output;
> >>   	q->last_buffer_dequeued = false;
> >>
> >>   	dprintk(3, "successful\n");
> >>   	return 0;
> >>   }
> >> -
> >> -/**
> >> - * vb2_streamoff - stop streaming
> >> - * @q:		videobuf2 queue
> >> - * @type:	type argument passed from userspace to vidioc_streamoff handler
> >> - *
> >> - * Should be called from vidioc_streamoff handler of a driver.
> >> - * This function:
> >> - * 1) verifies current state,
> >> - * 2) stop streaming and dequeues any queued buffers, including those previously
> >> - *    passed to the driver (after waiting for the driver to finish).
> >> - *
> >> - * This call can be used for pausing playback.
> >> - * The return values from this function are intended to be directly returned
> >> - * from vidioc_streamoff handler in the driver
> >> - */
> >> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> >> -{
> >> -	if (vb2_fileio_is_active(q)) {
> >> -		dprintk(1, "file io in progress\n");
> >> -		return -EBUSY;
> >> -	}
> >> -	return vb2_internal_streamoff(q, type);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_streamoff);
> >> +EXPORT_SYMBOL_GPL(vb2_core_streamoff);
> >>
> >>   /**
> >>    * __find_plane_by_offset() - find plane associated with the given offset off
> >> @@ -2452,7 +1813,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
> >>   }
> >>
> >>   /**
> >> - * vb2_expbuf() - Export a buffer as a file descriptor
> >> + * vb2_core_expbuf() - Export a buffer as a file descriptor
> >>    * @q:		videobuf2 queue
> >>    * @eb:		export buffer structure passed from userspace to vidioc_expbuf
> >>    *		handler in driver
> >> @@ -2460,14 +1821,15 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
> >>    * The return values from this function are intended to be directly returned
> >>    * from vidioc_expbuf handler in driver.
> >>    */
> >> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
> >> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
> >> +		unsigned int index, unsigned int plane, unsigned int flags)
> >>   {
> >>   	struct vb2_buffer *vb = NULL;
> >>   	struct vb2_plane *vb_plane;
> >>   	int ret;
> >>   	struct dma_buf *dbuf;
> >>
> >> -	if (q->memory != V4L2_MEMORY_MMAP) {
> >> +	if (q->memory != VB2_MEMORY_MMAP) {
> >>   		dprintk(1, "queue is not currently set up for mmap\n");
> >>   		return -EINVAL;
> >>   	}
> >> @@ -2477,78 +1839,60 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
> >> +	if (flags & ~(O_CLOEXEC | O_ACCMODE)) {
> >>   		dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n");
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	if (eb->type != q->type) {
> >> +	if (type != q->type) {
> >>   		dprintk(1, "invalid buffer type\n");
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	if (eb->index >= q->num_buffers) {
> >> +	if (index >= q->num_buffers) {
> >>   		dprintk(1, "buffer index out of range\n");
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	vb = q->bufs[eb->index];
> >> +	vb = q->bufs[index];
> >>
> >> -	if (eb->plane >= vb->num_planes) {
> >> +	if (plane >= vb->num_planes) {
> >>   		dprintk(1, "buffer plane out of range\n");
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	if (vb2_fileio_is_active(q)) {
> >> -		dprintk(1, "expbuf: file io in progress\n");
> >> -		return -EBUSY;
> >> -	}
> >> +	vb_plane = &vb->planes[plane];
> >>
> >> -	vb_plane = &vb->planes[eb->plane];
> >> -
> >> -	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
> >> +	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv,
> >> +				flags & O_ACCMODE);
> >>   	if (IS_ERR_OR_NULL(dbuf)) {
> >>   		dprintk(1, "failed to export buffer %d, plane %d\n",
> >> -			eb->index, eb->plane);
> >> +			index, plane);
> >>   		return -EINVAL;
> >>   	}
> >>
> >> -	ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
> >> +	ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
> >>   	if (ret < 0) {
> >>   		dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
> >> -			eb->index, eb->plane, ret);
> >> +			index, plane, ret);
> >>   		dma_buf_put(dbuf);
> >>   		return ret;
> >>   	}
> >>
> >>   	dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
> >> -		eb->index, eb->plane, ret);
> >> -	eb->fd = ret;
> >> +		index, plane, ret);
> >> +	*fd = ret;
> >>
> >>   	return 0;
> >>   }
> >> -EXPORT_SYMBOL_GPL(vb2_expbuf);
> >> +EXPORT_SYMBOL_GPL(vb2_core_expbuf);
> >>
> >>   /**
> >> - * vb2_mmap() - map video buffers into application address space
> >> + * vb2_core_mmap() - map video buffers into application address space
> >>    * @q:		videobuf2 queue
> >>    * @vma:	vma passed to the mmap file operation handler in the driver
> >> - *
> >> - * Should be called from mmap file operation handler of a driver.
> >> - * This function maps one plane of one of the available video buffers to
> >> - * userspace. To map whole video memory allocated on reqbufs, this function
> >> - * has to be called once per each plane per each buffer previously allocated.
> >> - *
> >> - * When the userspace application calls mmap, it passes to it an offset returned
> >> - * to it earlier by the means of vidioc_querybuf handler. That offset acts as
> >> - * a "cookie", which is then used to identify the plane to be mapped.
> >> - * This function finds a plane with a matching offset and a mapping is performed
> >> - * by the means of a provided memory operation.
> >> - *
> >> - * The return values from this function are intended to be directly returned
> >> - * from the mmap handler in driver.
> >
> > Please keep some documentation here. Ok, the function is now more
> > generic, but still it deserves to be properly documented ;)
> 
> As your comment, vb2_core_* functions is more generic, but they will be
> used internally by videobuf2. So, I move these documantaion to
> videobuf2-v4l2, which is exposed to device drivers.
> Which is better? Keep these documentation at both side,
> or at vb2-core, or at vb2-v4l2.

Keep it on both sides, changing the documentation if needed.

This way, if the Kernel manpages package is installed [1]), and someone
needs to better understand this function, all it needs to do is:
	man vb2_core_mmap

[1] package linux-manual on Debian. Some other distros call it as 
linux-manpages.


> I think that "at vb2-v4l2" is the best.
> 
> >
> >>    */
> >> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> >> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> >>   {
> >>   	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
> >>   	struct vb2_buffer *vb;
> >> @@ -2556,7 +1900,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> >>   	int ret;
> >>   	unsigned long length;
> >>
> >> -	if (q->memory != V4L2_MEMORY_MMAP) {
> >> +	if (q->memory != VB2_MEMORY_MMAP) {
> >>   		dprintk(1, "queue is not currently set up for mmap\n");
> >>   		return -EINVAL;
> >>   	}
> >> @@ -2568,7 +1912,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> >>   		dprintk(1, "invalid vma flags, VM_SHARED needed\n");
> >>   		return -EINVAL;
> >>   	}
> >> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
> >> +	if (q->is_output) {
> >>   		if (!(vma->vm_flags & VM_WRITE)) {
> >>   			dprintk(1, "invalid vma flags, VM_WRITE needed\n");
> >>   			return -EINVAL;
> >> @@ -2579,10 +1923,6 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> >>   			return -EINVAL;
> >>   		}
> >>   	}
> >> -	if (vb2_fileio_is_active(q)) {
> >> -		dprintk(1, "mmap: file io in progress\n");
> >> -		return -EBUSY;
> >> -	}
> >>
> >>   	/*
> >>   	 * Find the plane corresponding to the offset passed by userspace.
> >> @@ -2614,7 +1954,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> >>   	dprintk(3, "buffer %d, plane %d successfully mapped\n", buffer, plane);
> >>   	return 0;
> >>   }
> >> -EXPORT_SYMBOL_GPL(vb2_mmap);
> >> +EXPORT_SYMBOL_GPL(vb2_core_mmap);
> >>
> >>   #ifndef CONFIG_MMU
> >>   unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
> >> @@ -2629,7 +1969,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
> >>   	void *vaddr;
> >>   	int ret;
> >>
> >> -	if (q->memory != V4L2_MEMORY_MMAP) {
> >> +	if (q->memory != VB2_MEMORY_MMAP) {
> >>   		dprintk(1, "queue is not currently set up for mmap\n");
> >>   		return -EINVAL;
> >>   	}
> >> @@ -2649,123 +1989,8 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
> >>   EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
> >>   #endif
> >>
> >> -static int __vb2_init_fileio(struct vb2_queue *q, int read);
> >> -static int __vb2_cleanup_fileio(struct vb2_queue *q);
> >> -
> >> -/**
> >> - * vb2_poll() - implements poll userspace operation
> >> - * @q:		videobuf2 queue
> >> - * @file:	file argument passed to the poll file operation handler
> >> - * @wait:	wait argument passed to the poll file operation handler
> >> - *
> >> - * This function implements poll file operation handler for a driver.
> >> - * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
> >> - * be informed that the file descriptor of a video device is available for
> >> - * reading.
> >> - * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
> >> - * will be reported as available for writing.
> >> - *
> >> - * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
> >> - * pending events.
> >> - *
> >> - * The return values from this function are intended to be directly returned
> >> - * from poll handler in driver.
> >> - */
> >> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> >> -{
> >> -	struct video_device *vfd = video_devdata(file);
> >> -	unsigned long req_events = poll_requested_events(wait);
> >> -	struct vb2_buffer *vb = NULL;
> >> -	unsigned int res = 0;
> >> -	unsigned long flags;
> >> -
> >> -	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> >> -		struct v4l2_fh *fh = file->private_data;
> >> -
> >> -		if (v4l2_event_pending(fh))
> >> -			res = POLLPRI;
> >> -		else if (req_events & POLLPRI)
> >> -			poll_wait(file, &fh->wait, wait);
> >> -	}
> >> -
> >> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLIN | POLLRDNORM)))
> >> -		return res;
> >> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLOUT | POLLWRNORM)))
> >> -		return res;
> >> -
> >> -	/*
> >> -	 * Start file I/O emulator only if streaming API has not been used yet.
> >> -	 */
> >> -	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
> >> -		if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
> >> -				(req_events & (POLLIN | POLLRDNORM))) {
> >> -			if (__vb2_init_fileio(q, 1))
> >> -				return res | POLLERR;
> >> -		}
> >> -		if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
> >> -				(req_events & (POLLOUT | POLLWRNORM))) {
> >> -			if (__vb2_init_fileio(q, 0))
> >> -				return res | POLLERR;
> >> -			/*
> >> -			 * Write to OUTPUT queue can be done immediately.
> >> -			 */
> >> -			return res | POLLOUT | POLLWRNORM;
> >> -		}
> >> -	}
> >> -
> >> -	/*
> >> -	 * There is nothing to wait for if the queue isn't streaming, or if the
> >> -	 * error flag is set.
> >> -	 */
> >> -	if (!vb2_is_streaming(q) || q->error)
> >> -		return res | POLLERR;
> >> -	/*
> >> -	 * For compatibility with vb1: if QBUF hasn't been called yet, then
> >> -	 * return POLLERR as well. This only affects capture queues, output
> >> -	 * queues will always initialize waiting_for_buffers to false.
> >> -	 */
> >> -	if (q->waiting_for_buffers)
> >> -		return res | POLLERR;
> >> -
> >> -	/*
> >> -	 * For output streams you can write as long as there are fewer buffers
> >> -	 * queued than there are buffers available.
> >> -	 */
> >> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
> >> -		return res | POLLOUT | POLLWRNORM;
> >> -
> >> -	if (list_empty(&q->done_list)) {
> >> -		/*
> >> -		 * If the last buffer was dequeued from a capture queue,
> >> -		 * return immediately. DQBUF will return -EPIPE.
> >> -		 */
> >> -		if (q->last_buffer_dequeued)
> >> -			return res | POLLIN | POLLRDNORM;
> >> -
> >> -		poll_wait(file, &q->done_wq, wait);
> >> -	}
> >> -
> >> -	/*
> >> -	 * Take first buffer available for dequeuing.
> >> -	 */
> >> -	spin_lock_irqsave(&q->done_lock, flags);
> >> -	if (!list_empty(&q->done_list))
> >> -		vb = list_first_entry(&q->done_list, struct vb2_buffer,
> >> -					done_entry);
> >> -	spin_unlock_irqrestore(&q->done_lock, flags);
> >> -
> >> -	if (vb && (vb->state == VB2_BUF_STATE_DONE
> >> -			|| vb->state == VB2_BUF_STATE_ERROR)) {
> >> -		return (V4L2_TYPE_IS_OUTPUT(q->type)) ?
> >> -				res | POLLOUT | POLLWRNORM :
> >> -				res | POLLIN | POLLRDNORM;
> >> -	}
> >> -	return res;
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_poll);
> >> -
> >>   /**
> >> - * vb2_queue_init() - initialize a videobuf2 queue
> >> + * vb2_core_queue_init() - initialize a videobuf2 queue
> >>    * @q:		videobuf2 queue; this structure should be allocated in driver
> >>    *
> >>    * The vb2_queue structure should be allocated by the driver. The driver is
> >> @@ -2775,7 +2000,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
> >>    * to the struct vb2_queue description in include/media/videobuf2-core.h
> >>    * for more information.
> >>    */
> >> -int vb2_queue_init(struct vb2_queue *q)
> >> +int vb2_core_queue_init(struct vb2_queue *q)
> >>   {
> >>   	/*
> >>   	 * Sanity check
> >> @@ -2783,19 +2008,13 @@ int vb2_queue_init(struct vb2_queue *q)
> >>   	if (WARN_ON(!q)				||
> >>   		WARN_ON(!q->ops)		||
> >>   		WARN_ON(!q->mem_ops)		||
> >> +		WARN_ON(!q->buf_ops)		||
> >>   		WARN_ON(!q->type)		||
> >>   		WARN_ON(!q->io_modes)		||
> >>   		WARN_ON(!q->ops->queue_setup)	||
> >> -		WARN_ON(!q->ops->buf_queue)	||
> >> -		WARN_ON(q->timestamp_flags &
> >> -			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> >> -			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
> >> +		WARN_ON(!q->ops->buf_queue))
> >>   		return -EINVAL;
> >>
> >> -	/* Warn that the driver should choose an appropriate timestamp type */
> >> -	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> >> -		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
> >> -
> >>   	INIT_LIST_HEAD(&q->queued_list);
> >>   	INIT_LIST_HEAD(&q->done_list);
> >>   	spin_lock_init(&q->done_lock);
> >> @@ -2807,822 +2026,24 @@ int vb2_queue_init(struct vb2_queue *q)
> >>
> >>   	return 0;
> >>   }
> >> -EXPORT_SYMBOL_GPL(vb2_queue_init);
> >> +EXPORT_SYMBOL_GPL(vb2_core_queue_init);
> >>
> >>   /**
> >> - * vb2_queue_release() - stop streaming, release the queue and free memory
> >> + * vb2_core_queue_release() - stop streaming, release the queue and free memory
> >>    * @q:		videobuf2 queue
> >>    *
> >>    * This function stops streaming and performs necessary clean ups, including
> >>    * freeing video buffer memory. The driver is responsible for freeing
> >>    * the vb2_queue structure itself.
> >>    */
> >> -void vb2_queue_release(struct vb2_queue *q)
> >> +void vb2_core_queue_release(struct vb2_queue *q)
> >>   {
> >> -	__vb2_cleanup_fileio(q);
> >>   	__vb2_queue_cancel(q);
> >>   	mutex_lock(&q->mmap_lock);
> >>   	__vb2_queue_free(q, q->num_buffers);
> >>   	mutex_unlock(&q->mmap_lock);
> >>   }
> >> -EXPORT_SYMBOL_GPL(vb2_queue_release);
> >> -
> >> -/**
> >> - * struct vb2_fileio_buf - buffer context used by file io emulator
> >> - *
> >> - * vb2 provides a compatibility layer and emulator of file io (read and
> >> - * write) calls on top of streaming API. This structure is used for
> >> - * tracking context related to the buffers.
> >> - */
> >> -struct vb2_fileio_buf {
> >> -	void *vaddr;
> >> -	unsigned int size;
> >> -	unsigned int pos;
> >> -	unsigned int queued:1;
> >> -};
> >> -
> >> -/**
> >> - * struct vb2_fileio_data - queue context used by file io emulator
> >> - *
> >> - * @cur_index:	the index of the buffer currently being read from or
> >> - *		written to. If equal to q->num_buffers then a new buffer
> >> - *		must be dequeued.
> >> - * @initial_index: in the read() case all buffers are queued up immediately
> >> - *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
> >> - *		buffers. However, in the write() case no buffers are initially
> >> - *		queued, instead whenever a buffer is full it is queued up by
> >> - *		__vb2_perform_fileio(). Only once all available buffers have
> >> - *		been queued up will __vb2_perform_fileio() start to dequeue
> >> - *		buffers. This means that initially __vb2_perform_fileio()
> >> - *		needs to know what buffer index to use when it is queuing up
> >> - *		the buffers for the first time. That initial index is stored
> >> - *		in this field. Once it is equal to q->num_buffers all
> >> - *		available buffers have been queued and __vb2_perform_fileio()
> >> - *		should start the normal dequeue/queue cycle.
> >> - *
> >> - * vb2 provides a compatibility layer and emulator of file io (read and
> >> - * write) calls on top of streaming API. For proper operation it required
> >> - * this structure to save the driver state between each call of the read
> >> - * or write function.
> >> - */
> >> -struct vb2_fileio_data {
> >> -	struct v4l2_requestbuffers req;
> >> -	struct v4l2_plane p;
> >> -	struct v4l2_buffer b;
> >> -	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
> >> -	unsigned int cur_index;
> >> -	unsigned int initial_index;
> >> -	unsigned int q_count;
> >> -	unsigned int dq_count;
> >> -	unsigned read_once:1;
> >> -	unsigned write_immediately:1;
> >> -};
> >> -
> >> -/**
> >> - * __vb2_init_fileio() - initialize file io emulator
> >> - * @q:		videobuf2 queue
> >> - * @read:	mode selector (1 means read, 0 means write)
> >> - */
> >> -static int __vb2_init_fileio(struct vb2_queue *q, int read)
> >> -{
> >> -	struct vb2_fileio_data *fileio;
> >> -	int i, ret;
> >> -	unsigned int count = 0;
> >> -
> >> -	/*
> >> -	 * Sanity check
> >> -	 */
> >> -	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
> >> -			(!read && !(q->io_modes & VB2_WRITE))))
> >> -		return -EINVAL;
> >> -
> >> -	/*
> >> -	 * Check if device supports mapping buffers to kernel virtual space.
> >> -	 */
> >> -	if (!q->mem_ops->vaddr)
> >> -		return -EBUSY;
> >> -
> >> -	/*
> >> -	 * Check if streaming api has not been already activated.
> >> -	 */
> >> -	if (q->streaming || q->num_buffers > 0)
> >> -		return -EBUSY;
> >> -
> >> -	/*
> >> -	 * Start with count 1, driver can increase it in queue_setup()
> >> -	 */
> >> -	count = 1;
> >> -
> >> -	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
> >> -		(read) ? "read" : "write", count, q->fileio_read_once,
> >> -		q->fileio_write_immediately);
> >> -
> >> -	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
> >> -	if (fileio == NULL)
> >> -		return -ENOMEM;
> >> -
> >> -	fileio->read_once = q->fileio_read_once;
> >> -	fileio->write_immediately = q->fileio_write_immediately;
> >> -
> >> -	/*
> >> -	 * Request buffers and use MMAP type to force driver
> >> -	 * to allocate buffers by itself.
> >> -	 */
> >> -	fileio->req.count = count;
> >> -	fileio->req.memory = V4L2_MEMORY_MMAP;
> >> -	fileio->req.type = q->type;
> >> -	q->fileio = fileio;
> >> -	ret = __reqbufs(q, &fileio->req);
> >> -	if (ret)
> >> -		goto err_kfree;
> >> -
> >> -	/*
> >> -	 * Check if plane_count is correct
> >> -	 * (multiplane buffers are not supported).
> >> -	 */
> >> -	if (q->bufs[0]->num_planes != 1) {
> >> -		ret = -EBUSY;
> >> -		goto err_reqbufs;
> >> -	}
> >> -
> >> -	/*
> >> -	 * Get kernel address of each buffer.
> >> -	 */
> >> -	for (i = 0; i < q->num_buffers; i++) {
> >> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
> >> -		if (fileio->bufs[i].vaddr == NULL) {
> >> -			ret = -EINVAL;
> >> -			goto err_reqbufs;
> >> -		}
> >> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
> >> -	}
> >> -
> >> -	/*
> >> -	 * Read mode requires pre queuing of all buffers.
> >> -	 */
> >> -	if (read) {
> >> -		bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> >> -
> >> -		/*
> >> -		 * Queue all buffers.
> >> -		 */
> >> -		for (i = 0; i < q->num_buffers; i++) {
> >> -			struct v4l2_buffer *b = &fileio->b;
> >> -
> >> -			memset(b, 0, sizeof(*b));
> >> -			b->type = q->type;
> >> -			if (is_multiplanar) {
> >> -				memset(&fileio->p, 0, sizeof(fileio->p));
> >> -				b->m.planes = &fileio->p;
> >> -				b->length = 1;
> >> -			}
> >> -			b->memory = q->memory;
> >> -			b->index = i;
> >> -			ret = vb2_internal_qbuf(q, b);
> >> -			if (ret)
> >> -				goto err_reqbufs;
> >> -			fileio->bufs[i].queued = 1;
> >> -		}
> >> -		/*
> >> -		 * All buffers have been queued, so mark that by setting
> >> -		 * initial_index to q->num_buffers
> >> -		 */
> >> -		fileio->initial_index = q->num_buffers;
> >> -		fileio->cur_index = q->num_buffers;
> >> -	}
> >> -
> >> -	/*
> >> -	 * Start streaming.
> >> -	 */
> >> -	ret = vb2_internal_streamon(q, q->type);
> >> -	if (ret)
> >> -		goto err_reqbufs;
> >> -
> >> -	return ret;
> >> -
> >> -err_reqbufs:
> >> -	fileio->req.count = 0;
> >> -	__reqbufs(q, &fileio->req);
> >> -
> >> -err_kfree:
> >> -	q->fileio = NULL;
> >> -	kfree(fileio);
> >> -	return ret;
> >> -}
> >> -
> >> -/**
> >> - * __vb2_cleanup_fileio() - free resourced used by file io emulator
> >> - * @q:		videobuf2 queue
> >> - */
> >> -static int __vb2_cleanup_fileio(struct vb2_queue *q)
> >> -{
> >> -	struct vb2_fileio_data *fileio = q->fileio;
> >> -
> >> -	if (fileio) {
> >> -		vb2_internal_streamoff(q, q->type);
> >> -		q->fileio = NULL;
> >> -		fileio->req.count = 0;
> >> -		vb2_reqbufs(q, &fileio->req);
> >> -		kfree(fileio);
> >> -		dprintk(3, "file io emulator closed\n");
> >> -	}
> >> -	return 0;
> >> -}
> >> -
> >> -/**
> >> - * __vb2_perform_fileio() - perform a single file io (read or write) operation
> >> - * @q:		videobuf2 queue
> >> - * @data:	pointed to target userspace buffer
> >> - * @count:	number of bytes to read or write
> >> - * @ppos:	file handle position tracking pointer
> >> - * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
> >> - * @read:	access mode selector (1 means read, 0 means write)
> >> - */
> >> -static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
> >> -		loff_t *ppos, int nonblock, int read)
> >> -{
> >> -	struct vb2_fileio_data *fileio;
> >> -	struct vb2_fileio_buf *buf;
> >> -	bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> >> -	/*
> >> -	 * When using write() to write data to an output video node the vb2 core
> >> -	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
> >> -	 * else is able to provide this information with the write() operation.
> >> -	 */
> >> -	bool set_timestamp = !read &&
> >> -		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> >> -		V4L2_BUF_FLAG_TIMESTAMP_COPY;
> >> -	int ret, index;
> >> -
> >> -	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
> >> -		read ? "read" : "write", (long)*ppos, count,
> >> -		nonblock ? "non" : "");
> >> -
> >> -	if (!data)
> >> -		return -EINVAL;
> >> -
> >> -	/*
> >> -	 * Initialize emulator on first call.
> >> -	 */
> >> -	if (!vb2_fileio_is_active(q)) {
> >> -		ret = __vb2_init_fileio(q, read);
> >> -		dprintk(3, "vb2_init_fileio result: %d\n", ret);
> >> -		if (ret)
> >> -			return ret;
> >> -	}
> >> -	fileio = q->fileio;
> >> -
> >> -	/*
> >> -	 * Check if we need to dequeue the buffer.
> >> -	 */
> >> -	index = fileio->cur_index;
> >> -	if (index >= q->num_buffers) {
> >> -		/*
> >> -		 * Call vb2_dqbuf to get buffer back.
> >> -		 */
> >> -		memset(&fileio->b, 0, sizeof(fileio->b));
> >> -		fileio->b.type = q->type;
> >> -		fileio->b.memory = q->memory;
> >> -		if (is_multiplanar) {
> >> -			memset(&fileio->p, 0, sizeof(fileio->p));
> >> -			fileio->b.m.planes = &fileio->p;
> >> -			fileio->b.length = 1;
> >> -		}
> >> -		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
> >> -		dprintk(5, "vb2_dqbuf result: %d\n", ret);
> >> -		if (ret)
> >> -			return ret;
> >> -		fileio->dq_count += 1;
> >> -
> >> -		fileio->cur_index = index = fileio->b.index;
> >> -		buf = &fileio->bufs[index];
> >> -
> >> -		/*
> >> -		 * Get number of bytes filled by the driver
> >> -		 */
> >> -		buf->pos = 0;
> >> -		buf->queued = 0;
> >> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> >> -				 : vb2_plane_size(q->bufs[index], 0);
> >> -		/*
> >> -		 * Compensate for data_offset on read
> >> -		 * in the multiplanar case
> >> -		 */
> >> -		if (is_multiplanar && read &&
> >> -			fileio->b.m.planes[0].data_offset < buf->size) {
> >> -			buf->pos = fileio->b.m.planes[0].data_offset;
> >> -			buf->size -= buf->pos;
> >> -		}
> >> -	} else {
> >> -		buf = &fileio->bufs[index];
> >> -	}
> >> -
> >> -	/*
> >> -	 * Limit count on last few bytes of the buffer.
> >> -	 */
> >> -	if (buf->pos + count > buf->size) {
> >> -		count = buf->size - buf->pos;
> >> -		dprintk(5, "reducing read count: %zd\n", count);
> >> -	}
> >> -
> >> -	/*
> >> -	 * Transfer data to userspace.
> >> -	 */
> >> -	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
> >> -		count, index, buf->pos);
> >> -	if (read)
> >> -		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
> >> -	else
> >> -		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
> >> -	if (ret) {
> >> -		dprintk(3, "error copying data\n");
> >> -		return -EFAULT;
> >> -	}
> >> -
> >> -	/*
> >> -	 * Update counters.
> >> -	 */
> >> -	buf->pos += count;
> >> -	*ppos += count;
> >> -
> >> -	/*
> >> -	 * Queue next buffer if required.
> >> -	 */
> >> -	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
> >> -		/*
> >> -		 * Check if this is the last buffer to read.
> >> -		 */
> >> -		if (read && fileio->read_once && fileio->dq_count == 1) {
> >> -			dprintk(3, "read limit reached\n");
> >> -			return __vb2_cleanup_fileio(q);
> >> -		}
> >> -
> >> -		/*
> >> -		 * Call vb2_qbuf and give buffer to the driver.
> >> -		 */
> >> -		memset(&fileio->b, 0, sizeof(fileio->b));
> >> -		fileio->b.type = q->type;
> >> -		fileio->b.memory = q->memory;
> >> -		fileio->b.index = index;
> >> -		fileio->b.bytesused = buf->pos;
> >> -		if (is_multiplanar) {
> >> -			memset(&fileio->p, 0, sizeof(fileio->p));
> >> -			fileio->p.bytesused = buf->pos;
> >> -			fileio->b.m.planes = &fileio->p;
> >> -			fileio->b.length = 1;
> >> -		}
> >> -		if (set_timestamp)
> >> -			v4l2_get_timestamp(&fileio->b.timestamp);
> >> -		ret = vb2_internal_qbuf(q, &fileio->b);
> >> -		dprintk(5, "vb2_dbuf result: %d\n", ret);
> >> -		if (ret)
> >> -			return ret;
> >> -
> >> -		/*
> >> -		 * Buffer has been queued, update the status
> >> -		 */
> >> -		buf->pos = 0;
> >> -		buf->queued = 1;
> >> -		buf->size = vb2_plane_size(q->bufs[index], 0);
> >> -		fileio->q_count += 1;
> >> -		/*
> >> -		 * If we are queuing up buffers for the first time, then
> >> -		 * increase initial_index by one.
> >> -		 */
> >> -		if (fileio->initial_index < q->num_buffers)
> >> -			fileio->initial_index++;
> >> -		/*
> >> -		 * The next buffer to use is either a buffer that's going to be
> >> -		 * queued for the first time (initial_index < q->num_buffers)
> >> -		 * or it is equal to q->num_buffers, meaning that the next
> >> -		 * time we need to dequeue a buffer since we've now queued up
> >> -		 * all the 'first time' buffers.
> >> -		 */
> >> -		fileio->cur_index = fileio->initial_index;
> >> -	}
> >> -
> >> -	/*
> >> -	 * Return proper number of bytes processed.
> >> -	 */
> >> -	if (ret == 0)
> >> -		ret = count;
> >> -	return ret;
> >> -}
> >> -
> >> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> >> -		loff_t *ppos, int nonblocking)
> >> -{
> >> -	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_read);
> >> -
> >> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> >> -		loff_t *ppos, int nonblocking)
> >> -{
> >> -	return __vb2_perform_fileio(q, (char __user *) data, count,
> >> -							ppos, nonblocking, 0);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_write);
> >> -
> >> -struct vb2_threadio_data {
> >> -	struct task_struct *thread;
> >> -	vb2_thread_fnc fnc;
> >> -	void *priv;
> >> -	bool stop;
> >> -};
> >> -
> >> -static int vb2_thread(void *data)
> >> -{
> >> -	struct vb2_queue *q = data;
> >> -	struct vb2_threadio_data *threadio = q->threadio;
> >> -	struct vb2_fileio_data *fileio = q->fileio;
> >> -	bool set_timestamp = false;
> >> -	int prequeue = 0;
> >> -	int index = 0;
> >> -	int ret = 0;
> >> -
> >> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
> >> -		prequeue = q->num_buffers;
> >> -		set_timestamp =
> >> -			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> >> -			V4L2_BUF_FLAG_TIMESTAMP_COPY;
> >> -	}
> >> -
> >> -	set_freezable();
> >> -
> >> -	for (;;) {
> >> -		struct vb2_buffer *vb;
> >> -
> >> -		/*
> >> -		 * Call vb2_dqbuf to get buffer back.
> >> -		 */
> >> -		memset(&fileio->b, 0, sizeof(fileio->b));
> >> -		fileio->b.type = q->type;
> >> -		fileio->b.memory = q->memory;
> >> -		if (prequeue) {
> >> -			fileio->b.index = index++;
> >> -			prequeue--;
> >> -		} else {
> >> -			call_void_qop(q, wait_finish, q);
> >> -			if (!threadio->stop)
> >> -				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
> >> -			call_void_qop(q, wait_prepare, q);
> >> -			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
> >> -		}
> >> -		if (ret || threadio->stop)
> >> -			break;
> >> -		try_to_freeze();
> >> -
> >> -		vb = q->bufs[fileio->b.index];
> >> -		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
> >> -			if (threadio->fnc(vb, threadio->priv))
> >> -				break;
> >> -		call_void_qop(q, wait_finish, q);
> >> -		if (set_timestamp)
> >> -			v4l2_get_timestamp(&fileio->b.timestamp);
> >> -		if (!threadio->stop)
> >> -			ret = vb2_internal_qbuf(q, &fileio->b);
> >> -		call_void_qop(q, wait_prepare, q);
> >> -		if (ret || threadio->stop)
> >> -			break;
> >> -	}
> >> -
> >> -	/* Hmm, linux becomes *very* unhappy without this ... */
> >> -	while (!kthread_should_stop()) {
> >> -		set_current_state(TASK_INTERRUPTIBLE);
> >> -		schedule();
> >> -	}
> >> -	return 0;
> >> -}
> >> -
> >> -/*
> >> - * This function should not be used for anything else but the videobuf2-dvb
> >> - * support. If you think you have another good use-case for this, then please
> >> - * contact the linux-media mailinglist first.
> >> - */
> >> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> >> -			const char *thread_name)
> >> -{
> >> -	struct vb2_threadio_data *threadio;
> >> -	int ret = 0;
> >> -
> >> -	if (q->threadio)
> >> -		return -EBUSY;
> >> -	if (vb2_is_busy(q))
> >> -		return -EBUSY;
> >> -	if (WARN_ON(q->fileio))
> >> -		return -EBUSY;
> >> -
> >> -	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
> >> -	if (threadio == NULL)
> >> -		return -ENOMEM;
> >> -	threadio->fnc = fnc;
> >> -	threadio->priv = priv;
> >> -
> >> -	ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type));
> >> -	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
> >> -	if (ret)
> >> -		goto nomem;
> >> -	q->threadio = threadio;
> >> -	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
> >> -	if (IS_ERR(threadio->thread)) {
> >> -		ret = PTR_ERR(threadio->thread);
> >> -		threadio->thread = NULL;
> >> -		goto nothread;
> >> -	}
> >> -	return 0;
> >> -
> >> -nothread:
> >> -	__vb2_cleanup_fileio(q);
> >> -nomem:
> >> -	kfree(threadio);
> >> -	return ret;
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_thread_start);
> >> -
> >> -int vb2_thread_stop(struct vb2_queue *q)
> >> -{
> >> -	struct vb2_threadio_data *threadio = q->threadio;
> >> -	int err;
> >> -
> >> -	if (threadio == NULL)
> >> -		return 0;
> >> -	threadio->stop = true;
> >> -	/* Wake up all pending sleeps in the thread */
> >> -	vb2_queue_error(q);
> >> -	err = kthread_stop(threadio->thread);
> >> -	__vb2_cleanup_fileio(q);
> >> -	threadio->thread = NULL;
> >> -	kfree(threadio);
> >> -	q->threadio = NULL;
> >> -	return err;
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_thread_stop);
> >> -
> >> -/*
> >> - * The following functions are not part of the vb2 core API, but are helper
> >> - * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
> >> - * and struct vb2_ops.
> >> - * They contain boilerplate code that most if not all drivers have to do
> >> - * and so they simplify the driver code.
> >> - */
> >> -
> >> -/* The queue is busy if there is a owner and you are not that owner. */
> >> -static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
> >> -{
> >> -	return vdev->queue->owner && vdev->queue->owner != file->private_data;
> >> -}
> >> -
> >> -/* vb2 ioctl helpers */
> >> -
> >> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
> >> -			  struct v4l2_requestbuffers *p)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -	int res = __verify_memory_type(vdev->queue, p->memory, p->type);
> >> -
> >> -	if (res)
> >> -		return res;
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		return -EBUSY;
> >> -	res = __reqbufs(vdev->queue, p);
> >> -	/* If count == 0, then the owner has released all buffers and he
> >> -	   is no longer owner of the queue. Otherwise we have a new owner. */
> >> -	if (res == 0)
> >> -		vdev->queue->owner = p->count ? file->private_data : NULL;
> >> -	return res;
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
> >> -
> >> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
> >> -			  struct v4l2_create_buffers *p)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -	int res = __verify_memory_type(vdev->queue, p->memory, p->format.type);
> >> -
> >> -	p->index = vdev->queue->num_buffers;
> >> -	/* If count == 0, then just check if memory and type are valid.
> >> -	   Any -EBUSY result from __verify_memory_type can be mapped to 0. */
> >> -	if (p->count == 0)
> >> -		return res != -EBUSY ? res : 0;
> >> -	if (res)
> >> -		return res;
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		return -EBUSY;
> >> -	res = __create_bufs(vdev->queue, p);
> >> -	if (res == 0)
> >> -		vdev->queue->owner = file->private_data;
> >> -	return res;
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
> >> -
> >> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> >> -			  struct v4l2_buffer *p)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		return -EBUSY;
> >> -	return vb2_prepare_buf(vdev->queue, p);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
> >> -
> >> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
> >> -	return vb2_querybuf(vdev->queue, p);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
> >> -
> >> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		return -EBUSY;
> >> -	return vb2_qbuf(vdev->queue, p);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
> >> -
> >> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		return -EBUSY;
> >> -	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
> >> -
> >> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		return -EBUSY;
> >> -	return vb2_streamon(vdev->queue, i);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
> >> -
> >> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		return -EBUSY;
> >> -	return vb2_streamoff(vdev->queue, i);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
> >> -
> >> -int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		return -EBUSY;
> >> -	return vb2_expbuf(vdev->queue, p);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
> >> -
> >> -/* v4l2_file_operations helpers */
> >> -
> >> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	return vb2_mmap(vdev->queue, vma);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_fop_mmap);
> >> -
> >> -int _vb2_fop_release(struct file *file, struct mutex *lock)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	if (lock)
> >> -		mutex_lock(lock);
> >> -	if (file->private_data == vdev->queue->owner) {
> >> -		vb2_queue_release(vdev->queue);
> >> -		vdev->queue->owner = NULL;
> >> -	}
> >> -	if (lock)
> >> -		mutex_unlock(lock);
> >> -	return v4l2_fh_release(file);
> >> -}
> >> -EXPORT_SYMBOL_GPL(_vb2_fop_release);
> >> -
> >> -int vb2_fop_release(struct file *file)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> >> -
> >> -	return _vb2_fop_release(file, lock);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_fop_release);
> >> -
> >> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> >> -		size_t count, loff_t *ppos)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> >> -	int err = -EBUSY;
> >> -
> >> -	if (!(vdev->queue->io_modes & VB2_WRITE))
> >> -		return -EINVAL;
> >> -	if (lock && mutex_lock_interruptible(lock))
> >> -		return -ERESTARTSYS;
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		goto exit;
> >> -	err = vb2_write(vdev->queue, buf, count, ppos,
> >> -			file->f_flags & O_NONBLOCK);
> >> -	if (vdev->queue->fileio)
> >> -		vdev->queue->owner = file->private_data;
> >> -exit:
> >> -	if (lock)
> >> -		mutex_unlock(lock);
> >> -	return err;
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_fop_write);
> >> -
> >> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
> >> -		size_t count, loff_t *ppos)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> >> -	int err = -EBUSY;
> >> -
> >> -	if (!(vdev->queue->io_modes & VB2_READ))
> >> -		return -EINVAL;
> >> -	if (lock && mutex_lock_interruptible(lock))
> >> -		return -ERESTARTSYS;
> >> -	if (vb2_queue_is_busy(vdev, file))
> >> -		goto exit;
> >> -	err = vb2_read(vdev->queue, buf, count, ppos,
> >> -			file->f_flags & O_NONBLOCK);
> >> -	if (vdev->queue->fileio)
> >> -		vdev->queue->owner = file->private_data;
> >> -exit:
> >> -	if (lock)
> >> -		mutex_unlock(lock);
> >> -	return err;
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_fop_read);
> >> -
> >> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -	struct vb2_queue *q = vdev->queue;
> >> -	struct mutex *lock = q->lock ? q->lock : vdev->lock;
> >> -	unsigned res;
> >> -	void *fileio;
> >> -
> >> -	/*
> >> -	 * If this helper doesn't know how to lock, then you shouldn't be using
> >> -	 * it but you should write your own.
> >> -	 */
> >> -	WARN_ON(!lock);
> >> -
> >> -	if (lock && mutex_lock_interruptible(lock))
> >> -		return POLLERR;
> >> -
> >> -	fileio = q->fileio;
> >> -
> >> -	res = vb2_poll(vdev->queue, file, wait);
> >> -
> >> -	/* If fileio was started, then we have a new queue owner. */
> >> -	if (!fileio && q->fileio)
> >> -		q->owner = file->private_data;
> >> -	if (lock)
> >> -		mutex_unlock(lock);
> >> -	return res;
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_fop_poll);
> >> -
> >> -#ifndef CONFIG_MMU
> >> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> >> -		unsigned long len, unsigned long pgoff, unsigned long flags)
> >> -{
> >> -	struct video_device *vdev = video_devdata(file);
> >> -
> >> -	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
> >> -#endif
> >> -
> >> -/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
> >> -
> >> -void vb2_ops_wait_prepare(struct vb2_queue *vq)
> >> -{
> >> -	mutex_unlock(vq->lock);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
> >> -
> >> -void vb2_ops_wait_finish(struct vb2_queue *vq)
> >> -{
> >> -	mutex_lock(vq->lock);
> >> -}
> >> -EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
> >> +EXPORT_SYMBOL_GPL(vb2_core_queue_release);
> >>
> >>   MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
> >>   MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
> >> diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h
> >> new file mode 100644
> >> index 0000000..3998ac9
> >> --- /dev/null
> >> +++ b/drivers/media/v4l2-core/videobuf2-internal.h
> >> @@ -0,0 +1,184 @@
> >> +#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H
> >> +#define _MEDIA_VIDEOBUF2_INTERNAL_H
> >> +
> >> +#include <linux/err.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/module.h>
> >> +#include <media/videobuf2-core.h>
> >> +
> >> +extern int vb2_debug;
> >> +
> >> +#define dprintk(level, fmt, arg...)					\
> >> +	do {								\
> >> +		if (vb2_debug >= level)					\
> >> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
> >> +	} while (0)
> >> +
> >> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> >> +
> >> +/*
> >> + * If advanced debugging is on, then count how often each op is called
> >> + * successfully, which can either be per-buffer or per-queue.
> >> + *
> >> + * This makes it easy to check that the 'init' and 'cleanup'
> >> + * (and variations thereof) stay balanced.
> >> + */
> >> +
> >> +#define log_memop(vb, op)						\
> >> +	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
> >> +		(vb)->vb2_queue, (vb)->index, #op,			\
> >> +		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
> >> +
> >> +#define call_memop(vb, op, args...)					\
> >> +({									\
> >> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
> >> +	int err;							\
> >> +									\
> >> +	log_memop(vb, op);						\
> >> +	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
> >> +	if (!err)							\
> >> +		(vb)->cnt_mem_ ## op++;					\
> >> +	err;								\
> >> +})
> >> +
> >> +#define call_ptr_memop(vb, op, args...)					\
> >> +({									\
> >> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
> >> +	void *ptr;							\
> >> +									\
> >> +	log_memop(vb, op);						\
> >> +	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
> >> +	if (!IS_ERR_OR_NULL(ptr))					\
> >> +		(vb)->cnt_mem_ ## op++;					\
> >> +	ptr;								\
> >> +})
> >> +
> >> +#define call_void_memop(vb, op, args...)				\
> >> +({									\
> >> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
> >> +									\
> >> +	log_memop(vb, op);						\
> >> +	if (_q->mem_ops->op)						\
> >> +		_q->mem_ops->op(args);					\
> >> +	(vb)->cnt_mem_ ## op++;						\
> >> +})
> >> +
> >> +#define log_qop(q, op)							\
> >> +	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
> >> +		(q)->ops->op ? "" : " (nop)")
> >> +
> >> +#define call_qop(q, op, args...)					\
> >> +({									\
> >> +	int err;							\
> >> +									\
> >> +	log_qop(q, op);							\
> >> +	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
> >> +	if (!err)							\
> >> +		(q)->cnt_ ## op++;					\
> >> +	err;								\
> >> +})
> >> +
> >> +#define call_void_qop(q, op, args...)					\
> >> +({									\
> >> +	log_qop(q, op);							\
> >> +	if ((q)->ops->op)						\
> >> +		(q)->ops->op(args);					\
> >> +	(q)->cnt_ ## op++;						\
> >> +})
> >> +
> >> +#define log_vb_qop(vb, op, args...)					\
> >> +	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
> >> +		(vb)->vb2_queue, (vb)->index, #op,			\
> >> +		(vb)->vb2_queue->ops->op ? "" : " (nop)")
> >> +
> >> +#define call_vb_qop(vb, op, args...)					\
> >> +({									\
> >> +	int err;							\
> >> +									\
> >> +	log_vb_qop(vb, op);						\
> >> +	err = (vb)->vb2_queue->ops->op ?				\
> >> +		(vb)->vb2_queue->ops->op(args) : 0;			\
> >> +	if (!err)							\
> >> +		(vb)->cnt_ ## op++;					\
> >> +	err;								\
> >> +})
> >> +
> >> +#define call_void_vb_qop(vb, op, args...)				\
> >> +({									\
> >> +	log_vb_qop(vb, op);						\
> >> +	if ((vb)->vb2_queue->ops->op)					\
> >> +		(vb)->vb2_queue->ops->op(args);				\
> >> +	(vb)->cnt_ ## op++;						\
> >> +})
> >> +
> >> +#else
> >> +
> >> +#define call_memop(vb, op, args...)					\
> >> +	((vb)->vb2_queue->mem_ops->op ?					\
> >> +		(vb)->vb2_queue->mem_ops->op(args) : 0)
> >> +
> >> +#define call_ptr_memop(vb, op, args...)					\
> >> +	((vb)->vb2_queue->mem_ops->op ?					\
> >> +		(vb)->vb2_queue->mem_ops->op(args) : NULL)
> >> +
> >> +#define call_void_memop(vb, op, args...)				\
> >> +	do {								\
> >> +		if ((vb)->vb2_queue->mem_ops->op)			\
> >> +			(vb)->vb2_queue->mem_ops->op(args);		\
> >> +	} while (0)
> >> +
> >> +#define call_qop(q, op, args...)					\
> >> +	((q)->ops->op ? (q)->ops->op(args) : 0)
> >> +
> >> +#define call_void_qop(q, op, args...)					\
> >> +	do {								\
> >> +		if ((q)->ops->op)					\
> >> +			(q)->ops->op(args);				\
> >> +	} while (0)
> >> +
> >> +#define call_vb_qop(vb, op, args...)					\
> >> +	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
> >> +
> >> +#define call_void_vb_qop(vb, op, args...)				\
> >> +	do {								\
> >> +		if ((vb)->vb2_queue->ops->op)				\
> >> +			(vb)->vb2_queue->ops->op(args);			\
> >> +	} while (0)
> >> +
> >> +#endif
> >> +
> >> +#define call_bufop(q, op, args...)					\
> >> +({									\
> >> +	int ret = 0;							\
> >> +	if (q && q->buf_ops && q->buf_ops->op)				\
> >> +		ret = q->buf_ops->op(args);				\
> >> +	ret;								\
> >> +})
> >> +
> >> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
> >> +int vb2_verify_memory_type(struct vb2_queue *q,
> >> +		unsigned int memory, unsigned int type);
> >> +int vb2_verify_buffer(struct vb2_queue *q,
> >> +			unsigned int memory, unsigned int type,
> >> +			unsigned int index, unsigned int nplanes,
> >> +			void *pplane, const char *opname);
> >> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb);
> >> +
> >> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb);
> >> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
> >> +		unsigned int *count);
> >> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
> >> +		unsigned int *count, void *parg);
> >> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
> >> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb);
> >> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblock);
> >> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
> >> +		unsigned int index, unsigned int plane, unsigned int flags);
> >> +int vb2_core_streamon(struct vb2_queue *q);
> >> +int vb2_core_streamoff(struct vb2_queue *q);
> >> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
> >> +
> >> +int __must_check vb2_core_queue_init(struct vb2_queue *q);
> >> +void vb2_core_queue_release(struct vb2_queue *q);
> >> +
> >> +#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */
> >> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> >> index 2f2b738..9fc6bef 100644
> >> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> >> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> >> @@ -24,8 +24,1648 @@
> >>   #include <linux/freezer.h>
> >>   #include <linux/kthread.h>
> >>
> >> +#include <media/v4l2-dev.h>
> >> +#include <media/v4l2-fh.h>
> >> +#include <media/v4l2-event.h>
> >> +#include <media/v4l2-common.h>
> >>   #include <media/videobuf2-v4l2.h>
> >>
> >> +#include "videobuf2-internal.h"
> >> +
> >> +/* Flags that are set by the vb2 core */
> >> +#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | \
> >> +				V4L2_BUF_FLAG_QUEUED | \
> >> +				V4L2_BUF_FLAG_DONE | \
> >> +				V4L2_BUF_FLAG_ERROR | \
> >> +				V4L2_BUF_FLAG_PREPARED | \
> >> +				V4L2_BUF_FLAG_TIMESTAMP_MASK)
> >> +
> >> +/* Output buffer flags that should be passed on to the driver */
> >> +#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | \
> >> +				V4L2_BUF_FLAG_BFRAME | \
> >> +				V4L2_BUF_FLAG_KEYFRAME | \
> >> +				V4L2_BUF_FLAG_TIMECODE)
> >> +
> >> +/**
> >> + * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
> >> + * returned to userspace
> >> + */
> >> +static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
> >> +{
> >> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
> >
> > As commented before, avoid doing typecasts if not required.
> >
> >> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >> +	struct vb2_queue *q = vb->vb2_queue;
> >> +	unsigned int plane;
> >> +
> >> +	/* Copy back data such as timestamp, flags, etc. */
> >> +	b->index = vb->index;
> >> +	b->type = vb->type;
> >> +	b->memory = vb->memory;
> >> +	b->bytesused = 0;
> >> +
> >> +	b->flags = vbuf->flags;
> >> +	b->field = vbuf->field;
> >> +	b->timestamp = vbuf->timestamp;
> >> +	b->timecode = vbuf->timecode;
> >> +	b->sequence = vbuf->sequence;
> >> +
> >> +	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
> >> +		/*
> >> +		 * Fill in plane-related data if userspace provided an array
> >> +		 * for it. The caller has already verified memory and size.
> >> +		 */
> >> +		b->length = vb->num_planes;
> >> +		for (plane = 0; plane < vb->num_planes; ++plane) {
> >> +			struct v4l2_plane *pdst = &b->m.planes[plane];
> >> +			struct vb2_plane *psrc = &vb->planes[plane];
> >> +
> >> +			pdst->bytesused = psrc->bytesused;
> >> +			pdst->length = psrc->length;
> >> +			if (q->memory == V4L2_MEMORY_MMAP)
> >> +				pdst->m.mem_offset = psrc->m.offset;
> >> +			else if (q->memory == V4L2_MEMORY_USERPTR)
> >> +				pdst->m.userptr = psrc->m.userptr;
> >> +			else if (q->memory == V4L2_MEMORY_DMABUF)
> >> +				pdst->m.fd = psrc->m.fd;
> >> +			pdst->data_offset = psrc->data_offset;
> >> +		}
> >> +	} else {
> >> +		/*
> >> +		 * We use length and offset in v4l2_planes array even for
> >> +		 * single-planar buffers, but userspace does not.
> >> +		 */
> >> +		b->length = vb->planes[0].length;
> >> +		b->bytesused = vb->planes[0].bytesused;
> >> +		if (q->memory == V4L2_MEMORY_MMAP)
> >> +			b->m.offset = vb->planes[0].m.offset;
> >> +		else if (q->memory == V4L2_MEMORY_USERPTR)
> >> +			b->m.userptr = vb->planes[0].m.userptr;
> >> +		else if (q->memory == V4L2_MEMORY_DMABUF)
> >> +			b->m.fd = vb->planes[0].m.fd;
> >> +	}
> >> +
> >> +	/*
> >> +	 * Clear any buffer state related flags.
> >> +	 */
> >> +	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
> >> +	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
> >> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> >> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> >> +		/*
> >> +		 * For non-COPY timestamps, drop timestamp source bits
> >> +		 * and obtain the timestamp source from the queue.
> >> +		 */
> >> +		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> >> +		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> >> +	}
> >> +
> >> +	switch (vb->state) {
> >> +	case VB2_BUF_STATE_QUEUED:
> >> +	case VB2_BUF_STATE_ACTIVE:
> >> +		b->flags |= V4L2_BUF_FLAG_QUEUED;
> >> +		break;
> >> +	case VB2_BUF_STATE_ERROR:
> >> +		b->flags |= V4L2_BUF_FLAG_ERROR;
> >> +		/* fall through */
> >> +	case VB2_BUF_STATE_DONE:
> >> +		b->flags |= V4L2_BUF_FLAG_DONE;
> >> +		break;
> >> +	case VB2_BUF_STATE_PREPARED:
> >> +		b->flags |= V4L2_BUF_FLAG_PREPARED;
> >> +		break;
> >> +	case VB2_BUF_STATE_PREPARING:
> >> +	case VB2_BUF_STATE_DEQUEUED:
> >> +		/* nothing */
> >> +		break;
> >> +	}
> >> +
> >> +	if (vb2_buffer_in_use(q, vb))
> >> +		b->flags |= V4L2_BUF_FLAG_MAPPED;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +/**
> >> + * __verify_length() - Verify that the bytesused value for each plane fits in
> >> + * the plane length and that the data offset doesn't exceed the bytesused value.
> >> + */
> >> +static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >> +{
> >> +	unsigned int length;
> >> +	unsigned int bytesused;
> >> +	unsigned int plane;
> >> +
> >> +	if (!V4L2_TYPE_IS_OUTPUT(b->type))
> >> +		return 0;
> >> +
> >> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> >> +		for (plane = 0; plane < vb->num_planes; ++plane) {
> >> +			length = (b->memory == V4L2_MEMORY_USERPTR ||
> >> +				b->memory == V4L2_MEMORY_DMABUF)
> >> +				? b->m.planes[plane].length
> >> +				: vb->planes[plane].length;
> >> +			bytesused = b->m.planes[plane].bytesused
> >> +				? b->m.planes[plane].bytesused : length;
> >> +
> >> +			if (b->m.planes[plane].bytesused > length)
> >> +				return -EINVAL;
> >> +
> >> +			if (b->m.planes[plane].data_offset > 0 &&
> >> +				b->m.planes[plane].data_offset >= bytesused)
> >> +				return -EINVAL;
> >> +		}
> >> +	} else {
> >> +		length = (b->memory == V4L2_MEMORY_USERPTR)
> >> +			? b->length : vb->planes[0].length;
> >> +
> >> +		if (b->bytesused > length)
> >> +			return -EINVAL;
> >> +	}
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +/**
> >> + * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
> >> + * v4l2_buffer by the userspace. It also verifies that struct
> >> + * v4l2_buffer has a valid number of planes.
> >> + */
> >> +static int __fill_vb2_buffer(struct vb2_buffer *vb, void *pb,
> >> +				struct vb2_plane *planes)
> >> +{
> >> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
> >> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >> +	unsigned int plane;
> >> +	int ret;
> >> +
> >> +	ret = __verify_length(vb, b);
> >> +	if (ret < 0) {
> >> +		dprintk(1, "plane parameters verification failed: %d\n", ret);
> >> +		return ret;
> >> +	}
> >> +	vb->state = VB2_BUF_STATE_PREPARING;
> >> +	vbuf->timestamp.tv_sec = 0;
> >> +	vbuf->timestamp.tv_usec = 0;
> >> +	vbuf->sequence = 0;
> >> +
> >> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> >> +		if (b->memory == V4L2_MEMORY_USERPTR) {
> >> +			for (plane = 0; plane < vb->num_planes; ++plane) {
> >> +				planes[plane].m.userptr =
> >> +					b->m.planes[plane].m.userptr;
> >> +				planes[plane].length =
> >> +					b->m.planes[plane].length;
> >> +			}
> >> +		}
> >> +		if (b->memory == V4L2_MEMORY_DMABUF) {
> >> +			for (plane = 0; plane < vb->num_planes; ++plane) {
> >> +				planes[plane].m.fd =
> >> +					b->m.planes[plane].m.fd;
> >> +				planes[plane].length =
> >> +					b->m.planes[plane].length;
> >> +			}
> >> +		}
> >> +
> >> +		/* Fill in driver-provided information for OUTPUT types */
> >> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> +			/*
> >> +			 * Will have to go up to b->length when API starts
> >> +			 * accepting variable number of planes.
> >> +			 *
> >> +			 * If bytesused == 0 for the output buffer, then fall
> >> +			 * back to the full buffer size. In that case
> >> +			 * userspace clearly never bothered to set it and
> >> +			 * it's a safe assumption that they really meant to
> >> +			 * use the full plane sizes.
> >> +			 *
> >> +			 * Some drivers, e.g. old codec drivers, use bytesused == 0
> >> +			 * as a way to indicate that streaming is finished.
> >> +			 * In that case, the driver should use the
> >> +			 * allow_zero_bytesused flag to keep old userspace
> >> +			 * applications working.
> >> +			 */
> >> +			for (plane = 0; plane < vb->num_planes; ++plane) {
> >> +				struct vb2_plane *pdst = &planes[plane];
> >> +				struct v4l2_plane *psrc = &b->m.planes[plane];
> >> +
> >> +				if (psrc->bytesused == 0)
> >> +					vb2_warn_zero_bytesused(vb);
> >> +
> >> +				if (vb->vb2_queue->allow_zero_bytesused)
> >> +					pdst->bytesused = psrc->bytesused;
> >> +				else
> >> +					pdst->bytesused = psrc->bytesused ?
> >> +						psrc->bytesused : pdst->length;
> >> +				pdst->data_offset = psrc->data_offset;
> >> +			}
> >> +		}
> >> +	} else {
> >> +		/*
> >> +		 * Single-planar buffers do not use planes array,
> >> +		 * so fill in relevant v4l2_buffer struct fields instead.
> >> +		 * In videobuf we use our internal V4l2_planes struct for
> >> +		 * single-planar buffers as well, for simplicity.
> >> +		 *
> >> +		 * If bytesused == 0 for the output buffer, then fall back
> >> +		 * to the full buffer size as that's a sensible default.
> >> +		 *
> >> +		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
> >> +		 * a way to indicate that streaming is finished. In that case,
> >> +		 * the driver should use the allow_zero_bytesused flag to keep
> >> +		 * old userspace applications working.
> >> +		 */
> >> +		if (b->memory == V4L2_MEMORY_USERPTR) {
> >> +			planes[0].m.userptr = b->m.userptr;
> >> +			planes[0].length = b->length;
> >> +		}
> >> +
> >> +		if (b->memory == V4L2_MEMORY_DMABUF) {
> >> +			planes[0].m.fd = b->m.fd;
> >> +			planes[0].length = b->length;
> >> +		}
> >> +
> >> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> +			if (b->bytesused == 0)
> >> +				vb2_warn_zero_bytesused(vb);
> >> +
> >> +			if (vb->vb2_queue->allow_zero_bytesused)
> >> +				planes[0].bytesused = b->bytesused;
> >> +			else
> >> +				planes[0].bytesused = b->bytesused ?
> >> +					b->bytesused : planes[0].length;
> >> +		} else
> >> +			planes[0].bytesused = 0;
> >> +
> >> +	}
> >> +
> >> +	/* Zero flags that the vb2 core handles */
> >> +	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> >> +	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> >> +			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
> >> +			!V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> +		/*
> >> +		 * Non-COPY timestamps and non-OUTPUT queues will get
> >> +		 * their timestamp and timestamp source flags from the
> >> +		 * queue.
> >> +		 */
> >> +		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> >> +	}
> >> +
> >> +	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> +		/*
> >> +		 * For output buffers mask out the timecode flag:
> >> +		 * this will be handled later in vb2_internal_qbuf().
> >> +		 * The 'field' is valid metadata for this output buffer
> >> +		 * and so that needs to be copied here.
> >> +		 */
> >> +		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
> >> +		vbuf->field = b->field;
> >> +	} else {
> >> +		/* Zero any output buffer flags as this is a capture buffer */
> >> +		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
> >> +	}
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static int __fill_vb2_timestamp(struct vb2_buffer *vb, void *pb)
> >> +{
> >> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
> >> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >> +	struct vb2_queue *q = vb->vb2_queue;
> >> +
> >> +	/*
> >> +	 * For output buffers copy the timestamp if needed,
> >> +	 * and the timecode field and flag if needed.
> >> +	 */
> >> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> >> +			V4L2_BUF_FLAG_TIMESTAMP_COPY)
> >> +		vbuf->timestamp = b->timestamp;
> >> +	vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> >> +	if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> >> +		vbuf->timecode = b->timecode;
> >> +
> >> +	return 0;
> >> +};
> >> +
> >> +static int __is_last(struct vb2_buffer *vb)
> >> +{
> >> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >> +
> >> +	return (vbuf->flags & V4L2_BUF_FLAG_LAST);
> >> +}
> >> +
> >> +const struct vb2_buf_ops v4l2_buf_ops = {
> >> +	.fill_user_buffer	= __fill_v4l2_buffer,
> >> +	.fill_vb2_buffer	= __fill_vb2_buffer,
> >> +	.fill_vb2_timestamp	= __fill_vb2_timestamp,
> >> +	.is_last		= __is_last,
> >> +};
> >> +
> >> +/**
> >> + * vb2_querybuf() - query video buffer information
> >> + * @q:		videobuf queue
> >> + * @b:		buffer struct passed from userspace to vidioc_querybuf handler
> >> + *		in driver
> >> + *
> >> + * Should be called from vidioc_querybuf ioctl handler in driver.
> >> + * This function will verify the passed v4l2_buffer structure and fill the
> >> + * relevant information for the userspace.
> >> + *
> >> + * The return values from this function are intended to be directly returned
> >> + * from vidioc_querybuf handler in driver.
> >> + */
> >> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >> +{
> >> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
> >> +			b->length, b->m.planes, "querybuf");
> >> +
> >> +	return ret ? ret : vb2_core_querybuf(q, b->index, b);
> >> +}
> >> +EXPORT_SYMBOL(vb2_querybuf);
> >> +
> >> +/**
> >> + * vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies
> >> + * the memory and type values.
> >> + * @q:		videobuf2 queue
> >> + * @req:	struct passed from userspace to vidioc_reqbufs handler
> >> + *		in driver
> >> + */
> >> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> >> +{
> >> +	int ret = vb2_verify_memory_type(q, req->memory, req->type);
> >> +
> >> +	if (ret)
> >> +		return ret;
> >> +	if (vb2_fileio_is_active(q)) {
> >> +		dprintk(1, "file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +
> >> +	return vb2_core_reqbufs(q, req->memory, &req->count);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_reqbufs);
> >> +
> >> +/**
> >> + * vb2_create_bufs() - Wrapper for vb2_core_create_bufs() that also verifies
> >> + * the memory and type values.
> >> + * @q:		videobuf2 queue
> >> + * @create:	creation parameters, passed from userspace to vidioc_create_bufs
> >> + *		handler in driver
> >> + */
> >> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
> >> +{
> >> +	int ret = vb2_verify_memory_type(q, create->memory, create->format.type);
> >> +
> >> +	if (ret)
> >> +		return ret;
> >> +	if (create->count && vb2_fileio_is_active(q)) {
> >> +		dprintk(1, "file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +	return vb2_core_create_bufs(q, create->memory, &create->count, &create->format);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_create_bufs);
> >> +
> >> +/**
> >> + * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
> >> + * @q:		videobuf2 queue
> >> + * @b:		buffer structure passed from userspace to vidioc_prepare_buf
> >> + *		handler in driver
> >> + *
> >> + * Should be called from vidioc_prepare_buf ioctl handler of a driver.
> >> + * This function:
> >> + * 1) verifies the passed buffer,
> >> + * 2) calls buf_prepare callback in the driver (if provided), in which
> >> + *    driver-specific buffer initialization can be performed,
> >> + *
> >> + * The return values from this function are intended to be directly returned
> >> + * from vidioc_prepare_buf handler in driver.
> >> + */
> >> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
> >> +{
> >> +	int ret;
> >> +
> >> +	if (vb2_fileio_is_active(q)) {
> >> +		dprintk(1, "file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +
> >> +	ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
> >> +			b->length, b->m.planes, "prepare_buf");
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
> >> +		/*
> >> +		 * If the format's field is ALTERNATE, then the buffer's field
> >> +		 * should be either TOP or BOTTOM, not ALTERNATE since that
> >> +		 * makes no sense. The driver has to know whether the
> >> +		 * buffer represents a top or a bottom field in order to
> >> +		 * program any DMA correctly. Using ALTERNATE is wrong, since
> >> +		 * that just says that it is either a top or a bottom field,
> >> +		 * but not which of the two it is.
> >> +		 */
> >> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
> >> +				"for an output buffer\n");
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	return vb2_core_prepare_buf(q, b->index, b);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_prepare_buf);
> >> +
> >> +static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >> +{
> >> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
> >> +			b->length, b->m.planes, "qbuf");
> >> +	struct vb2_buffer *vb;
> >> +
> >> +	if (ret)
> >> +		return ret;
> >> +
> >> +	vb = q->bufs[b->index];
> >> +
> >> +	if (vb->state == VB2_BUF_STATE_DEQUEUED
> >> +			&& b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
> >> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
> >> +				"for an output buffer\n");
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	return ret ? ret : vb2_core_qbuf(q, b->index, b);
> >> +}
> >> +
> >> +/**
> >> + * vb2_qbuf() - Queue a buffer from userspace
> >> + * @q:		videobuf2 queue
> >> + * @b:		buffer structure passed from userspace to vidioc_qbuf handler
> >> + *		in driver
> >> + *
> >> + * Should be called from vidioc_qbuf ioctl handler of a driver.
> >> + * This function:
> >> + * 1) verifies the passed buffer,
> >> + * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
> >> + *    which driver-specific buffer initialization can be performed,
> >> + * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
> >> + *    callback for processing.
> >> + *
> >> + * The return values from this function are intended to be directly returned
> >> + * from vidioc_qbuf handler in driver.
> >> + */
> >> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >> +{
> >> +	if (vb2_fileio_is_active(q)) {
> >> +		dprintk(1, "file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +
> >> +	return vb2_internal_qbuf(q, b);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_qbuf);
> >> +
> >> +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> >> +			bool nonblocking)
> >> +{
> >> +	if (b->type != q->type) {
> >> +		dprintk(1, "invalid buffer type\n");
> >> +		return -EINVAL;
> >> +	}
> >> +	return vb2_core_dqbuf(q, b, nonblocking);
> >> +}
> >> +
> >> +/**
> >> + * vb2_dqbuf() - Dequeue a buffer to the userspace
> >> + * @q:		videobuf2 queue
> >> + * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
> >> + *		in driver
> >> + * @nonblocking: if true, this call will not sleep waiting for a buffer if no
> >> + *		 buffers ready for dequeuing are present. Normally the driver
> >> + *		 would be passing (file->f_flags & O_NONBLOCK) here
> >> + *
> >> + * Should be called from vidioc_dqbuf ioctl handler of a driver.
> >> + * This function:
> >> + * 1) verifies the passed buffer,
> >> + * 2) calls buf_finish callback in the driver (if provided), in which
> >> + *    driver can perform any additional operations that may be required before
> >> + *    returning the buffer to userspace, such as cache sync,
> >> + * 3) the buffer struct members are filled with relevant information for
> >> + *    the userspace.
> >> + *
> >> + * The return values from this function are intended to be directly returned
> >> + * from vidioc_dqbuf handler in driver.
> >> + */
> >> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
> >> +{
> >> +	if (vb2_fileio_is_active(q)) {
> >> +		dprintk(1, "file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +	return vb2_internal_dqbuf(q, b, nonblocking);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_dqbuf);
> >> +
> >> +/**
> >> + * vb2_expbuf() - Export a buffer as a file descriptor
> >> + * @q:		videobuf2 queue
> >> + * @eb:		export buffer structure passed from userspace to vidioc_expbuf
> >> + *		handler in driver
> >> + *
> >> + * The return values from this function are intended to be directly returned
> >> + * from vidioc_expbuf handler in driver.
> >> + */
> >> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
> >> +{
> >> +	if (vb2_fileio_is_active(q)) {
> >> +		dprintk(1, "file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +
> >> +	return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index,
> >> +				eb->plane, eb->flags);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_expbuf);
> >> +
> >> +static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> >> +{
> >> +	if (type != q->type) {
> >> +		dprintk(1, "invalid stream type\n");
> >> +		return -EINVAL;
> >> +	}
> >> +	return vb2_core_streamon(q);
> >> +}
> >> +
> >> +/**
> >> + * vb2_streamon - start streaming
> >> + * @q:		videobuf2 queue
> >> + * @type:	type argument passed from userspace to vidioc_streamon handler
> >> + *
> >> + * Should be called from vidioc_streamon handler of a driver.
> >> + * This function:
> >> + * 1) verifies current state
> >> + * 2) passes any previously queued buffers to the driver and starts streaming
> >> + *
> >> + * The return values from this function are intended to be directly returned
> >> + * from vidioc_streamon handler in the driver.
> >> + */
> >> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> >> +{
> >> +	if (vb2_fileio_is_active(q)) {
> >> +		dprintk(1, "file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +	return vb2_internal_streamon(q, type);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_streamon);
> >> +
> >> +static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> >> +{
> >> +	if (type != q->type) {
> >> +		dprintk(1, "invalid stream type\n");
> >> +		return -EINVAL;
> >> +	}
> >> +	return vb2_core_streamoff(q);
> >> +}
> >> +
> >> +/**
> >> + * vb2_streamoff - stop streaming
> >> + * @q:		videobuf2 queue
> >> + * @type:	type argument passed from userspace to vidioc_streamoff handler
> >> + *
> >> + * Should be called from vidioc_streamoff handler of a driver.
> >> + * This function:
> >> + * 1) verifies current state,
> >> + * 2) stop streaming and dequeues any queued buffers, including those previously
> >> + *    passed to the driver (after waiting for the driver to finish).
> >> + *
> >> + * This call can be used for pausing playback.
> >> + * The return values from this function are intended to be directly returned
> >> + * from vidioc_streamoff handler in the driver
> >> + */
> >> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> >> +{
> >> +	if (vb2_fileio_is_active(q)) {
> >> +		dprintk(1, "file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +	return vb2_internal_streamoff(q, type);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_streamoff);
> >> +
> >> +/**
> >> + * vb2_mmap() - map video buffers into application address space
> >> + * @q:		videobuf2 queue
> >> + * @vma:	vma passed to the mmap file operation handler in the driver
> >> + *
> >> + * Should be called from mmap file operation handler of a driver.
> >> + * This function maps one plane of one of the available video buffers to
> >> + * userspace. To map whole video memory allocated on reqbufs, this function
> >> + * has to be called once per each plane per each buffer previously allocated.
> >> + *
> >> + * When the userspace application calls mmap, it passes to it an offset returned
> >> + * to it earlier by the means of vidioc_querybuf handler. That offset acts as
> >> + * a "cookie", which is then used to identify the plane to be mapped.
> >> + * This function finds a plane with a matching offset and a mapping is performed
> >> + * by the means of a provided memory operation.
> >> + *
> >> + * The return values from this function are intended to be directly returned
> >> + * from the mmap handler in driver.
> >> + */
> >> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> >> +{
> >> +	if (vb2_fileio_is_active(q)) {
> >> +		dprintk(1, "mmap: file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +
> >> +	return vb2_core_mmap(q, vma);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_mmap);
> >> +
> >> +static int __vb2_init_fileio(struct vb2_queue *q, int read);
> >> +static int __vb2_cleanup_fileio(struct vb2_queue *q);
> >> +
> >> +/**
> >> + * vb2_poll() - implements poll userspace operation
> >> + * @q:		videobuf2 queue
> >> + * @file:	file argument passed to the poll file operation handler
> >> + * @wait:	wait argument passed to the poll file operation handler
> >> + *
> >> + * This function implements poll file operation handler for a driver.
> >> + * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
> >> + * be informed that the file descriptor of a video device is available for
> >> + * reading.
> >> + * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
> >> + * will be reported as available for writing.
> >> + *
> >> + * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
> >> + * pending events.
> >> + *
> >> + * The return values from this function are intended to be directly returned
> >> + * from poll handler in driver.
> >> + */
> >> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> >> +{
> >> +	struct video_device *vfd = video_devdata(file);
> >> +	unsigned long req_events = poll_requested_events(wait);
> >> +	struct vb2_buffer *vb = NULL;
> >> +	unsigned int res = 0;
> >> +	unsigned long flags;
> >> +
> >> +	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> >> +		struct v4l2_fh *fh = file->private_data;
> >> +
> >> +		if (v4l2_event_pending(fh))
> >> +			res = POLLPRI;
> >> +		else if (req_events & POLLPRI)
> >> +			poll_wait(file, &fh->wait, wait);
> >> +	}
> >> +
> >> +	if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
> >> +		return res;
> >> +	if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
> >> +		return res;
> >> +
> >> +	/*
> >> +	 * Start file I/O emulator only if streaming API has not been used yet.
> >> +	 */
> >> +	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
> >> +		if (!q->is_output && (q->io_modes & VB2_READ) &&
> >> +				(req_events & (POLLIN | POLLRDNORM))) {
> >> +			if (__vb2_init_fileio(q, 1))
> >> +				return res | POLLERR;
> >> +		}
> >> +		if (q->is_output && (q->io_modes & VB2_WRITE) &&
> >> +				(req_events & (POLLOUT | POLLWRNORM))) {
> >> +			if (__vb2_init_fileio(q, 0))
> >> +				return res | POLLERR;
> >> +			/*
> >> +			 * Write to OUTPUT queue can be done immediately.
> >> +			 */
> >> +			return res | POLLOUT | POLLWRNORM;
> >> +		}
> >> +	}
> >> +
> >> +	/*
> >> +	 * There is nothing to wait for if the queue isn't streaming, or if the
> >> +	 * error flag is set.
> >> +	 */
> >> +	if (!vb2_is_streaming(q) || q->error)
> >> +		return res | POLLERR;
> >> +	/*
> >> +	 * For compatibility with vb1: if QBUF hasn't been called yet, then
> >> +	 * return POLLERR as well. This only affects capture queues, output
> >> +	 * queues will always initialize waiting_for_buffers to false.
> >> +	 */
> >> +	if (q->waiting_for_buffers)
> >> +		return res | POLLERR;
> >> +
> >> +	/*
> >> +	 * For output streams you can write as long as there are fewer buffers
> >> +	 * queued than there are buffers available.
> >> +	 */
> >> +	if (q->is_output && q->queued_count < q->num_buffers)
> >> +		return res | POLLOUT | POLLWRNORM;
> >> +
> >> +	if (list_empty(&q->done_list)) {
> >> +		/*
> >> +		 * If the last buffer was dequeued from a capture queue,
> >> +		 * return immediately. DQBUF will return -EPIPE.
> >> +		 */
> >> +		if (q->last_buffer_dequeued)
> >> +			return res | POLLIN | POLLRDNORM;
> >> +
> >> +		poll_wait(file, &q->done_wq, wait);
> >> +	}
> >> +
> >> +	/*
> >> +	 * Take first buffer available for dequeuing.
> >> +	 */
> >> +	spin_lock_irqsave(&q->done_lock, flags);
> >> +	if (!list_empty(&q->done_list))
> >> +		vb = list_first_entry(&q->done_list, struct vb2_buffer,
> >> +					done_entry);
> >> +	spin_unlock_irqrestore(&q->done_lock, flags);
> >> +
> >> +	if (vb && (vb->state == VB2_BUF_STATE_DONE
> >> +			|| vb->state == VB2_BUF_STATE_ERROR)) {
> >> +		return (q->is_output) ?
> >> +				res | POLLOUT | POLLWRNORM :
> >> +				res | POLLIN | POLLRDNORM;
> >> +	}
> >> +	return res;
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_poll);
> >> +
> >> +/**
> >> + * vb2_queue_init() - initialize a videobuf2 queue
> >> + * @q:		videobuf2 queue; this structure should be allocated in driver
> >> + *
> >> + * The vb2_queue structure should be allocated by the driver. The driver is
> >> + * responsible of clearing it's content and setting initial values for some
> >> + * required entries before calling this function.
> >> + * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
> >> + * to the struct vb2_queue description in include/media/videobuf2-core.h
> >> + * for more information.
> >> + */
> >> +int vb2_queue_init(struct vb2_queue *q)
> >> +{
> >> +	if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
> >> +		|| WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
> >> +		|| WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
> >> +		return -EINVAL;
> >> +	/*
> >> +	 * Sanity check
> >> +	 */
> >> +	if (WARN_ON(!q)	|| WARN_ON(!q->type))
> >> +		return -EINVAL;
> >> +
> >> +	if (WARN_ON(q->timestamp_flags &
> >> +		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> >> +		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
> >> +		return -EINVAL;
> >> +
> >> +	/* Warn that the driver should choose an appropriate timestamp type */
> >> +	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> >> +		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
> >> +
> >> +	if (q->buf_struct_size == 0)
> >> +		q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
> >> +
> >> +	q->buf_ops = &v4l2_buf_ops;
> >> +	q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> >> +	q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
> >> +
> >> +	return vb2_core_queue_init(q);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_queue_init);
> >> +
> >> +/**
> >> + * vb2_queue_release() - stop streaming, release the queue and free memory
> >> + * @q:		videobuf2 queue
> >> + *
> >> + * This function stops streaming and performs necessary clean ups, including
> >> + * freeing video buffer memory. The driver is responsible for freeing
> >> + * the vb2_queue structure itself.
> >> + */
> >> +void vb2_queue_release(struct vb2_queue *q)
> >> +{
> >> +	__vb2_cleanup_fileio(q);
> >> +	vb2_core_queue_release(q);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_queue_release);
> >> +
> >> +/**
> >> + * struct vb2_fileio_buf - buffer context used by file io emulator
> >> + *
> >> + * vb2 provides a compatibility layer and emulator of file io (read and
> >> + * write) calls on top of streaming API. This structure is used for
> >> + * tracking context related to the buffers.
> >> + */
> >> +struct vb2_fileio_buf {
> >> +	void *vaddr;
> >> +	unsigned int size;
> >> +	unsigned int pos;
> >> +	unsigned int queued:1;
> >> +};
> >> +
> >> +/**
> >> + * struct vb2_fileio_data - queue context used by file io emulator
> >> + *
> >> + * @cur_index:	the index of the buffer currently being read from or
> >> + *		written to. If equal to q->num_buffers then a new buffer
> >> + *		must be dequeued.
> >> + * @initial_index: in the read() case all buffers are queued up immediately
> >> + *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
> >> + *		buffers. However, in the write() case no buffers are initially
> >> + *		queued, instead whenever a buffer is full it is queued up by
> >> + *		__vb2_perform_fileio(). Only once all available buffers have
> >> + *		been queued up will __vb2_perform_fileio() start to dequeue
> >> + *		buffers. This means that initially __vb2_perform_fileio()
> >> + *		needs to know what buffer index to use when it is queuing up
> >> + *		the buffers for the first time. That initial index is stored
> >> + *		in this field. Once it is equal to q->num_buffers all
> >> + *		available buffers have been queued and __vb2_perform_fileio()
> >> + *		should start the normal dequeue/queue cycle.
> >> + *
> >> + * vb2 provides a compatibility layer and emulator of file io (read and
> >> + * write) calls on top of streaming API. For proper operation it required
> >> + * this structure to save the driver state between each call of the read
> >> + * or write function.
> >> + */
> >> +struct vb2_fileio_data {
> >> +	struct v4l2_requestbuffers req;
> >> +	struct v4l2_plane p;
> >> +	struct v4l2_buffer b;
> >> +	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
> >> +	unsigned int cur_index;
> >> +	unsigned int initial_index;
> >> +	unsigned int q_count;
> >> +	unsigned int dq_count;
> >> +	unsigned read_once:1;
> >> +	unsigned write_immediately:1;
> >> +};
> >> +
> >> +/**
> >> + * __vb2_init_fileio() - initialize file io emulator
> >> + * @q:		videobuf2 queue
> >> + * @read:	mode selector (1 means read, 0 means write)
> >> + */
> >> +static int __vb2_init_fileio(struct vb2_queue *q, int read)
> >> +{
> >> +	struct vb2_fileio_data *fileio;
> >> +	int i, ret;
> >> +	unsigned int count = 0;
> >> +
> >> +	/*
> >> +	 * Sanity check
> >> +	 */
> >> +	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
> >> +			(!read && !(q->io_modes & VB2_WRITE))))
> >> +		return -EINVAL;
> >> +
> >> +	/*
> >> +	 * Check if device supports mapping buffers to kernel virtual space.
> >> +	 */
> >> +	if (!q->mem_ops->vaddr)
> >> +		return -EBUSY;
> >> +
> >> +	/*
> >> +	 * Check if streaming api has not been already activated.
> >> +	 */
> >> +	if (q->streaming || q->num_buffers > 0)
> >> +		return -EBUSY;
> >> +
> >> +	/*
> >> +	 * Start with count 1, driver can increase it in queue_setup()
> >> +	 */
> >> +	count = 1;
> >> +
> >> +	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, "
> >> +		"write_immediately %d\n",
> >> +		(read) ? "read" : "write", count, q->fileio_read_once,
> >> +		q->fileio_write_immediately);
> >> +
> >> +	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
> >> +	if (fileio == NULL)
> >> +		return -ENOMEM;
> >> +
> >> +	fileio->read_once = q->fileio_read_once;
> >> +	fileio->write_immediately = q->fileio_write_immediately;
> >> +
> >> +	/*
> >> +	 * Request buffers and use MMAP type to force driver
> >> +	 * to allocate buffers by itself.
> >> +	 */
> >> +	fileio->req.count = count;
> >> +	fileio->req.memory = V4L2_MEMORY_MMAP;
> >> +	fileio->req.type = q->type;
> >> +	q->fileio = fileio;
> >> +	ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
> >> +	if (ret)
> >> +		goto err_kfree;
> >> +
> >> +	/*
> >> +	 * Check if plane_count is correct
> >> +	 * (multiplane buffers are not supported).
> >> +	 */
> >> +	if (q->bufs[0]->num_planes != 1) {
> >> +		ret = -EBUSY;
> >> +		goto err_reqbufs;
> >> +	}
> >> +
> >> +	/*
> >> +	 * Get kernel address of each buffer.
> >> +	 */
> >> +	for (i = 0; i < q->num_buffers; i++) {
> >> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
> >> +		if (fileio->bufs[i].vaddr == NULL) {
> >> +			ret = -EINVAL;
> >> +			goto err_reqbufs;
> >> +		}
> >> +		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
> >> +	}
> >> +
> >> +	/*
> >> +	 * Read mode requires pre queuing of all buffers.
> >> +	 */
> >> +	if (read) {
> >> +		bool is_multiplanar = q->is_multiplanar;
> >> +
> >> +		/*
> >> +		 * Queue all buffers.
> >> +		 */
> >> +		for (i = 0; i < q->num_buffers; i++) {
> >> +			struct v4l2_buffer *b = &fileio->b;
> >> +
> >> +			memset(b, 0, sizeof(*b));
> >> +			b->type = q->type;
> >> +			if (is_multiplanar) {
> >> +				memset(&fileio->p, 0, sizeof(fileio->p));
> >> +				b->m.planes = &fileio->p;
> >> +				b->length = 1;
> >> +			}
> >> +			b->memory = q->memory;
> >> +			b->index = i;
> >> +			ret = vb2_internal_qbuf(q, b);
> >> +			if (ret)
> >> +				goto err_reqbufs;
> >> +			fileio->bufs[i].queued = 1;
> >> +		}
> >> +		/*
> >> +		 * All buffers have been queued, so mark that by setting
> >> +		 * initial_index to q->num_buffers
> >> +		 */
> >> +		fileio->initial_index = q->num_buffers;
> >> +		fileio->cur_index = q->num_buffers;
> >> +	}
> >> +
> >> +	/*
> >> +	 * Start streaming.
> >> +	 */
> >> +	ret = vb2_internal_streamon(q, q->type);
> >> +	if (ret)
> >> +		goto err_reqbufs;
> >> +
> >> +	return ret;
> >> +
> >> +err_reqbufs:
> >> +	fileio->req.count = 0;
> >> +	vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
> >> +
> >> +err_kfree:
> >> +	q->fileio = NULL;
> >> +	kfree(fileio);
> >> +	return ret;
> >> +}
> >> +
> >> +/**
> >> + * __vb2_cleanup_fileio() - free resourced used by file io emulator
> >> + * @q:		videobuf2 queue
> >> + */
> >> +static int __vb2_cleanup_fileio(struct vb2_queue *q)
> >> +{
> >> +	struct vb2_fileio_data *fileio = q->fileio;
> >> +
> >> +	if (fileio) {
> >> +		vb2_internal_streamoff(q, q->type);
> >> +		q->fileio = NULL;
> >> +		fileio->req.count = 0;
> >> +		vb2_reqbufs(q, &fileio->req);
> >> +		kfree(fileio);
> >> +		dprintk(3, "file io emulator closed\n");
> >> +	}
> >> +	return 0;
> >> +}
> >> +
> >> +/**
> >> + * __vb2_perform_fileio() - perform a single file io (read or write) operation
> >> + * @q:		videobuf2 queue
> >> + * @data:	pointed to target userspace buffer
> >> + * @count:	number of bytes to read or write
> >> + * @ppos:	file handle position tracking pointer
> >> + * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
> >> + * @read:	access mode selector (1 means read, 0 means write)
> >> + */
> >> +static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data,
> >> +		size_t count, loff_t *ppos, int nonblock, int read)
> >> +{
> >> +	struct vb2_fileio_data *fileio;
> >> +	struct vb2_fileio_buf *buf;
> >> +	bool is_multiplanar = q->is_multiplanar;
> >> +	/*
> >> +	 * When using write() to write data to an output video node the vb2 core
> >> +	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
> >> +	 * else is able to provide this information with the write() operation.
> >> +	 */
> >> +	bool set_timestamp = !read &&
> >> +		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> >> +		V4L2_BUF_FLAG_TIMESTAMP_COPY;
> >> +	int ret, index;
> >> +
> >> +	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
> >> +		read ? "read" : "write", (long)*ppos, count,
> >> +		nonblock ? "non" : "");
> >> +
> >> +	if (!data)
> >> +		return -EINVAL;
> >> +
> >> +	/*
> >> +	 * Initialize emulator on first call.
> >> +	 */
> >> +	if (!vb2_fileio_is_active(q)) {
> >> +		ret = __vb2_init_fileio(q, read);
> >> +		dprintk(3, "vb2_init_fileio result: %d\n", ret);
> >> +		if (ret)
> >> +			return ret;
> >> +	}
> >> +	fileio = q->fileio;
> >> +
> >> +	/*
> >> +	 * Check if we need to dequeue the buffer.
> >> +	 */
> >> +	index = fileio->cur_index;
> >> +	if (index >= q->num_buffers) {
> >> +		/*
> >> +		 * Call vb2_dqbuf to get buffer back.
> >> +		 */
> >> +		memset(&fileio->b, 0, sizeof(fileio->b));
> >> +		fileio->b.type = q->type;
> >> +		fileio->b.memory = q->memory;
> >> +		if (is_multiplanar) {
> >> +			memset(&fileio->p, 0, sizeof(fileio->p));
> >> +			fileio->b.m.planes = &fileio->p;
> >> +			fileio->b.length = 1;
> >> +		}
> >> +		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
> >> +		dprintk(5, "vb2_dqbuf result: %d\n", ret);
> >> +		if (ret)
> >> +			return ret;
> >> +		fileio->dq_count += 1;
> >> +
> >> +		fileio->cur_index = index = fileio->b.index;
> >> +		buf = &fileio->bufs[index];
> >> +
> >> +		/*
> >> +		 * Get number of bytes filled by the driver
> >> +		 */
> >> +		buf->pos = 0;
> >> +		buf->queued = 0;
> >> +		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> >> +				 : vb2_plane_size(q->bufs[index], 0);
> >> +
> >> +		/*
> >> +		 * Compensate for data_offset on read
> >> +		 * in the multiplanar case.
> >> +		 */
> >> +		if (is_multiplanar && read &&
> >> +			fileio->b.m.planes[0].data_offset < buf->size) {
> >> +			buf->pos = fileio->b.m.planes[0].data_offset;
> >> +			buf->size -= buf->pos;
> >> +		}
> >> +	} else {
> >> +		buf = &fileio->bufs[index];
> >> +	}
> >> +
> >> +	/*
> >> +	 * Limit count on last few bytes of the buffer.
> >> +	 */
> >> +	if (buf->pos + count > buf->size) {
> >> +		count = buf->size - buf->pos;
> >> +		dprintk(5, "reducing read count: %zd\n", count);
> >> +	}
> >> +
> >> +	/*
> >> +	 * Transfer data to userspace.
> >> +	 */
> >> +	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
> >> +		count, index, buf->pos);
> >> +	if (read)
> >> +		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
> >> +	else
> >> +		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
> >> +	if (ret) {
> >> +		dprintk(3, "error copying data\n");
> >> +		return -EFAULT;
> >> +	}
> >> +
> >> +	/*
> >> +	 * Update counters.
> >> +	 */
> >> +	buf->pos += count;
> >> +	*ppos += count;
> >> +
> >> +	/*
> >> +	 * Queue next buffer if required.
> >> +	 */
> >> +	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
> >> +		/*
> >> +		 * Check if this is the last buffer to read.
> >> +		 */
> >> +		if (read && fileio->read_once && fileio->dq_count == 1) {
> >> +			dprintk(3, "read limit reached\n");
> >> +			return __vb2_cleanup_fileio(q);
> >> +		}
> >> +
> >> +		/*
> >> +		 * Call vb2_qbuf and give buffer to the driver.
> >> +		 */
> >> +		memset(&fileio->b, 0, sizeof(fileio->b));
> >> +		fileio->b.type = q->type;
> >> +		fileio->b.memory = q->memory;
> >> +		fileio->b.index = index;
> >> +		fileio->b.bytesused = buf->pos;
> >> +		if (is_multiplanar) {
> >> +			memset(&fileio->p, 0, sizeof(fileio->p));
> >> +			fileio->p.bytesused = buf->pos;
> >> +			fileio->b.m.planes = &fileio->p;
> >> +			fileio->b.length = 1;
> >> +		}
> >> +		if (set_timestamp)
> >> +			v4l2_get_timestamp(&fileio->b.timestamp);
> >> +		ret = vb2_internal_qbuf(q, &fileio->b);
> >> +		dprintk(5, "vb2_dbuf result: %d\n", ret);
> >> +		if (ret)
> >> +			return ret;
> >> +
> >> +		/*
> >> +		 * Buffer has been queued, update the status
> >> +		 */
> >> +		buf->pos = 0;
> >> +		buf->queued = 1;
> >> +		buf->size = vb2_plane_size(q->bufs[index], 0);
> >> +		fileio->q_count += 1;
> >> +		/*
> >> +		 * If we are queuing up buffers for the first time, then
> >> +		 * increase initial_index by one.
> >> +		 */
> >> +		if (fileio->initial_index < q->num_buffers)
> >> +			fileio->initial_index++;
> >> +		/*
> >> +		 * The next buffer to use is either a buffer that's going to be
> >> +		 * queued for the first time (initial_index < q->num_buffers)
> >> +		 * or it is equal to q->num_buffers, meaning that the next
> >> +		 * time we need to dequeue a buffer since we've now queued up
> >> +		 * all the 'first time' buffers.
> >> +		 */
> >> +		fileio->cur_index = fileio->initial_index;
> >> +	}
> >> +
> >> +	/*
> >> +	 * Return proper number of bytes processed.
> >> +	 */
> >> +	if (ret == 0)
> >> +		ret = count;
> >> +	return ret;
> >> +}
> >> +
> >> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> >> +		loff_t *ppos, int nonblocking)
> >> +{
> >> +	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_read);
> >> +
> >> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> >> +		loff_t *ppos, int nonblocking)
> >> +{
> >> +	return __vb2_perform_fileio(q, (char __user *) data, count,
> >> +							ppos, nonblocking, 0);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_write);
> >> +
> >> +struct vb2_threadio_data {
> >> +	struct task_struct *thread;
> >> +	vb2_thread_fnc fnc;
> >> +	void *priv;
> >> +	bool stop;
> >> +};
> >> +
> >> +static int vb2_thread(void *data)
> >> +{
> >> +	struct vb2_queue *q = data;
> >> +	struct vb2_threadio_data *threadio = q->threadio;
> >> +	struct vb2_fileio_data *fileio = q->fileio;
> >> +	bool set_timestamp = false;
> >> +	int prequeue = 0;
> >> +	int index = 0;
> >> +	int ret = 0;
> >> +
> >> +	if (q->is_output) {
> >> +		prequeue = q->num_buffers;
> >> +		set_timestamp =
> >> +			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> >> +			V4L2_BUF_FLAG_TIMESTAMP_COPY;
> >> +	}
> >> +
> >> +	set_freezable();
> >> +
> >> +	for (;;) {
> >> +		struct vb2_buffer *vb;
> >> +
> >> +		/*
> >> +		 * Call vb2_dqbuf to get buffer back.
> >> +		 */
> >> +		memset(&fileio->b, 0, sizeof(fileio->b));
> >> +		fileio->b.type = q->type;
> >> +		fileio->b.memory = q->memory;
> >> +		if (prequeue) {
> >> +			fileio->b.index = index++;
> >> +			prequeue--;
> >> +		} else {
> >> +			call_void_qop(q, wait_finish, q);
> >> +			if (!threadio->stop)
> >> +				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
> >> +			call_void_qop(q, wait_prepare, q);
> >> +			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
> >> +		}
> >> +		if (ret || threadio->stop)
> >> +			break;
> >> +		try_to_freeze();
> >> +
> >> +		vb = q->bufs[fileio->b.index];
> >> +		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
> >> +			if (threadio->fnc(vb, threadio->priv))
> >> +				break;
> >> +		call_void_qop(q, wait_finish, q);
> >> +		if (set_timestamp)
> >> +			v4l2_get_timestamp(&fileio->b.timestamp);
> >> +		if (!threadio->stop)
> >> +			ret = vb2_internal_qbuf(q, &fileio->b);
> >> +		call_void_qop(q, wait_prepare, q);
> >> +		if (ret || threadio->stop)
> >> +			break;
> >> +	}
> >> +
> >> +	/* Hmm, linux becomes *very* unhappy without this ... */
> >> +	while (!kthread_should_stop()) {
> >> +		set_current_state(TASK_INTERRUPTIBLE);
> >> +		schedule();
> >> +	}
> >> +	return 0;
> >> +}
> >> +
> >> +/*
> >> + * This function should not be used for anything else but the videobuf2-dvb
> >> + * support. If you think you have another good use-case for this, then please
> >> + * contact the linux-media mailinglist first.
> >> + */
> >> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> >> +			const char *thread_name)
> >> +{
> >> +	struct vb2_threadio_data *threadio;
> >> +	int ret = 0;
> >> +
> >> +	if (q->threadio)
> >> +		return -EBUSY;
> >> +	if (vb2_is_busy(q))
> >> +		return -EBUSY;
> >> +	if (WARN_ON(q->fileio))
> >> +		return -EBUSY;
> >> +
> >> +	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
> >> +	if (threadio == NULL)
> >> +		return -ENOMEM;
> >> +	threadio->fnc = fnc;
> >> +	threadio->priv = priv;
> >> +
> >> +	ret = __vb2_init_fileio(q, !q->is_output);
> >> +	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
> >> +	if (ret)
> >> +		goto nomem;
> >> +	q->threadio = threadio;
> >> +	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
> >> +	if (IS_ERR(threadio->thread)) {
> >> +		ret = PTR_ERR(threadio->thread);
> >> +		threadio->thread = NULL;
> >> +		goto nothread;
> >> +	}
> >> +	return 0;
> >> +
> >> +nothread:
> >> +	__vb2_cleanup_fileio(q);
> >> +nomem:
> >> +	kfree(threadio);
> >> +	return ret;
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_thread_start);
> >> +
> >> +int vb2_thread_stop(struct vb2_queue *q)
> >> +{
> >> +	struct vb2_threadio_data *threadio = q->threadio;
> >> +	int err;
> >> +
> >> +	if (threadio == NULL)
> >> +		return 0;
> >> +	threadio->stop = true;
> >> +	/* Wake up all pending sleeps in the thread */
> >> +	vb2_queue_error(q);
> >> +	err = kthread_stop(threadio->thread);
> >> +	__vb2_cleanup_fileio(q);
> >> +	threadio->thread = NULL;
> >> +	kfree(threadio);
> >> +	q->threadio = NULL;
> >> +	return err;
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_thread_stop);
> >> +
> >> +/*
> >> + * The following functions are not part of the vb2 core API, but are helper
> >> + * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
> >> + * and struct vb2_ops.
> >> + * They contain boilerplate code that most if not all drivers have to do
> >> + * and so they simplify the driver code.
> >> + */
> >> +
> >> +/* The queue is busy if there is a owner and you are not that owner. */
> >> +static inline
> >> +bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
> >> +{
> >> +	return vdev->queue->owner && vdev->queue->owner != file->private_data;
> >> +}
> >> +
> >> +/* vb2 ioctl helpers */
> >> +
> >> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
> >> +			  struct v4l2_requestbuffers *p)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +	int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
> >> +
> >> +	if (res)
> >> +		return res;
> >> +	if (vb2_fileio_is_active(vdev->queue))
> >> +		return -EBUSY;
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		return -EBUSY;
> >> +	res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count);
> >> +	/* If count == 0, then the owner has released all buffers and he
> >> +	   is no longer owner of the queue. Otherwise we have a new owner. */
> >> +	if (res == 0)
> >> +		vdev->queue->owner = p->count ? file->private_data : NULL;
> >> +	return res;
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
> >> +
> >> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
> >> +			  struct v4l2_create_buffers *p)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +	int res = vb2_verify_memory_type(vdev->queue,
> >> +				p->memory, p->format.type);
> >> +
> >> +	if (vb2_fileio_is_active(vdev->queue))
> >> +		return -EBUSY;
> >> +	p->index = vdev->queue->num_buffers;
> >> +	/* If count == 0, then just check if memory and type are valid.
> >> +	   Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. */
> >> +	if (p->count == 0)
> >> +		return res != -EBUSY ? res : 0;
> >> +	if (res)
> >> +		return res;
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		return -EBUSY;
> >> +	res = vb2_core_create_bufs(vdev->queue,
> >> +				p->memory, &p->count, &p->format);
> >> +	if (res == 0)
> >> +		vdev->queue->owner = file->private_data;
> >> +	return res;
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
> >> +
> >> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> >> +			  struct v4l2_buffer *p)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		return -EBUSY;
> >> +	return vb2_prepare_buf(vdev->queue, p);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
> >> +
> >> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
> >> +	return vb2_querybuf(vdev->queue, p);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
> >> +
> >> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		return -EBUSY;
> >> +	return vb2_qbuf(vdev->queue, p);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
> >> +
> >> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		return -EBUSY;
> >> +	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
> >> +
> >> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		return -EBUSY;
> >> +	return vb2_streamon(vdev->queue, i);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
> >> +
> >> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		return -EBUSY;
> >> +	return vb2_streamoff(vdev->queue, i);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
> >> +
> >> +int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		return -EBUSY;
> >> +	return vb2_expbuf(vdev->queue, p);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
> >> +
> >> +/* v4l2_file_operations helpers */
> >> +
> >> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	if (vb2_fileio_is_active(vdev->queue)) {
> >> +		dprintk(1, "mmap: file io in progress\n");
> >> +		return -EBUSY;
> >> +	}
> >> +
> >> +	return vb2_mmap(vdev->queue, vma);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_fop_mmap);
> >> +
> >> +int _vb2_fop_release(struct file *file, struct mutex *lock)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	if (lock)
> >> +		mutex_lock(lock);
> >> +	if (file->private_data == vdev->queue->owner) {
> >> +		vb2_queue_release(vdev->queue);
> >> +		vdev->queue->owner = NULL;
> >> +	}
> >> +	if (lock)
> >> +		mutex_unlock(lock);
> >> +	return v4l2_fh_release(file);
> >> +}
> >> +EXPORT_SYMBOL_GPL(_vb2_fop_release);
> >> +
> >> +int vb2_fop_release(struct file *file)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> >> +
> >> +	return _vb2_fop_release(file, lock);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_fop_release);
> >> +
> >> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> >> +		size_t count, loff_t *ppos)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> >> +	int err = -EBUSY;
> >> +
> >> +	if (!(vdev->queue->io_modes & VB2_WRITE))
> >> +		return -EINVAL;
> >> +	if (lock && mutex_lock_interruptible(lock))
> >> +		return -ERESTARTSYS;
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		goto exit;
> >> +	err = vb2_write(vdev->queue, buf, count, ppos,
> >> +			file->f_flags & O_NONBLOCK);
> >> +	if (vdev->queue->fileio)
> >> +		vdev->queue->owner = file->private_data;
> >> +exit:
> >> +	if (lock)
> >> +		mutex_unlock(lock);
> >> +	return err;
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_fop_write);
> >> +
> >> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
> >> +		size_t count, loff_t *ppos)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> >> +	int err = -EBUSY;
> >> +
> >> +	if (!(vdev->queue->io_modes & VB2_READ))
> >> +		return -EINVAL;
> >> +	if (lock && mutex_lock_interruptible(lock))
> >> +		return -ERESTARTSYS;
> >> +	if (vb2_queue_is_busy(vdev, file))
> >> +		goto exit;
> >> +	err = vb2_read(vdev->queue, buf, count, ppos,
> >> +			file->f_flags & O_NONBLOCK);
> >> +	if (vdev->queue->fileio)
> >> +		vdev->queue->owner = file->private_data;
> >> +exit:
> >> +	if (lock)
> >> +		mutex_unlock(lock);
> >> +	return err;
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_fop_read);
> >> +
> >> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +	struct vb2_queue *q = vdev->queue;
> >> +	struct mutex *lock = q->lock ? q->lock : vdev->lock;
> >> +	unsigned res;
> >> +	void *fileio;
> >> +
> >> +	/*
> >> +	 * If this helper doesn't know how to lock, then you shouldn't be using
> >> +	 * it but you should write your own.
> >> +	 */
> >> +	WARN_ON(!lock);
> >> +
> >> +	if (lock && mutex_lock_interruptible(lock))
> >> +		return POLLERR;
> >> +
> >> +	fileio = q->fileio;
> >> +
> >> +	res = vb2_poll(vdev->queue, file, wait);
> >> +
> >> +	/* If fileio was started, then we have a new queue owner. */
> >> +	if (!fileio && q->fileio)
> >> +		q->owner = file->private_data;
> >> +	if (lock)
> >> +		mutex_unlock(lock);
> >> +	return res;
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_fop_poll);
> >> +
> >> +#ifndef CONFIG_MMU
> >> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> >> +		unsigned long len, unsigned long pgoff, unsigned long flags)
> >> +{
> >> +	struct video_device *vdev = video_devdata(file);
> >> +
> >> +	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
> >> +#endif
> >> +
> >> +/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
> >> +
> >> +void vb2_ops_wait_prepare(struct vb2_queue *vq)
> >> +{
> >> +	mutex_unlock(vq->lock);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
> >> +
> >> +void vb2_ops_wait_finish(struct vb2_queue *vq)
> >> +{
> >> +	mutex_lock(vq->lock);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
> >> +
> >>   MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
> >>   MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
> >>   MODULE_LICENSE("GPL");
> >> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> >> index 09d7529..4044bed 100644
> >> --- a/include/media/videobuf2-core.h
> >> +++ b/include/media/videobuf2-core.h
> >> @@ -15,9 +15,18 @@
> >>   #include <linux/mm_types.h>
> >>   #include <linux/mutex.h>
> >>   #include <linux/poll.h>
> >> -#include <linux/videodev2.h>
> >>   #include <linux/dma-buf.h>
> >>
> >> +#define VB2_MAX_FRAME	(32)
> >> +#define VB2_MAX_PLANES	(8)
> >> +
> >> +enum vb2_memory {
> >> +	VB2_MEMORY_UNKNOWN	= 0,
> >> +	VB2_MEMORY_MMAP		= 1,
> >> +	VB2_MEMORY_USERPTR	= 2,
> >> +	VB2_MEMORY_DMABUF	= 4,
> >> +};
> >> +
> >>   struct vb2_alloc_ctx;
> >>   struct vb2_fileio_data;
> >>   struct vb2_threadio_data;
> >> @@ -198,7 +207,7 @@ struct vb2_buffer {
> >>   	unsigned int		type;
> >>   	unsigned int		memory;
> >>   	unsigned int		num_planes;
> >> -	struct vb2_plane	planes[VIDEO_MAX_PLANES];
> >> +	struct vb2_plane	planes[VB2_MAX_PLANES];
> >>
> >>   #ifdef CONFIG_VIDEO_ADV_DEBUG
> >>   	/*
> >> @@ -330,18 +339,24 @@ struct vb2_ops {
> >>   	void (*buf_queue)(struct vb2_buffer *vb);
> >>   };
> >>
> >> -struct v4l2_fh;
> >> +struct vb2_buf_ops {
> >> +	int (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
> >> +	int (*fill_vb2_buffer)(struct vb2_buffer *vb, void *pb,
> >> +				struct vb2_plane *planes);
> >> +	int (*fill_vb2_timestamp)(struct vb2_buffer *vb, void *pb);
> >> +	int (*is_last)(struct vb2_buffer *vb);
> >> +};
> >>
> >>   /**
> >>    * struct vb2_queue - a videobuf queue
> >>    *
> >> - * @type:	queue type (see V4L2_BUF_TYPE_* in linux/videodev2.h
> >> + * @type:	queue type (see VB2_BUF_TYPE_*)
> >>    * @io_modes:	supported io methods (see vb2_io_modes enum)
> >>    * @fileio_read_once:		report EOF after reading the first buffer
> >>    * @fileio_write_immediately:	queue buffer after each write() call
> >>    * @allow_zero_bytesused:	allow bytesused == 0 to be passed to the driver
> >>    * @lock:	pointer to a mutex that protects the vb2_queue struct. The
> >> - *		driver can set this to a mutex to let the v4l2 core serialize
> >> + *		driver can set this to a mutex to let the vb2 core serialize
> >>    *		the queuing ioctls. If the driver wants to handle locking
> >>    *		itself, then this should be set to NULL. This lock is not used
> >>    *		by the videobuf2 core API.
> >> @@ -351,10 +366,13 @@ struct v4l2_fh;
> >>    *		drivers to easily associate an owner filehandle with the queue.
> >>    * @ops:	driver-specific callbacks
> >>    * @mem_ops:	memory allocator specific callbacks
> >> + * @buf_ops:	callbacks to deliver buffer information
> >> + *		between user-space and kernel-space
> >>    * @drv_priv:	driver private data
> >>    * @buf_struct_size: size of the driver-specific buffer structure;
> >>    *		"0" indicates the driver doesn't want to use a custom buffer
> >> - *		structure type, so sizeof(struct vb2_buffer) will is used
> >> + *		structure type, so, sizeof(struct vb2_v4l2_buffer) will is used
> >> + *		in case of v4l2.
> >>    * @timestamp_flags: Timestamp flags; V4L2_BUF_FLAG_TIMESTAMP_* and
> >>    *		V4L2_BUF_FLAG_TSTAMP_SRC_*
> >>    * @gfp_flags:	additional gfp flags used when allocating the buffers.
> >> @@ -385,6 +403,8 @@ struct v4l2_fh;
> >>    * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
> >>    *		buffers. Only set for capture queues if qbuf has not yet been
> >>    *		called since poll() needs to return POLLERR in that situation.
> >> + * @is_multiplanar: set if buffer type is multiplanar
> >> + * @is_output:	set if buffer type is output
> >>    * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
> >>    *		last decoded buffer was already dequeued. Set for capture queues
> >>    *		when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
> >> @@ -399,10 +419,12 @@ struct vb2_queue {
> >>   	unsigned			allow_zero_bytesused:1;
> >>
> >>   	struct mutex			*lock;
> >> -	struct v4l2_fh			*owner;
> >> +	void				*owner;
> >>
> >>   	const struct vb2_ops		*ops;
> >>   	const struct vb2_mem_ops	*mem_ops;
> >> +	const struct vb2_buf_ops	*buf_ops;
> >> +
> >>   	void				*drv_priv;
> >>   	unsigned int			buf_struct_size;
> >>   	u32				timestamp_flags;
> >> @@ -412,7 +434,7 @@ struct vb2_queue {
> >>   	/* private: internal use only */
> >>   	struct mutex			mmap_lock;
> >>   	unsigned int			memory;
> >> -	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
> >> +	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
> >>   	unsigned int			num_buffers;
> >>
> >>   	struct list_head		queued_list;
> >> @@ -423,13 +445,15 @@ struct vb2_queue {
> >>   	spinlock_t			done_lock;
> >>   	wait_queue_head_t		done_wq;
> >>
> >> -	void				*alloc_ctx[VIDEO_MAX_PLANES];
> >> -	unsigned int			plane_sizes[VIDEO_MAX_PLANES];
> >> +	void				*alloc_ctx[VB2_MAX_PLANES];
> >> +	unsigned int			plane_sizes[VB2_MAX_PLANES];
> >>
> >>   	unsigned int			streaming:1;
> >>   	unsigned int			start_streaming_called:1;
> >>   	unsigned int			error:1;
> >>   	unsigned int			waiting_for_buffers:1;
> >> +	unsigned int			is_multiplanar:1;
> >> +	unsigned int			is_output:1;
> >>   	unsigned int			last_buffer_dequeued:1;
> >>
> >>   	struct vb2_fileio_data		*fileio;
> >> @@ -455,25 +479,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
> >>   void vb2_discard_done(struct vb2_queue *q);
> >>   int vb2_wait_for_all_buffers(struct vb2_queue *q);
> >>
> >> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
> >> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
> >> -
> >> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
> >> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
> >> -
> >> -int __must_check vb2_queue_init(struct vb2_queue *q);
> >> -
> >> -void vb2_queue_release(struct vb2_queue *q);
> >>   void vb2_queue_error(struct vb2_queue *q);
> >> -
> >> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
> >> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
> >> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
> >> -
> >> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
> >> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
> >> -
> >> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
> >>   #ifndef CONFIG_MMU
> >>   unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
> >>   				    unsigned long addr,
> >> @@ -481,41 +487,6 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
> >>   				    unsigned long pgoff,
> >>   				    unsigned long flags);
> >>   #endif
> >> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
> >> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> >> -		loff_t *ppos, int nonblock);
> >> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> >> -		loff_t *ppos, int nonblock);
> >> -
> >> -/*
> >> - * vb2_thread_fnc - callback function for use with vb2_thread
> >> - *
> >> - * This is called whenever a buffer is dequeued in the thread.
> >> - */
> >> -typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
> >> -
> >> -/**
> >> - * vb2_thread_start() - start a thread for the given queue.
> >> - * @q:		videobuf queue
> >> - * @fnc:	callback function
> >> - * @priv:	priv pointer passed to the callback function
> >> - * @thread_name:the name of the thread. This will be prefixed with "vb2-".
> >> - *
> >> - * This starts a thread that will queue and dequeue until an error occurs
> >> - * or @vb2_thread_stop is called.
> >> - *
> >> - * This function should not be used for anything else but the videobuf2-dvb
> >> - * support. If you think you have another good use-case for this, then please
> >> - * contact the linux-media mailinglist first.
> >> - */
> >> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> >> -		     const char *thread_name);
> >> -
> >> -/**
> >> - * vb2_thread_stop() - stop the thread for the given queue.
> >> - * @q:		videobuf queue
> >> - */
> >> -int vb2_thread_stop(struct vb2_queue *q);
> >>
> >>   /**
> >>    * vb2_is_streaming() - return streaming status of the queue
> >> @@ -527,23 +498,6 @@ static inline bool vb2_is_streaming(struct vb2_queue *q)
> >>   }
> >>
> >>   /**
> >> - * vb2_fileio_is_active() - return true if fileio is active.
> >> - * @q:		videobuf queue
> >> - *
> >> - * This returns true if read() or write() is used to stream the data
> >> - * as opposed to stream I/O. This is almost never an important distinction,
> >> - * except in rare cases. One such case is that using read() or write() to
> >> - * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
> >> - * is no way you can pass the field information of each buffer to/from
> >> - * userspace. A driver that supports this field format should check for
> >> - * this in the queue_setup op and reject it if this function returns true.
> >> - */
> >> -static inline bool vb2_fileio_is_active(struct vb2_queue *q)
> >> -{
> >> -	return q->fileio;
> >> -}
> >> -
> >> -/**
> >>    * vb2_is_busy() - return busy status of the queue
> >>    * @q:		videobuf queue
> >>    *
> >> @@ -620,47 +574,4 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q)
> >>   	q->last_buffer_dequeued = false;
> >>   }
> >>
> >> -/*
> >> - * The following functions are not part of the vb2 core API, but are simple
> >> - * helper functions that you can use in your struct v4l2_file_operations,
> >> - * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock
> >> - * or video_device->lock is set, and they will set and test vb2_queue->owner
> >> - * to check if the calling filehandle is permitted to do the queuing operation.
> >> - */
> >> -
> >> -/* struct v4l2_ioctl_ops helpers */
> >> -
> >> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
> >> -			  struct v4l2_requestbuffers *p);
> >> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
> >> -			  struct v4l2_create_buffers *p);
> >> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> >> -			  struct v4l2_buffer *p);
> >> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
> >> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> >> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> >> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
> >> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
> >> -int vb2_ioctl_expbuf(struct file *file, void *priv,
> >> -	struct v4l2_exportbuffer *p);
> >> -
> >> -/* struct v4l2_file_operations helpers */
> >> -
> >> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
> >> -int vb2_fop_release(struct file *file);
> >> -int _vb2_fop_release(struct file *file, struct mutex *lock);
> >> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> >> -		size_t count, loff_t *ppos);
> >> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
> >> -		size_t count, loff_t *ppos);
> >> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
> >> -#ifndef CONFIG_MMU
> >> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> >> -		unsigned long len, unsigned long pgoff, unsigned long flags);
> >> -#endif
> >> -
> >> -/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
> >> -
> >> -void vb2_ops_wait_prepare(struct vb2_queue *vq);
> >> -void vb2_ops_wait_finish(struct vb2_queue *vq);
> >>   #endif /* _MEDIA_VIDEOBUF2_CORE_H */
> >> diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
> >> index fc2dbe9..790cb7a 100644
> >> --- a/include/media/videobuf2-v4l2.h
> >> +++ b/include/media/videobuf2-v4l2.h
> >> @@ -40,4 +40,120 @@ struct vb2_v4l2_buffer {
> >>   #define to_vb2_v4l2_buffer(vb) \
> >>   	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
> >>
> >> +
> >> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
> >> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
> >> +
> >> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
> >> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
> >> +
> >> +int __must_check vb2_queue_init(struct vb2_queue *q);
> >> +
> >> +void vb2_queue_release(struct vb2_queue *q);
> >> +
> >> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
> >> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
> >> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
> >> +
> >> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
> >> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
> >> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
> >> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
> >> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> >> +		loff_t *ppos, int nonblock);
> >> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> >> +		loff_t *ppos, int nonblock);
> >> +
> >> +/*
> >> + * vb2_thread_fnc - callback function for use with vb2_thread
> >> + *
> >> + * This is called whenever a buffer is dequeued in the thread.
> >> + */
> >> +typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
> >> +
> >> +/**
> >> + * vb2_thread_start() - start a thread for the given queue.
> >> + * @q:		videobuf queue
> >> + * @fnc:	callback function
> >> + * @priv:	priv pointer passed to the callback function
> >> + * @thread_name:the name of the thread. This will be prefixed with "vb2-".
> >> + *
> >> + * This starts a thread that will queue and dequeue until an error occurs
> >> + * or @vb2_thread_stop is called.
> >> + *
> >> + * This function should not be used for anything else but the videobuf2-dvb
> >> + * support. If you think you have another good use-case for this, then please
> >> + * contact the linux-media mailinglist first.
> >> + */
> >> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> >> +		     const char *thread_name);
> >> +
> >> +/**
> >> + * vb2_thread_stop() - stop the thread for the given queue.
> >> + * @q:		videobuf queue
> >> + */
> >> +int vb2_thread_stop(struct vb2_queue *q);
> >> +
> >> +/**
> >> + * vb2_fileio_is_active() - return true if fileio is active.
> >> + * @q:		videobuf queue
> >> + *
> >> + * This returns true if read() or write() is used to stream the data
> >> + * as opposed to stream I/O. This is almost never an important distinction,
> >> + * except in rare cases. One such case is that using read() or write() to
> >> + * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
> >> + * is no way you can pass the field information of each buffer to/from
> >> + * userspace. A driver that supports this field format should check for
> >> + * this in the queue_setup op and reject it if this function returns true.
> >> + */
> >> +static inline bool vb2_fileio_is_active(struct vb2_queue *q)
> >> +{
> >> +	return q->fileio;
> >> +}
> >> +
> >> +/*
> >> + * The following functions are not part of the vb2 core API, but are simple
> >> + * helper functions that you can use in your struct v4l2_file_operations,
> >> + * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize
> >> + * if vb2_queue->lock or video_device->lock is set, and they will set
> >> + * and test vb2_queue->owner to check if the calling filehandle is permitted
> >> + * to do the queuing operation.
> >> + */
> >> +
> >> +/* struct v4l2_ioctl_ops helpers */
> >> +
> >> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
> >> +			  struct v4l2_requestbuffers *p);
> >> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
> >> +			  struct v4l2_create_buffers *p);
> >> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> >> +			  struct v4l2_buffer *p);
> >> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
> >> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> >> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> >> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
> >> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
> >> +int vb2_ioctl_expbuf(struct file *file, void *priv,
> >> +	struct v4l2_exportbuffer *p);
> >> +
> >> +/* struct v4l2_file_operations helpers */
> >> +
> >> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
> >> +int vb2_fop_release(struct file *file);
> >> +int _vb2_fop_release(struct file *file, struct mutex *lock);
> >> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> >> +		size_t count, loff_t *ppos);
> >> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
> >> +		size_t count, loff_t *ppos);
> >> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
> >> +#ifndef CONFIG_MMU
> >> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> >> +		unsigned long len, unsigned long pgoff, unsigned long flags);
> >> +#endif
> >> +
> >> +/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
> >> +
> >> +void vb2_ops_wait_prepare(struct vb2_queue *vq);
> >> +void vb2_ops_wait_finish(struct vb2_queue *vq);
> >> +
> >>   #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
> >> diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
> >> index b015b38..f31b258 100644
> >> --- a/include/trace/events/v4l2.h
> >> +++ b/include/trace/events/v4l2.h
> >> @@ -5,6 +5,7 @@
> >>   #define _TRACE_V4L2_H
> >>
> >>   #include <linux/tracepoint.h>
> >> +#include <media/videobuf2-v4l2.h>
> >>
> >>   /* Enums require being exported to userspace, for user tool parsing */
> >>   #undef EM
> >> @@ -203,7 +204,8 @@ DECLARE_EVENT_CLASS(vb2_event_class,
> >>
> >>   	TP_fast_assign(
> >>   		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >> -		__entry->minor = q->owner ? q->owner->vdev->minor : -1;
> >> +		struct v4l2_fh *owner = (struct v4l2_fh *) q->owner;
> >> +		__entry->minor = owner ? owner->vdev->minor : -1;
> >>   		__entry->queued_count = q->queued_count;
> >>   		__entry->owned_by_drv_count =
> >>   			atomic_read(&q->owned_by_drv_count);
> >
> > Regards,
> > Mauro
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-media" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer
  2015-08-28  1:26     ` Junghak Sung
@ 2015-08-28  9:09       ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2015-08-28  9:09 UTC (permalink / raw)
  To: Junghak Sung
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Em Fri, 28 Aug 2015 10:26:48 +0900
Junghak Sung <jh1009.sung@samsung.com> escreveu:

> 
> Hello Mauro,
> 
> First of all, thank you for your detailed review.
> 
> 
> On 08/27/2015 07:28 PM, Mauro Carvalho Chehab wrote:
> > Em Wed, 26 Aug 2015 20:59:29 +0900
> > Junghak Sung <jh1009.sung@samsung.com> escreveu:
> >
> >> Remove v4l2-specific stuff from struct vb2_buffer and add member variables
> >> related with buffer management.
> >>
> >> struct vb2_plane {
> >>          <snip>
> >>          /* plane information */
> >>          unsigned int            bytesused;
> >>          unsigned int            length;
> >>          union {
> >>                  unsigned int    offset;
> >>                  unsigned long   userptr;
> >>                  int             fd;
> >>          } m;
> >>          unsigned int            data_offset;
> >> }
> >>
> >> struct vb2_buffer {
> >>          <snip>
> >>          /* buffer information */
> >>          unsigned int            num_planes;
> >>          unsigned int            index;
> >>          unsigned int            type;
> >>          unsigned int            memory;
> >>
> >>          struct vb2_plane        planes[VIDEO_MAX_PLANES];
> >>          <snip>
> >> };
> >>
> >> And create struct vb2_v4l2_buffer as container buffer for v4l2 use.
> >>
> >> struct vb2_v4l2_buffer {
> >>          struct vb2_buffer       vb2_buf;
> >>
> >>          __u32                   flags;
> >>          __u32                   field;
> >>          struct timeval          timestamp;
> >>          struct v4l2_timecode    timecode;
> >>          __u32                   sequence;
> >> };
> >
> > The comments seemed a little hard for me to read, but the changes
> > look ok.
> >
> 
> Ok, I will modify these comments more clearly at next round.
> 
> > I made some comments mostly regarding to documentation. See below.
> >
> >> This patch includes only changes inside of videobuf2. So, it is required to
> >> modify all device drivers which use videobuf2.
> >
> > So, in practice, we need to fold both patches 2 and 3 when merging upstream,
> > to avoid breaking git bisectability.
> >
> 
> I'm sorry, but I can not understand the meaning of "fold both patches".
> Would you please explain more detailed what should I do at next round.
> If these two patches are get together to one patch, the size will
> be over 300KB, which causes a size problem to send it to ML.

No. What I'm meaning is that reviewers/(sub)maintainers need to be reminded 
that patches 2 and 3 should be merged together when the patches got applied,
as otherwise they'll break the compilation.

So, just add a notice on the next patch series, but keep them as two
separate patches ;)

Regards,
Mauro

> 
> >>
> >> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> >> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> >> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> >> Acked-by: Inki Dae <inki.dae@samsung.com>
> >> ---
> >>   drivers/media/v4l2-core/videobuf2-core.c |  324 +++++++++++++++++-------------
> >>   include/media/videobuf2-core.h           |   50 ++---
> >>   include/media/videobuf2-v4l2.h           |   26 +++
> >>   3 files changed, 236 insertions(+), 164 deletions(-)
> >>
> >> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> >> index ab00ea0..9266d50 100644
> >> --- a/drivers/media/v4l2-core/videobuf2-core.c
> >> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> >> @@ -35,10 +35,10 @@
> >>   static int debug;
> >>   module_param(debug, int, 0644);
> >>
> >> -#define dprintk(level, fmt, arg...)					      \
> >> -	do {								      \
> >> -		if (debug >= level)					      \
> >> -			pr_info("vb2: %s: " fmt, __func__, ## arg); \
> >> +#define dprintk(level, fmt, arg...)					\
> >> +	do {								\
> >> +		if (debug >= level)					\
> >> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
> >>   	} while (0)
> >>
> >>   #ifdef CONFIG_VIDEO_ADV_DEBUG
> >> @@ -53,7 +53,7 @@ module_param(debug, int, 0644);
> >>
> >>   #define log_memop(vb, op)						\
> >>   	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
> >> -		(vb)->vb2_queue, (vb)->v4l2_buf.index, #op,		\
> >> +		(vb)->vb2_queue, (vb)->index, #op,			\
> >>   		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
> >>
> >>   #define call_memop(vb, op, args...)					\
> >> @@ -115,7 +115,7 @@ module_param(debug, int, 0644);
> >>
> >>   #define log_vb_qop(vb, op, args...)					\
> >>   	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
> >> -		(vb)->vb2_queue, (vb)->v4l2_buf.index, #op,		\
> >> +		(vb)->vb2_queue, (vb)->index, #op,			\
> >>   		(vb)->vb2_queue->ops->op ? "" : " (nop)")
> >>
> >>   #define call_vb_qop(vb, op, args...)					\
> >> @@ -205,13 +205,13 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
> >>   		unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]);
> >>
> >>   		mem_priv = call_ptr_memop(vb, alloc, q->alloc_ctx[plane],
> >> -				      size, dma_dir, q->gfp_flags);
> >> +					size, dma_dir, q->gfp_flags);
> >>   		if (IS_ERR_OR_NULL(mem_priv))
> >>   			goto free;
> >>
> >>   		/* Associate allocator private data with this plane */
> >>   		vb->planes[plane].mem_priv = mem_priv;
> >> -		vb->v4l2_planes[plane].length = q->plane_sizes[plane];
> >> +		vb->planes[plane].length = q->plane_sizes[plane];
> >>   	}
> >>
> >>   	return 0;
> >> @@ -235,8 +235,7 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb)
> >>   	for (plane = 0; plane < vb->num_planes; ++plane) {
> >>   		call_void_memop(vb, put, vb->planes[plane].mem_priv);
> >>   		vb->planes[plane].mem_priv = NULL;
> >> -		dprintk(3, "freed plane %d of buffer %d\n", plane,
> >> -			vb->v4l2_buf.index);
> >> +		dprintk(3, "freed plane %d of buffer %d\n", plane, vb->index);
> >>   	}
> >>   }
> >>
> >> @@ -269,7 +268,9 @@ static void __vb2_plane_dmabuf_put(struct vb2_buffer *vb, struct vb2_plane *p)
> >>
> >>   	call_void_memop(vb, detach_dmabuf, p->mem_priv);
> >>   	dma_buf_put(p->dbuf);
> >> -	memset(p, 0, sizeof(*p));
> >> +	p->mem_priv = NULL;
> >> +	p->dbuf = NULL;
> >> +	p->dbuf_mapped = 0;
> >>   }
> >>
> >>   /**
> >> @@ -299,7 +300,7 @@ static void __setup_lengths(struct vb2_queue *q, unsigned int n)
> >>   			continue;
> >>
> >>   		for (plane = 0; plane < vb->num_planes; ++plane)
> >> -			vb->v4l2_planes[plane].length = q->plane_sizes[plane];
> >> +			vb->planes[plane].length = q->plane_sizes[plane];
> >>   	}
> >>   }
> >>
> >> @@ -314,10 +315,10 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
> >>   	unsigned long off;
> >>
> >>   	if (q->num_buffers) {
> >> -		struct v4l2_plane *p;
> >> +		struct vb2_plane *p;
> >>   		vb = q->bufs[q->num_buffers - 1];
> >> -		p = &vb->v4l2_planes[vb->num_planes - 1];
> >> -		off = PAGE_ALIGN(p->m.mem_offset + p->length);
> >> +		p = &vb->planes[vb->num_planes - 1];
> >> +		off = PAGE_ALIGN(p->m.offset + p->length);
> >>   	} else {
> >>   		off = 0;
> >>   	}
> >> @@ -328,12 +329,12 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
> >>   			continue;
> >>
> >>   		for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -			vb->v4l2_planes[plane].m.mem_offset = off;
> >> +			vb->planes[plane].m.offset = off;
> >>
> >>   			dprintk(3, "buffer %d, plane %d offset 0x%08lx\n",
> >>   					buffer, plane, off);
> >>
> >> -			off += vb->v4l2_planes[plane].length;
> >> +			off += vb->planes[plane].length;
> >>   			off = PAGE_ALIGN(off);
> >>   		}
> >>   	}
> >> @@ -347,7 +348,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
> >>    * Returns the number of buffers successfully allocated.
> >>    */
> >>   static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
> >> -			     unsigned int num_buffers, unsigned int num_planes)
> >> +			unsigned int num_buffers, unsigned int num_planes)
> >>   {
> >>   	unsigned int buffer;
> >>   	struct vb2_buffer *vb;
> >> @@ -361,16 +362,12 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
> >>   			break;
> >>   		}
> >>
> >> -		/* Length stores number of planes for multiplanar buffers */
> >> -		if (V4L2_TYPE_IS_MULTIPLANAR(q->type))
> >> -			vb->v4l2_buf.length = num_planes;
> >> -
> >>   		vb->state = VB2_BUF_STATE_DEQUEUED;
> >>   		vb->vb2_queue = q;
> >>   		vb->num_planes = num_planes;
> >> -		vb->v4l2_buf.index = q->num_buffers + buffer;
> >> -		vb->v4l2_buf.type = q->type;
> >> -		vb->v4l2_buf.memory = memory;
> >> +		vb->index = q->num_buffers + buffer;
> >> +		vb->type = q->type;
> >> +		vb->memory = memory;
> >>
> >>   		/* Allocate video buffer memory for the MMAP type */
> >>   		if (memory == V4L2_MEMORY_MMAP) {
> >> @@ -418,7 +415,7 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
> >>   	struct vb2_buffer *vb;
> >>
> >>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
> >> -	     ++buffer) {
> >> +			++buffer) {
> >>   		vb = q->bufs[buffer];
> >>   		if (!vb)
> >>   			continue;
> >> @@ -451,7 +448,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
> >>   	 * just return -EAGAIN.
> >>   	 */
> >>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
> >> -	     ++buffer) {
> >> +			++buffer) {
> >>   		if (q->bufs[buffer] == NULL)
> >>   			continue;
> >>   		if (q->bufs[buffer]->state == VB2_BUF_STATE_PREPARING) {
> >> @@ -462,7 +459,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
> >>
> >>   	/* Call driver-provided cleanup function for each buffer, if provided */
> >>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
> >> -	     ++buffer) {
> >> +			++buffer) {
> >>   		struct vb2_buffer *vb = q->bufs[buffer];
> >>
> >>   		if (vb && vb->planes[0].mem_priv)
> >> @@ -536,7 +533,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
> >>
> >>   	/* Free videobuf buffers */
> >>   	for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
> >> -	     ++buffer) {
> >> +			++buffer) {
> >>   		kfree(q->bufs[buffer]);
> >>   		q->bufs[buffer] = NULL;
> >>   	}
> >> @@ -590,23 +587,22 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> >>   		for (plane = 0; plane < vb->num_planes; ++plane) {
> >>   			length = (b->memory == V4L2_MEMORY_USERPTR ||
> >> -				  b->memory == V4L2_MEMORY_DMABUF)
> >> -			       ? b->m.planes[plane].length
> >> -			       : vb->v4l2_planes[plane].length;
> >> +				b->memory == V4L2_MEMORY_DMABUF)
> >> +				? b->m.planes[plane].length
> >> +				: vb->planes[plane].length;
> >>   			bytesused = b->m.planes[plane].bytesused
> >> -				  ? b->m.planes[plane].bytesused : length;
> >> +				? b->m.planes[plane].bytesused : length;
> >>
> >>   			if (b->m.planes[plane].bytesused > length)
> >>   				return -EINVAL;
> >>
> >>   			if (b->m.planes[plane].data_offset > 0 &&
> >> -			    b->m.planes[plane].data_offset >= bytesused)
> >> +				b->m.planes[plane].data_offset >= bytesused)
> >>   				return -EINVAL;
> >>   		}
> >>   	} else {
> >>   		length = (b->memory == V4L2_MEMORY_USERPTR)
> >> -		       ? b->length : vb->v4l2_planes[0].length;
> >> -		bytesused = b->bytesused ? b->bytesused : length;
> >> +			? b->length : vb->planes[0].length;
> >>
> >>   		if (b->bytesused > length)
> >>   			return -EINVAL;
> >> @@ -656,12 +652,21 @@ static bool __buffers_in_use(struct vb2_queue *q)
> >>    */
> >>   static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
> >>   {
> >> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >>   	struct vb2_queue *q = vb->vb2_queue;
> >> +	unsigned int plane;
> >>
> >>   	/* Copy back data such as timestamp, flags, etc. */
> >> -	memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
> >> -	b->reserved2 = vb->v4l2_buf.reserved2;
> >> -	b->reserved = vb->v4l2_buf.reserved;
> >> +	b->index = vb->index;
> >> +	b->type = vb->type;
> >> +	b->memory = vb->memory;
> >> +	b->bytesused = 0;
> >> +
> >> +	b->flags = vbuf->flags;
> >> +	b->field = vbuf->field;
> >> +	b->timestamp = vbuf->timestamp;
> >> +	b->timecode = vbuf->timecode;
> >> +	b->sequence = vbuf->sequence;
> >>
> >>   	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
> >>   		/*
> >> @@ -669,21 +674,33 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
> >>   		 * for it. The caller has already verified memory and size.
> >>   		 */
> >>   		b->length = vb->num_planes;
> >> -		memcpy(b->m.planes, vb->v4l2_planes,
> >> -			b->length * sizeof(struct v4l2_plane));
> >> +		for (plane = 0; plane < vb->num_planes; ++plane) {
> >> +			struct v4l2_plane *pdst = &b->m.planes[plane];
> >> +			struct vb2_plane *psrc = &vb->planes[plane];
> >> +
> >> +			pdst->bytesused = psrc->bytesused;
> >> +			pdst->length = psrc->length;
> >> +			if (q->memory == V4L2_MEMORY_MMAP)
> >> +				pdst->m.mem_offset = psrc->m.offset;
> >> +			else if (q->memory == V4L2_MEMORY_USERPTR)
> >> +				pdst->m.userptr = psrc->m.userptr;
> >> +			else if (q->memory == V4L2_MEMORY_DMABUF)
> >> +				pdst->m.fd = psrc->m.fd;
> >> +			pdst->data_offset = psrc->data_offset;
> >> +		}
> >>   	} else {
> >>   		/*
> >>   		 * We use length and offset in v4l2_planes array even for
> >>   		 * single-planar buffers, but userspace does not.
> >>   		 */
> >> -		b->length = vb->v4l2_planes[0].length;
> >> -		b->bytesused = vb->v4l2_planes[0].bytesused;
> >> +		b->length = vb->planes[0].length;
> >> +		b->bytesused = vb->planes[0].bytesused;
> >>   		if (q->memory == V4L2_MEMORY_MMAP)
> >> -			b->m.offset = vb->v4l2_planes[0].m.mem_offset;
> >> +			b->m.offset = vb->planes[0].m.offset;
> >>   		else if (q->memory == V4L2_MEMORY_USERPTR)
> >> -			b->m.userptr = vb->v4l2_planes[0].m.userptr;
> >> +			b->m.userptr = vb->planes[0].m.userptr;
> >>   		else if (q->memory == V4L2_MEMORY_DMABUF)
> >> -			b->m.fd = vb->v4l2_planes[0].m.fd;
> >> +			b->m.fd = vb->planes[0].m.fd;
> >>   	}
> >>
> >>   	/*
> >> @@ -692,7 +709,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
> >>   	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
> >>   	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
> >>   	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> >> -	    V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> >> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> >>   		/*
> >>   		 * For non-COPY timestamps, drop timestamp source bits
> >>   		 * and obtain the timestamp source from the queue.
> >> @@ -767,7 +784,7 @@ EXPORT_SYMBOL(vb2_querybuf);
> >>   static int __verify_userptr_ops(struct vb2_queue *q)
> >>   {
> >>   	if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
> >> -	    !q->mem_ops->put_userptr)
> >> +			!q->mem_ops->put_userptr)
> >>   		return -EINVAL;
> >>
> >>   	return 0;
> >> @@ -780,7 +797,7 @@ static int __verify_userptr_ops(struct vb2_queue *q)
> >>   static int __verify_mmap_ops(struct vb2_queue *q)
> >>   {
> >>   	if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
> >> -	    !q->mem_ops->put || !q->mem_ops->mmap)
> >> +			!q->mem_ops->put || !q->mem_ops->mmap)
> >>   		return -EINVAL;
> >>
> >>   	return 0;
> >> @@ -793,8 +810,8 @@ static int __verify_mmap_ops(struct vb2_queue *q)
> >>   static int __verify_dmabuf_ops(struct vb2_queue *q)
> >>   {
> >>   	if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
> >> -	    !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
> >> -	    !q->mem_ops->unmap_dmabuf)
> >> +		!q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
> >> +		!q->mem_ops->unmap_dmabuf)
> >>   		return -EINVAL;
> >>
> >>   	return 0;
> >> @@ -808,7 +825,7 @@ static int __verify_memory_type(struct vb2_queue *q,
> >>   		enum v4l2_memory memory, enum v4l2_buf_type type)
> >>   {
> >>   	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
> >> -	    memory != V4L2_MEMORY_DMABUF) {
> >> +			memory != V4L2_MEMORY_DMABUF) {
> >>   		dprintk(1, "unsupported memory type\n");
> >>   		return -EINVAL;
> >>   	}
> >> @@ -927,7 +944,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> >>   	 * Driver also sets the size and allocator context for each plane.
> >>   	 */
> >>   	ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
> >> -		       q->plane_sizes, q->alloc_ctx);
> >> +			q->plane_sizes, q->alloc_ctx);
> >>   	if (ret)
> >>   		return ret;
> >>
> >> @@ -952,7 +969,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> >>   		num_buffers = allocated_buffers;
> >>
> >>   		ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
> >> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
> >> +				&num_planes, q->plane_sizes, q->alloc_ctx);
> >>
> >>   		if (!ret && allocated_buffers < num_buffers)
> >>   			ret = -ENOMEM;
> >> @@ -1040,7 +1057,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
> >>   	 * buffer and their sizes are acceptable
> >>   	 */
> >>   	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> >> -		       &num_planes, q->plane_sizes, q->alloc_ctx);
> >> +			&num_planes, q->plane_sizes, q->alloc_ctx);
> >>   	if (ret)
> >>   		return ret;
> >>
> >> @@ -1063,7 +1080,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
> >>   		 * queue driver has set up
> >>   		 */
> >>   		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> >> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
> >> +				&num_planes, q->plane_sizes, q->alloc_ctx);
> >>
> >>   		if (!ret && allocated_buffers < num_buffers)
> >>   			ret = -ENOMEM;
> >> @@ -1183,8 +1200,8 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
> >>   		return;
> >>
> >>   	if (WARN_ON(state != VB2_BUF_STATE_DONE &&
> >> -		    state != VB2_BUF_STATE_ERROR &&
> >> -		    state != VB2_BUF_STATE_QUEUED))
> >> +		state != VB2_BUF_STATE_ERROR &&
> >> +		state != VB2_BUF_STATE_QUEUED))
> >>   		state = VB2_BUF_STATE_ERROR;
> >>
> >>   #ifdef CONFIG_VIDEO_ADV_DEBUG
> >> @@ -1195,7 +1212,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
> >>   	vb->cnt_buf_done++;
> >>   #endif
> >>   	dprintk(4, "done processing on buffer %d, state: %d\n",
> >> -			vb->v4l2_buf.index, state);
> >> +			vb->index, state);
> >>
> >>   	/* sync buffers */
> >>   	for (plane = 0; plane < vb->num_planes; ++plane)
> >> @@ -1268,25 +1285,26 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
> >>    * v4l2_buffer by the userspace. The caller has already verified that struct
> >>    * v4l2_buffer has a valid number of planes.
> >>    */
> >> -static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
> >> -				struct v4l2_plane *v4l2_planes)
> >> +static void __fill_vb2_buffer(struct vb2_buffer *vb,
> >> +		const struct v4l2_buffer *b, struct vb2_plane *planes)
> >>   {
> >> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >>   	unsigned int plane;
> >>
> >>   	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> >>   		if (b->memory == V4L2_MEMORY_USERPTR) {
> >>   			for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -				v4l2_planes[plane].m.userptr =
> >> +				planes[plane].m.userptr =
> >>   					b->m.planes[plane].m.userptr;
> >> -				v4l2_planes[plane].length =
> >> +				planes[plane].length =
> >>   					b->m.planes[plane].length;
> >>   			}
> >>   		}
> >>   		if (b->memory == V4L2_MEMORY_DMABUF) {
> >>   			for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -				v4l2_planes[plane].m.fd =
> >> +				planes[plane].m.fd =
> >>   					b->m.planes[plane].m.fd;
> >> -				v4l2_planes[plane].length =
> >> +				planes[plane].length =
> >>   					b->m.planes[plane].length;
> >>   			}
> >>   		}
> >> @@ -1310,7 +1328,7 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
> >>   			 * applications working.
> >>   			 */
> >>   			for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -				struct v4l2_plane *pdst = &v4l2_planes[plane];
> >> +				struct vb2_plane *pdst = &planes[plane];
> >>   				struct v4l2_plane *psrc = &b->m.planes[plane];
> >>
> >>   				if (psrc->bytesused == 0)
> >> @@ -1340,13 +1358,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
> >>   		 * old userspace applications working.
> >>   		 */
> >>   		if (b->memory == V4L2_MEMORY_USERPTR) {
> >> -			v4l2_planes[0].m.userptr = b->m.userptr;
> >> -			v4l2_planes[0].length = b->length;
> >> +			planes[0].m.userptr = b->m.userptr;
> >> +			planes[0].length = b->length;
> >>   		}
> >>
> >>   		if (b->memory == V4L2_MEMORY_DMABUF) {
> >> -			v4l2_planes[0].m.fd = b->m.fd;
> >> -			v4l2_planes[0].length = b->length;
> >> +			planes[0].m.fd = b->m.fd;
> >> +			planes[0].length = b->length;
> >>   		}
> >>
> >>   		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> @@ -1354,25 +1372,26 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
> >>   				vb2_warn_zero_bytesused(vb);
> >>
> >>   			if (vb->vb2_queue->allow_zero_bytesused)
> >> -				v4l2_planes[0].bytesused = b->bytesused;
> >> +				planes[0].bytesused = b->bytesused;
> >>   			else
> >> -				v4l2_planes[0].bytesused = b->bytesused ?
> >> -					b->bytesused : v4l2_planes[0].length;
> >> +				planes[0].bytesused = b->bytesused ?
> >> +					b->bytesused : planes[0].length;
> >>   		} else
> >> -			v4l2_planes[0].bytesused = 0;
> >> +			planes[0].bytesused = 0;
> >>
> >>   	}
> >>
> >>   	/* Zero flags that the vb2 core handles */
> >> -	vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> >> +	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> >>   	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> >> -	    V4L2_BUF_FLAG_TIMESTAMP_COPY || !V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> +			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
> >> +			!V4L2_TYPE_IS_OUTPUT(b->type)) {
> >>   		/*
> >>   		 * Non-COPY timestamps and non-OUTPUT queues will get
> >>   		 * their timestamp and timestamp source flags from the
> >>   		 * queue.
> >>   		 */
> >> -		vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> >> +		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> >>   	}
> >>
> >>   	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> >> @@ -1382,11 +1401,11 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
> >>   		 * The 'field' is valid metadata for this output buffer
> >>   		 * and so that needs to be copied here.
> >>   		 */
> >> -		vb->v4l2_buf.flags &= ~V4L2_BUF_FLAG_TIMECODE;
> >> -		vb->v4l2_buf.field = b->field;
> >> +		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
> >> +		vbuf->field = b->field;
> >>   	} else {
> >>   		/* Zero any output buffer flags as this is a capture buffer */
> >> -		vb->v4l2_buf.flags &= ~V4L2_BUFFER_OUT_FLAGS;
> >> +		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
> >>   	}
> >>   }
> >>
> >> @@ -1395,7 +1414,7 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
> >>    */
> >>   static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   {
> >> -	__fill_vb2_buffer(vb, b, vb->v4l2_planes);
> >> +	__fill_vb2_buffer(vb, b, vb->planes);
> >>   	return call_vb_qop(vb, buf_prepare, vb);
> >>   }
> >>
> >> @@ -1404,7 +1423,7 @@ static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>    */
> >>   static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   {
> >> -	struct v4l2_plane planes[VIDEO_MAX_PLANES];
> >> +	struct vb2_plane planes[VIDEO_MAX_PLANES];
> >>   	struct vb2_queue *q = vb->vb2_queue;
> >>   	void *mem_priv;
> >>   	unsigned int plane;
> >> @@ -1419,9 +1438,9 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>
> >>   	for (plane = 0; plane < vb->num_planes; ++plane) {
> >>   		/* Skip the plane if already verified */
> >> -		if (vb->v4l2_planes[plane].m.userptr &&
> >> -		    vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
> >> -		    && vb->v4l2_planes[plane].length == planes[plane].length)
> >> +		if (vb->planes[plane].m.userptr &&
> >> +			vb->planes[plane].m.userptr == planes[plane].m.userptr
> >> +			&& vb->planes[plane].length == planes[plane].length)
> >>   			continue;
> >>
> >>   		dprintk(3, "userspace address for plane %d changed, "
> >> @@ -1447,12 +1466,15 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   		}
> >>
> >>   		vb->planes[plane].mem_priv = NULL;
> >> -		memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
> >> +		vb->planes[plane].bytesused = 0;
> >> +		vb->planes[plane].length = 0;
> >> +		vb->planes[plane].m.userptr = 0;
> >> +		vb->planes[plane].data_offset = 0;
> >>
> >>   		/* Acquire each plane's memory */
> >>   		mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane],
> >> -				      planes[plane].m.userptr,
> >> -				      planes[plane].length, dma_dir);
> >> +					planes[plane].m.userptr,
> >> +					planes[plane].length, dma_dir);
> >>   		if (IS_ERR_OR_NULL(mem_priv)) {
> >>   			dprintk(1, "failed acquiring userspace "
> >>   						"memory for plane %d\n", plane);
> >> @@ -1466,8 +1488,12 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   	 * Now that everything is in order, copy relevant information
> >>   	 * provided by userspace.
> >>   	 */
> >> -	for (plane = 0; plane < vb->num_planes; ++plane)
> >> -		vb->v4l2_planes[plane] = planes[plane];
> >> +	for (plane = 0; plane < vb->num_planes; ++plane) {
> >> +		vb->planes[plane].bytesused = planes[plane].bytesused;
> >> +		vb->planes[plane].length = planes[plane].length;
> >> +		vb->planes[plane].m.userptr = planes[plane].m.userptr;
> >> +		vb->planes[plane].data_offset = planes[plane].data_offset;
> >> +	}
> >>
> >>   	if (reacquired) {
> >>   		/*
> >> @@ -1494,10 +1520,11 @@ err:
> >>   	/* In case of errors, release planes that were already acquired */
> >>   	for (plane = 0; plane < vb->num_planes; ++plane) {
> >>   		if (vb->planes[plane].mem_priv)
> >> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
> >> +			call_void_memop(vb, put_userptr,
> >> +				vb->planes[plane].mem_priv);
> >>   		vb->planes[plane].mem_priv = NULL;
> >> -		vb->v4l2_planes[plane].m.userptr = 0;
> >> -		vb->v4l2_planes[plane].length = 0;
> >> +		vb->planes[plane].m.userptr = 0;
> >> +		vb->planes[plane].length = 0;
> >>   	}
> >>
> >>   	return ret;
> >> @@ -1508,7 +1535,7 @@ err:
> >>    */
> >>   static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   {
> >> -	struct v4l2_plane planes[VIDEO_MAX_PLANES];
> >> +	struct vb2_plane planes[VIDEO_MAX_PLANES];
> >>   	struct vb2_queue *q = vb->vb2_queue;
> >>   	void *mem_priv;
> >>   	unsigned int plane;
> >> @@ -1544,7 +1571,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>
> >>   		/* Skip the plane if already verified */
> >>   		if (dbuf == vb->planes[plane].dbuf &&
> >> -		    vb->v4l2_planes[plane].length == planes[plane].length) {
> >> +			vb->planes[plane].length == planes[plane].length) {
> >>   			dma_buf_put(dbuf);
> >>   			continue;
> >>   		}
> >> @@ -1558,11 +1585,15 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>
> >>   		/* Release previously acquired memory if present */
> >>   		__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
> >> -		memset(&vb->v4l2_planes[plane], 0, sizeof(struct v4l2_plane));
> >> +		vb->planes[plane].bytesused = 0;
> >> +		vb->planes[plane].length = 0;
> >> +		vb->planes[plane].m.fd = 0;
> >> +		vb->planes[plane].data_offset = 0;
> >>
> >>   		/* Acquire each plane's memory */
> >> -		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
> >> -			dbuf, planes[plane].length, dma_dir);
> >> +		mem_priv = call_ptr_memop(vb, attach_dmabuf,
> >> +			q->alloc_ctx[plane], dbuf, planes[plane].length,
> >> +			dma_dir);
> >>   		if (IS_ERR(mem_priv)) {
> >>   			dprintk(1, "failed to attach dmabuf\n");
> >>   			ret = PTR_ERR(mem_priv);
> >> @@ -1592,8 +1623,12 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   	 * Now that everything is in order, copy relevant information
> >>   	 * provided by userspace.
> >>   	 */
> >> -	for (plane = 0; plane < vb->num_planes; ++plane)
> >> -		vb->v4l2_planes[plane] = planes[plane];
> >> +	for (plane = 0; plane < vb->num_planes; ++plane) {
> >> +		vb->planes[plane].bytesused = planes[plane].bytesused;
> >> +		vb->planes[plane].length = planes[plane].length;
> >> +		vb->planes[plane].m.fd = planes[plane].m.userptr;
> >> +		vb->planes[plane].data_offset = planes[plane].data_offset;
> >> +	}
> >>
> >>   	if (reacquired) {
> >>   		/*
> >> @@ -1644,6 +1679,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
> >>
> >>   static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   {
> >> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> >>   	struct vb2_queue *q = vb->vb2_queue;
> >>   	int ret;
> >>
> >> @@ -1672,9 +1708,9 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   	}
> >>
> >>   	vb->state = VB2_BUF_STATE_PREPARING;
> >> -	vb->v4l2_buf.timestamp.tv_sec = 0;
> >> -	vb->v4l2_buf.timestamp.tv_usec = 0;
> >> -	vb->v4l2_buf.sequence = 0;
> >> +	vbuf->timestamp.tv_sec = 0;
> >> +	vbuf->timestamp.tv_usec = 0;
> >> +	vbuf->sequence = 0;
> >>
> >>   	switch (q->memory) {
> >>   	case V4L2_MEMORY_MMAP:
> >> @@ -1701,7 +1737,7 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> >>   }
> >>
> >>   static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
> >> -				    const char *opname)
> >> +					const char *opname)
> >>   {
> >>   	if (b->type != q->type) {
> >>   		dprintk(1, "%s: invalid buffer type\n", opname);
> >> @@ -1768,7 +1804,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
> >>   		/* Fill buffer information for the userspace */
> >>   		__fill_v4l2_buffer(vb, b);
> >>
> >> -		dprintk(1, "prepare of buffer %d succeeded\n", vb->v4l2_buf.index);
> >> +		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
> >>   	}
> >>   	return ret;
> >>   }
> >> @@ -1800,7 +1836,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
> >>   	/* Tell the driver to start streaming */
> >>   	q->start_streaming_called = 1;
> >>   	ret = call_qop(q, start_streaming, q,
> >> -		       atomic_read(&q->owned_by_drv_count));
> >> +			atomic_read(&q->owned_by_drv_count));
> >>   	if (!ret)
> >>   		return 0;
> >>
> >> @@ -1810,7 +1846,7 @@ static int vb2_start_streaming(struct vb2_queue *q)
> >>   	/*
> >>   	 * If you see this warning, then the driver isn't cleaning up properly
> >>   	 * after a failed start_streaming(). See the start_streaming()
> >> -	 * documentation in videobuf2-v4l2.h for more information how buffers
> >> +	 * documentation in videobuf2-core.h for more information how buffers
> >>   	 * should be returned to vb2 in start_streaming().
> >>   	 */
> >>   	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
> >> @@ -1841,11 +1877,13 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >>   {
> >>   	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
> >>   	struct vb2_buffer *vb;
> >> +	struct vb2_v4l2_buffer *vbuf;
> >>
> >>   	if (ret)
> >>   		return ret;
> >>
> >>   	vb = q->bufs[b->index];
> >> +	vbuf = to_vb2_v4l2_buffer(vb);
> >>
> >>   	switch (vb->state) {
> >>   	case VB2_BUF_STATE_DEQUEUED:
> >> @@ -1877,11 +1915,11 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >>   		 * and the timecode field and flag if needed.
> >>   		 */
> >>   		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> >> -		    V4L2_BUF_FLAG_TIMESTAMP_COPY)
> >> -			vb->v4l2_buf.timestamp = b->timestamp;
> >> -		vb->v4l2_buf.flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> >> +				V4L2_BUF_FLAG_TIMESTAMP_COPY)
> >> +			vbuf->timestamp = b->timestamp;
> >> +		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> >>   		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> >> -			vb->v4l2_buf.timecode = b->timecode;
> >> +			vbuf->timecode = b->timecode;
> >>   	}
> >>
> >>   	trace_vb2_qbuf(q, vb);
> >> @@ -1903,13 +1941,13 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> >>   	 * then we can finally call start_streaming().
> >>   	 */
> >>   	if (q->streaming && !q->start_streaming_called &&
> >> -	    q->queued_count >= q->min_buffers_needed) {
> >> +			q->queued_count >= q->min_buffers_needed) {
> >>   		ret = vb2_start_streaming(q);
> >>   		if (ret)
> >>   			return ret;
> >>   	}
> >>
> >> -	dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
> >> +	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
> >>   	return 0;
> >>   }
> >>
> >> @@ -2099,9 +2137,11 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
> >>   		}
> >>   }
> >>
> >> -static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
> >> +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> >> +		bool nonblocking)
> >>   {
> >>   	struct vb2_buffer *vb = NULL;
> >> +	struct vb2_v4l2_buffer *vbuf = NULL;
> >>   	int ret;
> >>
> >>   	if (b->type != q->type) {
> >> @@ -2134,14 +2174,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool n
> >>
> >>   	trace_vb2_dqbuf(q, vb);
> >>
> >> +	vbuf = to_vb2_v4l2_buffer(vb);
> >>   	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
> >> -	    vb->v4l2_buf.flags & V4L2_BUF_FLAG_LAST)
> >> +			vbuf->flags & V4L2_BUF_FLAG_LAST)
> >>   		q->last_buffer_dequeued = true;
> >>   	/* go back to dequeued state */
> >>   	__vb2_dqbuf(vb);
> >>
> >>   	dprintk(1, "dqbuf of buffer %d, with state %d\n",
> >> -			vb->v4l2_buf.index, vb->state);
> >> +			vb->index, vb->state);
> >>
> >>   	return 0;
> >>   }
> >> @@ -2197,7 +2238,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
> >>   	/*
> >>   	 * If you see this warning, then the driver isn't cleaning up properly
> >>   	 * in stop_streaming(). See the stop_streaming() documentation in
> >> -	 * videobuf2-v4l2.h for more information how buffers should be returned
> >> +	 * videobuf2-core.h for more information how buffers should be returned
> >>   	 * to vb2 in stop_streaming().
> >>   	 */
> >>   	if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
> >> @@ -2399,7 +2440,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
> >>   		vb = q->bufs[buffer];
> >>
> >>   		for (plane = 0; plane < vb->num_planes; ++plane) {
> >> -			if (vb->v4l2_planes[plane].m.mem_offset == off) {
> >> +			if (vb->planes[plane].m.offset == off) {
> >>   				*_buffer = buffer;
> >>   				*_plane = plane;
> >>   				return 0;
> >> @@ -2557,7 +2598,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> >>   	 * The buffer length was page_aligned at __vb2_buf_mem_alloc(),
> >>   	 * so, we need to do the same here.
> >>   	 */
> >> -	length = PAGE_ALIGN(vb->v4l2_planes[plane].length);
> >> +	length = PAGE_ALIGN(vb->planes[plane].length);
> >>   	if (length < (vma->vm_end - vma->vm_start)) {
> >>   		dprintk(1,
> >>   			"MMAP invalid, as it would overflow buffer length\n");
> >> @@ -2577,10 +2618,10 @@ EXPORT_SYMBOL_GPL(vb2_mmap);
> >>
> >>   #ifndef CONFIG_MMU
> >>   unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
> >> -				    unsigned long addr,
> >> -				    unsigned long len,
> >> -				    unsigned long pgoff,
> >> -				    unsigned long flags)
> >> +					unsigned long addr,
> >> +					unsigned long len,
> >> +					unsigned long pgoff,
> >> +					unsigned long flags)
> >>   {
> >>   	unsigned long off = pgoff << PAGE_SHIFT;
> >>   	struct vb2_buffer *vb;
> >> @@ -2731,7 +2772,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
> >>    * responsible of clearing it's content and setting initial values for some
> >>    * required entries before calling this function.
> >>    * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
> >> - * to the struct vb2_queue description in include/media/videobuf2-v4l2.h
> >> + * to the struct vb2_queue description in include/media/videobuf2-core.h
> >>    * for more information.
> >>    */
> >>   int vb2_queue_init(struct vb2_queue *q)
> >> @@ -2739,16 +2780,16 @@ int vb2_queue_init(struct vb2_queue *q)
> >>   	/*
> >>   	 * Sanity check
> >>   	 */
> >> -	if (WARN_ON(!q)			  ||
> >> -	    WARN_ON(!q->ops)		  ||
> >> -	    WARN_ON(!q->mem_ops)	  ||
> >> -	    WARN_ON(!q->type)		  ||
> >> -	    WARN_ON(!q->io_modes)	  ||
> >> -	    WARN_ON(!q->ops->queue_setup) ||
> >> -	    WARN_ON(!q->ops->buf_queue)   ||
> >> -	    WARN_ON(q->timestamp_flags &
> >> -		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> >> -		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
> >> +	if (WARN_ON(!q)				||
> >> +		WARN_ON(!q->ops)		||
> >> +		WARN_ON(!q->mem_ops)		||
> >> +		WARN_ON(!q->type)		||
> >> +		WARN_ON(!q->io_modes)		||
> >> +		WARN_ON(!q->ops->queue_setup)	||
> >> +		WARN_ON(!q->ops->buf_queue)	||
> >> +		WARN_ON(q->timestamp_flags &
> >> +			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> >> +			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
> >>   		return -EINVAL;
> >>
> >>   	/* Warn that the driver should choose an appropriate timestamp type */
> >> @@ -2852,7 +2893,7 @@ static int __vb2_init_fileio(struct vb2_queue *q, int read)
> >>   	 * Sanity check
> >>   	 */
> >>   	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
> >> -		    (!read && !(q->io_modes & VB2_WRITE))))
> >> +			(!read && !(q->io_modes & VB2_WRITE))))
> >>   		return -EINVAL;
> >>
> >>   	/*
> >> @@ -3063,9 +3104,12 @@ static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_
> >>   		buf->queued = 0;
> >>   		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> >>   				 : vb2_plane_size(q->bufs[index], 0);
> >> -		/* Compensate for data_offset on read in the multiplanar case. */
> >> +		/*
> >> +		 * Compensate for data_offset on read
> >> +		 * in the multiplanar case
> >> +		 */
> >>   		if (is_multiplanar && read &&
> >> -		    fileio->b.m.planes[0].data_offset < buf->size) {
> >> +			fileio->b.m.planes[0].data_offset < buf->size) {
> >>   			buf->pos = fileio->b.m.planes[0].data_offset;
> >>   			buf->size -= buf->pos;
> >>   		}
> >> @@ -3257,7 +3301,7 @@ static int vb2_thread(void *data)
> >>    * contact the linux-media mailinglist first.
> >>    */
> >>   int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> >> -		     const char *thread_name)
> >> +			const char *thread_name)
> >>   {
> >>   	struct vb2_threadio_data *threadio;
> >>   	int ret = 0;
> >> @@ -3491,7 +3535,7 @@ ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> >>   	if (vb2_queue_is_busy(vdev, file))
> >>   		goto exit;
> >>   	err = vb2_write(vdev->queue, buf, count, ppos,
> >> -		       file->f_flags & O_NONBLOCK);
> >> +			file->f_flags & O_NONBLOCK);
> >>   	if (vdev->queue->fileio)
> >>   		vdev->queue->owner = file->private_data;
> >>   exit:
> >> @@ -3515,7 +3559,7 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf,
> >>   	if (vb2_queue_is_busy(vdev, file))
> >>   		goto exit;
> >>   	err = vb2_read(vdev->queue, buf, count, ppos,
> >> -		       file->f_flags & O_NONBLOCK);
> >> +			file->f_flags & O_NONBLOCK);
> >>   	if (vdev->queue->fileio)
> >>   		vdev->queue->owner = file->private_data;
> >>   exit:
> >> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> >> index 155991e..8787a6c 100644
> >> --- a/include/media/videobuf2-core.h
> >> +++ b/include/media/videobuf2-core.h
> >> @@ -115,6 +115,16 @@ struct vb2_plane {
> >>   	void			*mem_priv;
> >>   	struct dma_buf		*dbuf;
> >>   	unsigned int		dbuf_mapped;
> >> +
> >> +	/* plane information */
> >> +	unsigned int		bytesused;
> >> +	unsigned int		length;
> >> +	union {
> >> +		unsigned int	offset;
> >> +		unsigned long	userptr;
> >> +		int		fd;
> >> +	} m;
> >> +	unsigned int		data_offset;
> >>   };
> >
> > Nitpick: it would be good to add a documentation for struct vb2_plane,
> > describing what each field means on this struct. Granted, this could
> > be added after this patch series.
> >
> > Btw, I don't see much reason to have the:
> > 	/* plane information */
> > comment here, as this struct is all about plane information, right?
> > Or, maybe you wanted, instead, to comment that those fields should
> > have what's there at struct v4l2_plane? That would make sense ;)
> 
> Latter is right.
> 
> > So, I would change this comment to something like:
> >
> > 	/*
> > 	 * Should contain enough plane information to contain the
> > 	 * fields needed to fill struct v4l2_plane at videodev2.h
> > 	 */
> >
> OK, I will change it.
> >
> >>
> >>   /**
> >> @@ -161,41 +171,33 @@ struct vb2_queue;
> >>
> >>   /**
> >>    * struct vb2_buffer - represents a video buffer
> >> - * @v4l2_buf:		struct v4l2_buffer associated with this buffer; can
> >> - *			be read by the driver and relevant entries can be
> >> - *			changed by the driver in case of CAPTURE types
> >> - *			(such as timestamp)
> >> - * @v4l2_planes:	struct v4l2_planes associated with this buffer; can
> >> - *			be read by the driver and relevant entries can be
> >> - *			changed by the driver in case of CAPTURE types
> >> - *			(such as bytesused); NOTE that even for single-planar
> >> - *			types, the v4l2_planes[0] struct should be used
> >> - *			instead of v4l2_buf for filling bytesused - drivers
> >> - *			should use the vb2_set_plane_payload() function for that
> >>    * @vb2_queue:		the queue to which this driver belongs
> >> - * @num_planes:		number of planes in the buffer
> >> - *			on an internal driver queue
> >>    * @state:		current buffer state; do not change
> >>    * @queued_entry:	entry on the queued buffers list, which holds all
> >>    *			buffers queued from userspace
> >>    * @done_entry:		entry on the list that stores all buffers ready to
> >>    *			be dequeued to userspace
> >> + * @index:		id number of the buffer
> >> + * @type:		buffer type
> >> + * @memory:		the method, in which the actual data is passed
> >> + * @num_planes:		number of planes in the buffer
> >> + *			on an internal driver queue
> >>    * @planes:		private per-plane information; do not change
> >>    */
> >>   struct vb2_buffer {
> >> -	struct v4l2_buffer	v4l2_buf;
> >> -	struct v4l2_plane	v4l2_planes[VIDEO_MAX_PLANES];
> >> -
> >>   	struct vb2_queue	*vb2_queue;
> >>
> >> -	unsigned int		num_planes;
> >> -
> >> -/* Private: internal use only */
> >> +	/* Private: internal use only */
> >>   	enum vb2_buffer_state	state;
> >>
> >>   	struct list_head	queued_entry;
> >>   	struct list_head	done_entry;
> >>
> >> +	/* buffer information */
> >> +	unsigned int		index;
> >> +	unsigned int		type;
> >> +	unsigned int		memory;
> >> +	unsigned int		num_planes;
> >
> > Nitpick: Those comments that follow Documentation/kernel-doc-nano-HOWTO.txt
> > are used to produce DocBook data, on both html and manpages formats.
> > As documented there, DocBook discards documentation for all fields after a
> > /*private: ...*/ comment.
> >
> > In other words, we need to take care of putting things after /*private:*/
> > only when we're 100% sure that such fields are not meant to be filled/used
> > by the callers, and will be used only internally, and don't deserve any
> > documentation for the kABI.
> >
> > As you're adding documentation for those fields, and num_planes were
> > documented before your series, I suspect that this is not what you want.
> > So, please move them to be before the private: comment.
> 
> Oh, I didn't know that /*private: ...*/ comment have so much meaning.
> I will change it at next round.
> 
> >
> > Btw, if your patches are based on top of the current patchwork tree
> > e. g. if it has this patch:
> > 	http://git.linuxtv.org/cgit.cgi/media_tree.git/commit/?id=d071c833a0d30e7aae0ea565d92ef83c79106d6f
> >
> > Then you can make the Kernel to handle all those kernel-doc-nano
> > comments with:
> >
> > 	make cleandocs && make DOCBOOKS=device-drivers.xml htmldocs
> >
> > It will produce some html pages like:
> > 	http://linuxtv.org/downloads/v4l-dvb-internals/device-drivers/mediadev.html
> >
> > With can be useful to check if the documentation tags are properly placed.
> >
> >>   	struct vb2_plane	planes[VIDEO_MAX_PLANES];
> >>
> >>   #ifdef CONFIG_VIDEO_ADV_DEBUG
> >> @@ -390,7 +392,7 @@ struct v4l2_fh;
> >>    * @threadio:	thread io internal data, used only if thread is active
> >>    */
> >>   struct vb2_queue {
> >> -	enum v4l2_buf_type		type;
> >> +	unsigned int			type;
> >>   	unsigned int			io_modes;
> >>   	unsigned			fileio_read_once:1;
> >>   	unsigned			fileio_write_immediately:1;
> >> @@ -409,7 +411,7 @@ struct vb2_queue {
> >>
> >>   	/* private: internal use only */
> >>   	struct mutex			mmap_lock;
> >> -	enum v4l2_memory		memory;
> >> +	unsigned int			memory;
> >
> > Will the vb2-core use type/memory fields or just vb2-v4l2? As you
> > removed the enum, I suspect you won't be relying on having the videodev2.h
> > header included here, right.
> 
> Exactly.
> 
> >
> > If so, then the meaning of the type/memory fields are private to the
> > caller of the VB2-core  (e. .g. the meaning are private to vb2-v4l2 and
> > vb2-dvb). So, you should be changing the description of those fields
> > at the doc-nano to:
> > ...
> >   * @type: private type whose content is defined by the vb2-core caller.
> >   *        For example, for V4L2, it should match the V4L2_BUF_TYPE_*
> >   *	  in include/uapi/linux/videodev2.h
> > ...
> >
> > to let it clear.
> >
> 
> 0k, I will change it as your comment.
> 
> >>   	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
> >>   	unsigned int			num_buffers;
> >>
> >> @@ -571,7 +573,7 @@ static inline void vb2_set_plane_payload(struct vb2_buffer *vb,
> >>   				 unsigned int plane_no, unsigned long size)
> >>   {
> >>   	if (plane_no < vb->num_planes)
> >> -		vb->v4l2_planes[plane_no].bytesused = size;
> >> +		vb->planes[plane_no].bytesused = size;
> >>   }
> >>
> >>   /**
> >> @@ -583,7 +585,7 @@ static inline unsigned long vb2_get_plane_payload(struct vb2_buffer *vb,
> >>   				 unsigned int plane_no)
> >>   {
> >>   	if (plane_no < vb->num_planes)
> >> -		return vb->v4l2_planes[plane_no].bytesused;
> >> +		return vb->planes[plane_no].bytesused;
> >>   	return 0;
> >>   }
> >>
> >> @@ -596,7 +598,7 @@ static inline unsigned long
> >>   vb2_plane_size(struct vb2_buffer *vb, unsigned int plane_no)
> >>   {
> >>   	if (plane_no < vb->num_planes)
> >> -		return vb->v4l2_planes[plane_no].length;
> >> +		return vb->planes[plane_no].length;
> >>   	return 0;
> >>   }
> >>
> >> diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
> >> index d4a4d9a..fc2dbe9 100644
> >> --- a/include/media/videobuf2-v4l2.h
> >> +++ b/include/media/videobuf2-v4l2.h
> >> @@ -12,6 +12,32 @@
> >>   #ifndef _MEDIA_VIDEOBUF2_V4L2_H
> >>   #define _MEDIA_VIDEOBUF2_V4L2_H
> >>
> >> +#include <linux/videodev2.h>
> >>   #include <media/videobuf2-core.h>
> >>
> >> +/**
> >> + * struct vb2_v4l2_buffer - video buffer information for v4l2
> >> + * @vb2_buf:	video buffer 2
> >> + * @flags:	buffer informational flags
> >> + * @field:	enum v4l2_field; field order of the image in the buffer
> >> + * @timestamp:	frame timestamp
> >> + * @timecode:	frame timecode
> >> + * @sequence:	sequence count of this frame
> >> + */
> >> +struct vb2_v4l2_buffer {
> >> +	struct vb2_buffer	vb2_buf;
> >> +
> >> +	__u32			flags;
> >> +	__u32			field;
> >> +	struct timeval		timestamp;
> >> +	struct v4l2_timecode	timecode;
> >> +	__u32			sequence;
> >> +};
> >> +
> >> +/**
> >> + * to_vb2_v4l2_buffer() - cast struct vb2_buffer * to struct vb2_v4l2_buffer *
> >> + */
> >> +#define to_vb2_v4l2_buffer(vb) \
> >> +	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
> >> +
> >>   #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
> >
> > Regards,
> > Mauro
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-media" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 3/5] media: videobuf2: Modify all device drivers
  2015-08-28  2:19     ` Junghak Sung
@ 2015-08-28  9:14       ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 23+ messages in thread
From: Mauro Carvalho Chehab @ 2015-08-28  9:14 UTC (permalink / raw)
  To: Junghak Sung
  Cc: linux-media, hverkuil, laurent.pinchart, sakari.ailus, pawel,
	inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Em Fri, 28 Aug 2015 11:19:29 +0900
Junghak Sung <jh1009.sung@samsung.com> escreveu:

> Dear Mauro,
> 
> I'm sorry but patch 3 is very incomplete.
> At this round, I could not modify all device drivers,
> because there are too many files to be changed
> and I should change them by hands.
> 
> I just want to be reviewed the modification pattern only before
> I start to modify whole related device drivers.
> I mean that .. most of drivers will be changed with a similar pattern
> ,even though, detailed will be a little different.
> 
> Could you verify whether my modification in this patch is correct?

It is hard to tell without being able to compile ;)

Provided that you don't add uneeded typecases, the compiler do a 
way better job checking those things than humans.

Of course, we still do manual check in order to check border
cases.

Regards,
Mauro

> 
> 
> On 08/27/2015 07:33 PM, Mauro Carvalho Chehab wrote:
> > Em Wed, 26 Aug 2015 20:59:30 +0900
> > Junghak Sung <jh1009.sung@samsung.com> escreveu:
> >
> >> Modify all device drivers related with previous change that restructures
> >> vb2_buffer for common use.
> >> Actually, not all device drivers, yet. So, it required to modifiy more file
> >> to complete this patch.
> >
> > I was expecting to be able to compile everything after applying both
> > patches 2 and 3, but compilation failed:
> >
> > In file included from drivers/media/platform/am437x/am437x-vpfe.c:41:0:
> > drivers/media/platform/am437x/am437x-vpfe.h:107:25: error: field 'vb' has incomplete type
> >    struct vb2_v4l2_buffer vb;
> >                           ^
> > drivers/media/platform/am437x/am437x-vpfe.c: In function 'to_vpfe_buffer':
> > drivers/media/platform/am437x/am437x-vpfe.c:312:72: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
> > drivers/media/platform/am437x/am437x-vpfe.c: In function 'vpfe_buffer_prepare':
> > drivers/media/platform/am437x/am437x-vpfe.c:1952:4: error: 'struct vb2_buffer' has no member named 'v4l2_buf'
> >    vb->v4l2_buf.field = vpfe->fmt.fmt.pix.field;
> >      ^
> > drivers/media/platform/am437x/am437x-vpfe.c: In function 'to_vpfe_buffer':
> > drivers/media/platform/am437x/am437x-vpfe.c:313:1: warning: control reaches end of non-void function [-Wreturn-type]
> >   }
> >   ^
> > scripts/Makefile.build:258: recipe for target 'drivers/media/platform/am437x/am437x-vpfe.o' failed
> > make[3]: *** [drivers/media/platform/am437x/am437x-vpfe.o] Error 1
> > scripts/Makefile.build:403: recipe for target 'drivers/media/platform/am437x' failed
> > make[2]: *** [drivers/media/platform/am437x] Error 2
> > scripts/Makefile.build:403: recipe for target 'drivers/media/platform' failed
> > make[1]: *** [drivers/media/platform] Error 2
> > make[1]: *** Waiting for unfinished jobs....
> > In file included from drivers/media/pci/cobalt/cobalt-driver.c:30:0:
> > drivers/media/pci/cobalt/cobalt-driver.h:209:25: error: field 'vb' has incomplete type
> >    struct vb2_v4l2_buffer vb;
> >                           ^
> > drivers/media/pci/cobalt/cobalt-driver.h: In function 'to_cobalt_buffer':
> > drivers/media/pci/cobalt/cobalt-driver.h:215:70: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
> > scripts/Makefile.build:258: recipe for target 'drivers/media/pci/cobalt/cobalt-driver.o' failed
> > make[3]: *** [drivers/media/pci/cobalt/cobalt-driver.o] Error 1
> > scripts/Makefile.build:403: recipe for target 'drivers/media/pci/cobalt' failed
> > make[2]: *** [drivers/media/pci/cobalt] Error 2
> > scripts/Makefile.build:403: recipe for target 'drivers/media/pci' failed
> > make[1]: *** [drivers/media/pci] Error 2
> > drivers/media/dvb-frontends/rtl2832_sdr.c:110:25: error: field 'vb' has incomplete type
> >    struct vb2_v4l2_buffer vb;   /* common v4l buffer stuff -- must be first */
> >                           ^
> > drivers/media/dvb-frontends/rtl2832_sdr.c: In function 'rtl2832_sdr_buf_queue':
> > drivers/media/dvb-frontends/rtl2832_sdr.c:523:73: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
> > drivers/media/dvb-frontends/rtl2832_sdr.c:523:73: note: (near initialization for 'buf')
> > scripts/Makefile.build:258: recipe for target 'drivers/media/dvb-frontends/rtl2832_sdr.o' failed
> > make[2]: *** [drivers/media/dvb-frontends/rtl2832_sdr.o] Error 1
> > scripts/Makefile.build:403: recipe for target 'drivers/media/dvb-frontends' failed
> > make[1]: *** [drivers/media/dvb-frontends] Error 2
> > Makefile:1380: recipe for target '_module_drivers/media' failed
> > make: *** [_module_drivers/media] Error 2
> >
> >
> > So, obviously there's something wrong there. Please fix.
> >
> > I'll skip this patch from my review.
> >
> > Thanks!
> > Mauro
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-media" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer
  2015-08-26 11:59 ` [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer Junghak Sung
  2015-08-27 10:28   ` Mauro Carvalho Chehab
@ 2015-08-28 13:31   ` Hans Verkuil
  2015-08-31  2:01     ` Junghak Sung
  1 sibling, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2015-08-28 13:31 UTC (permalink / raw)
  To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
	sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Hi Junghak,

Thanks for this patch, it looks much better. I do have a number of comments, though...

On 08/26/2015 01:59 PM, Junghak Sung wrote:
> Remove v4l2-specific stuff from struct vb2_buffer and add member variables
> related with buffer management.
> 
> struct vb2_plane {
>         <snip>
>         /* plane information */
>         unsigned int            bytesused;
>         unsigned int            length;
>         union {
>                 unsigned int    offset;
>                 unsigned long   userptr;
>                 int             fd;
>         } m;
>         unsigned int            data_offset;
> }
> 
> struct vb2_buffer {
>         <snip>
>         /* buffer information */
>         unsigned int            num_planes;
>         unsigned int            index;
>         unsigned int            type;
>         unsigned int            memory;
> 
>         struct vb2_plane        planes[VIDEO_MAX_PLANES];
>         <snip>
> };
> 
> And create struct vb2_v4l2_buffer as container buffer for v4l2 use.
> 
> struct vb2_v4l2_buffer {
>         struct vb2_buffer       vb2_buf;
> 
>         __u32                   flags;
>         __u32                   field;
>         struct timeval          timestamp;
>         struct v4l2_timecode    timecode;
>         __u32                   sequence;
> };
> 
> This patch includes only changes inside of videobuf2. So, it is required to
> modify all device drivers which use videobuf2.
> 
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>
> ---
>  drivers/media/v4l2-core/videobuf2-core.c |  324 +++++++++++++++++-------------
>  include/media/videobuf2-core.h           |   50 ++---
>  include/media/videobuf2-v4l2.h           |   26 +++
>  3 files changed, 236 insertions(+), 164 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> index ab00ea0..9266d50 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> @@ -35,10 +35,10 @@
>  static int debug;
>  module_param(debug, int, 0644);
>  
> -#define dprintk(level, fmt, arg...)					      \
> -	do {								      \
> -		if (debug >= level)					      \
> -			pr_info("vb2: %s: " fmt, __func__, ## arg); \
> +#define dprintk(level, fmt, arg...)					\
> +	do {								\
> +		if (debug >= level)					\
> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\

These are just whitespace changes, and that is something it see *a lot* in this
patch. And usually for no clear reason.

Please remove those whitespace changes, it makes a difficult patch even harder
to read than it already is.

>  	} while (0)
>  
>  #ifdef CONFIG_VIDEO_ADV_DEBUG

<snip>

> @@ -656,12 +652,21 @@ static bool __buffers_in_use(struct vb2_queue *q)
>   */
>  static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>  {
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>  	struct vb2_queue *q = vb->vb2_queue;
> +	unsigned int plane;
>  
>  	/* Copy back data such as timestamp, flags, etc. */
> -	memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
> -	b->reserved2 = vb->v4l2_buf.reserved2;
> -	b->reserved = vb->v4l2_buf.reserved;

Hmm, I'm not sure why these reserved fields were copied here. I think it was
for compatibility reasons for some old drivers that abused the reserved field.
However, in the new code these reserved fields should probably be explicitly
initialized to 0.

> +	b->index = vb->index;
> +	b->type = vb->type;
> +	b->memory = vb->memory;
> +	b->bytesused = 0;
> +
> +	b->flags = vbuf->flags;
> +	b->field = vbuf->field;
> +	b->timestamp = vbuf->timestamp;
> +	b->timecode = vbuf->timecode;
> +	b->sequence = vbuf->sequence;
>  
>  	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>  		/*
> @@ -669,21 +674,33 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>  		 * for it. The caller has already verified memory and size.
>  		 */
>  		b->length = vb->num_planes;
> -		memcpy(b->m.planes, vb->v4l2_planes,
> -			b->length * sizeof(struct v4l2_plane));

A similar problem occurs here: the memcpy would have copied the reserved
field in v4l2_plane as well, but that no longer happens, so you need to
do an explicit memset for the reserved field in the new code.

> +		for (plane = 0; plane < vb->num_planes; ++plane) {
> +			struct v4l2_plane *pdst = &b->m.planes[plane];
> +			struct vb2_plane *psrc = &vb->planes[plane];
> +
> +			pdst->bytesused = psrc->bytesused;
> +			pdst->length = psrc->length;
> +			if (q->memory == V4L2_MEMORY_MMAP)
> +				pdst->m.mem_offset = psrc->m.offset;
> +			else if (q->memory == V4L2_MEMORY_USERPTR)
> +				pdst->m.userptr = psrc->m.userptr;
> +			else if (q->memory == V4L2_MEMORY_DMABUF)
> +				pdst->m.fd = psrc->m.fd;
> +			pdst->data_offset = psrc->data_offset;
> +		}
>  	} else {
>  		/*
>  		 * We use length and offset in v4l2_planes array even for
>  		 * single-planar buffers, but userspace does not.
>  		 */
> -		b->length = vb->v4l2_planes[0].length;
> -		b->bytesused = vb->v4l2_planes[0].bytesused;
> +		b->length = vb->planes[0].length;
> +		b->bytesused = vb->planes[0].bytesused;
>  		if (q->memory == V4L2_MEMORY_MMAP)
> -			b->m.offset = vb->v4l2_planes[0].m.mem_offset;
> +			b->m.offset = vb->planes[0].m.offset;
>  		else if (q->memory == V4L2_MEMORY_USERPTR)
> -			b->m.userptr = vb->v4l2_planes[0].m.userptr;
> +			b->m.userptr = vb->planes[0].m.userptr;
>  		else if (q->memory == V4L2_MEMORY_DMABUF)
> -			b->m.fd = vb->v4l2_planes[0].m.fd;
> +			b->m.fd = vb->planes[0].m.fd;
>  	}
>  
>  	/*
> @@ -692,7 +709,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>  	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>  	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>  	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> -	    V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>  		/*
>  		 * For non-COPY timestamps, drop timestamp source bits
>  		 * and obtain the timestamp source from the queue.
> @@ -767,7 +784,7 @@ EXPORT_SYMBOL(vb2_querybuf);
>  static int __verify_userptr_ops(struct vb2_queue *q)
>  {
>  	if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
> -	    !q->mem_ops->put_userptr)
> +			!q->mem_ops->put_userptr)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -780,7 +797,7 @@ static int __verify_userptr_ops(struct vb2_queue *q)
>  static int __verify_mmap_ops(struct vb2_queue *q)
>  {
>  	if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
> -	    !q->mem_ops->put || !q->mem_ops->mmap)
> +			!q->mem_ops->put || !q->mem_ops->mmap)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -793,8 +810,8 @@ static int __verify_mmap_ops(struct vb2_queue *q)
>  static int __verify_dmabuf_ops(struct vb2_queue *q)
>  {
>  	if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
> -	    !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
> -	    !q->mem_ops->unmap_dmabuf)
> +		!q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
> +		!q->mem_ops->unmap_dmabuf)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -808,7 +825,7 @@ static int __verify_memory_type(struct vb2_queue *q,
>  		enum v4l2_memory memory, enum v4l2_buf_type type)
>  {
>  	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
> -	    memory != V4L2_MEMORY_DMABUF) {
> +			memory != V4L2_MEMORY_DMABUF) {
>  		dprintk(1, "unsupported memory type\n");
>  		return -EINVAL;
>  	}
> @@ -927,7 +944,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  	 * Driver also sets the size and allocator context for each plane.
>  	 */
>  	ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
> -		       q->plane_sizes, q->alloc_ctx);
> +			q->plane_sizes, q->alloc_ctx);
>  	if (ret)
>  		return ret;
>  
> @@ -952,7 +969,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  		num_buffers = allocated_buffers;
>  
>  		ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
> +				&num_planes, q->plane_sizes, q->alloc_ctx);
>  
>  		if (!ret && allocated_buffers < num_buffers)
>  			ret = -ENOMEM;
> @@ -1040,7 +1057,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  	 * buffer and their sizes are acceptable
>  	 */
>  	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> -		       &num_planes, q->plane_sizes, q->alloc_ctx);
> +			&num_planes, q->plane_sizes, q->alloc_ctx);
>  	if (ret)
>  		return ret;
>  
> @@ -1063,7 +1080,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  		 * queue driver has set up
>  		 */
>  		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
> +				&num_planes, q->plane_sizes, q->alloc_ctx);
>  
>  		if (!ret && allocated_buffers < num_buffers)
>  			ret = -ENOMEM;
> @@ -1183,8 +1200,8 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
>  		return;
>  
>  	if (WARN_ON(state != VB2_BUF_STATE_DONE &&
> -		    state != VB2_BUF_STATE_ERROR &&
> -		    state != VB2_BUF_STATE_QUEUED))
> +		state != VB2_BUF_STATE_ERROR &&
> +		state != VB2_BUF_STATE_QUEUED))
>  		state = VB2_BUF_STATE_ERROR;
>  
>  #ifdef CONFIG_VIDEO_ADV_DEBUG

All the chunks above are all spurious whitespace changes. As mentioned in the beginning,
please remove all those pointless whitespace changes!

There are a lot more of these, but I won't comment on them anymore.

Basically this patch looks good to me, so once I have the next version without all the
whitespace confusion and with the reserved field issues solved I'll do a final review.

BTW, did you test this with 'v4l2-compliance -s' and with the vivid driver? Just to
make sure you didn't break anything.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts
  2015-08-26 11:59 ` [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts Junghak Sung
  2015-08-27 11:43   ` Mauro Carvalho Chehab
@ 2015-08-28 13:50   ` Hans Verkuil
  2015-08-31  2:08     ` Junghak Sung
  1 sibling, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2015-08-28 13:50 UTC (permalink / raw)
  To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
	sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

On 08/26/2015 01:59 PM, Junghak Sung wrote:
> Divide videobuf2-core into core part and v4l2-specific part
> - core part: videobuf2 core related with buffer management & memory
>  allocation
> - v4l2-specific part: v4l2-specific stuff
> 
> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Acked-by: Inki Dae <inki.dae@samsung.com>

As Mauro also noted, this patch is very hard to review. I think you can reduce
the changes to some extent: the creation of the videobuf2-internal.h header
can certainly be done first.

After that you can make a patch that just moves functions from core.c to v4l2.c.
E.g. a function like vb2_ioctl_prepare_buf() isn't changed, just moved. And there
are lots of those.

Patches that just move things around without doing any functional changes are
easy to review and they reduce the size of the patch that actually does make
functional changes and thus needs a much more careful review.

There may well be more ways of splitting up this large patch, but I think the
two suggestions I made above will already go a long way to making this more
manageable.

Regards,

	Hans

> ---
>  drivers/media/v4l2-core/videobuf2-core.c     | 1933 +++-----------------------
>  drivers/media/v4l2-core/videobuf2-internal.h |  184 +++
>  drivers/media/v4l2-core/videobuf2-v4l2.c     | 1640 ++++++++++++++++++++++
>  include/media/videobuf2-core.h               |  157 +--
>  include/media/videobuf2-v4l2.h               |  116 ++
>  include/trace/events/v4l2.h                  |    4 +-
>  6 files changed, 2154 insertions(+), 1880 deletions(-)
>  create mode 100644 drivers/media/v4l2-core/videobuf2-internal.h
> 
> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
> index 9266d50..2cd4241 100644
> --- a/drivers/media/v4l2-core/videobuf2-core.c
> +++ b/drivers/media/v4l2-core/videobuf2-core.c
> @@ -6,9 +6,6 @@
>   * Author: Pawel Osciak <pawel@osciak.com>
>   *	   Marek Szyprowski <m.szyprowski@samsung.com>
>   *
> - * The vb2_thread implementation was based on code from videobuf-dvb.c:
> - *	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
> - *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License as published by
>   * the Free Software Foundation.
> @@ -24,164 +21,14 @@
>  #include <linux/freezer.h>
>  #include <linux/kthread.h>
>  
> -#include <media/v4l2-dev.h>
> -#include <media/v4l2-fh.h>
> -#include <media/v4l2-event.h>
> -#include <media/v4l2-common.h>
> -#include <media/videobuf2-v4l2.h>
> +#include <media/videobuf2-core.h>
> +#include "videobuf2-internal.h"
>  
>  #include <trace/events/v4l2.h>
>  
> -static int debug;
> -module_param(debug, int, 0644);
> -
> -#define dprintk(level, fmt, arg...)					\
> -	do {								\
> -		if (debug >= level)					\
> -			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
> -	} while (0)
> -
> -#ifdef CONFIG_VIDEO_ADV_DEBUG
> -
> -/*
> - * If advanced debugging is on, then count how often each op is called
> - * successfully, which can either be per-buffer or per-queue.
> - *
> - * This makes it easy to check that the 'init' and 'cleanup'
> - * (and variations thereof) stay balanced.
> - */
> -
> -#define log_memop(vb, op)						\
> -	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
> -		(vb)->vb2_queue, (vb)->index, #op,			\
> -		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
> -
> -#define call_memop(vb, op, args...)					\
> -({									\
> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
> -	int err;							\
> -									\
> -	log_memop(vb, op);						\
> -	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
> -	if (!err)							\
> -		(vb)->cnt_mem_ ## op++;					\
> -	err;								\
> -})
> -
> -#define call_ptr_memop(vb, op, args...)					\
> -({									\
> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
> -	void *ptr;							\
> -									\
> -	log_memop(vb, op);						\
> -	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
> -	if (!IS_ERR_OR_NULL(ptr))					\
> -		(vb)->cnt_mem_ ## op++;					\
> -	ptr;								\
> -})
> -
> -#define call_void_memop(vb, op, args...)				\
> -({									\
> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
> -									\
> -	log_memop(vb, op);						\
> -	if (_q->mem_ops->op)						\
> -		_q->mem_ops->op(args);					\
> -	(vb)->cnt_mem_ ## op++;						\
> -})
> -
> -#define log_qop(q, op)							\
> -	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
> -		(q)->ops->op ? "" : " (nop)")
> -
> -#define call_qop(q, op, args...)					\
> -({									\
> -	int err;							\
> -									\
> -	log_qop(q, op);							\
> -	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
> -	if (!err)							\
> -		(q)->cnt_ ## op++;					\
> -	err;								\
> -})
> -
> -#define call_void_qop(q, op, args...)					\
> -({									\
> -	log_qop(q, op);							\
> -	if ((q)->ops->op)						\
> -		(q)->ops->op(args);					\
> -	(q)->cnt_ ## op++;						\
> -})
> -
> -#define log_vb_qop(vb, op, args...)					\
> -	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
> -		(vb)->vb2_queue, (vb)->index, #op,			\
> -		(vb)->vb2_queue->ops->op ? "" : " (nop)")
> -
> -#define call_vb_qop(vb, op, args...)					\
> -({									\
> -	int err;							\
> -									\
> -	log_vb_qop(vb, op);						\
> -	err = (vb)->vb2_queue->ops->op ?				\
> -		(vb)->vb2_queue->ops->op(args) : 0;			\
> -	if (!err)							\
> -		(vb)->cnt_ ## op++;					\
> -	err;								\
> -})
> -
> -#define call_void_vb_qop(vb, op, args...)				\
> -({									\
> -	log_vb_qop(vb, op);						\
> -	if ((vb)->vb2_queue->ops->op)					\
> -		(vb)->vb2_queue->ops->op(args);				\
> -	(vb)->cnt_ ## op++;						\
> -})
> -
> -#else
> -
> -#define call_memop(vb, op, args...)					\
> -	((vb)->vb2_queue->mem_ops->op ?					\
> -		(vb)->vb2_queue->mem_ops->op(args) : 0)
> -
> -#define call_ptr_memop(vb, op, args...)					\
> -	((vb)->vb2_queue->mem_ops->op ?					\
> -		(vb)->vb2_queue->mem_ops->op(args) : NULL)
> -
> -#define call_void_memop(vb, op, args...)				\
> -	do {								\
> -		if ((vb)->vb2_queue->mem_ops->op)			\
> -			(vb)->vb2_queue->mem_ops->op(args);		\
> -	} while (0)
> -
> -#define call_qop(q, op, args...)					\
> -	((q)->ops->op ? (q)->ops->op(args) : 0)
> -
> -#define call_void_qop(q, op, args...)					\
> -	do {								\
> -		if ((q)->ops->op)					\
> -			(q)->ops->op(args);				\
> -	} while (0)
> -
> -#define call_vb_qop(vb, op, args...)					\
> -	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
> -
> -#define call_void_vb_qop(vb, op, args...)				\
> -	do {								\
> -		if ((vb)->vb2_queue->ops->op)				\
> -			(vb)->vb2_queue->ops->op(args);			\
> -	} while (0)
> -
> -#endif
> -
> -/* Flags that are set by the vb2 core */
> -#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
> -				 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
> -				 V4L2_BUF_FLAG_PREPARED | \
> -				 V4L2_BUF_FLAG_TIMESTAMP_MASK)
> -/* Output buffer flags that should be passed on to the driver */
> -#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
> -				 V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
> +int vb2_debug;
> +module_param_named(debug, vb2_debug, int, 0644);
> +EXPORT_SYMBOL_GPL(vb2_debug);
>  
>  static void __vb2_queue_cancel(struct vb2_queue *q);
>  static void __enqueue_in_driver(struct vb2_buffer *vb);
> @@ -193,7 +40,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
>  {
>  	struct vb2_queue *q = vb->vb2_queue;
>  	enum dma_data_direction dma_dir =
> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> +			q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>  	void *mem_priv;
>  	int plane;
>  
> @@ -249,7 +96,8 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
>  
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		if (vb->planes[plane].mem_priv)
> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
> +			call_void_memop(vb, put_userptr,
> +					vb->planes[plane].mem_priv);
>  		vb->planes[plane].mem_priv = NULL;
>  	}
>  }
> @@ -347,7 +195,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>   *
>   * Returns the number of buffers successfully allocated.
>   */
> -static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
> +static int __vb2_queue_alloc(struct vb2_queue *q, unsigned int memory,
>  			unsigned int num_buffers, unsigned int num_planes)
>  {
>  	unsigned int buffer;
> @@ -370,7 +218,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>  		vb->memory = memory;
>  
>  		/* Allocate video buffer memory for the MMAP type */
> -		if (memory == V4L2_MEMORY_MMAP) {
> +		if (memory == VB2_MEMORY_MMAP) {
>  			ret = __vb2_buf_mem_alloc(vb);
>  			if (ret) {
>  				dprintk(1, "failed allocating memory for "
> @@ -397,7 +245,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>  	}
>  
>  	__setup_lengths(q, buffer);
> -	if (memory == V4L2_MEMORY_MMAP)
> +	if (memory == VB2_MEMORY_MMAP)
>  		__setup_offsets(q, buffer);
>  
>  	dprintk(1, "allocated %d buffers, %d plane(s) each\n",
> @@ -421,9 +269,9 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>  			continue;
>  
>  		/* Free MMAP buffers or release USERPTR buffers */
> -		if (q->memory == V4L2_MEMORY_MMAP)
> +		if (q->memory == VB2_MEMORY_MMAP)
>  			__vb2_buf_mem_free(vb);
> -		else if (q->memory == V4L2_MEMORY_DMABUF)
> +		else if (q->memory == VB2_MEMORY_DMABUF)
>  			__vb2_buf_dmabuf_put(vb);
>  		else
>  			__vb2_buf_userptr_put(vb);
> @@ -547,75 +395,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>  }
>  
>  /**
> - * __verify_planes_array() - verify that the planes array passed in struct
> - * v4l2_buffer from userspace can be safely used
> - */
> -static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> -{
> -	if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
> -		return 0;
> -
> -	/* Is memory for copying plane information present? */
> -	if (NULL == b->m.planes) {
> -		dprintk(1, "multi-planar buffer passed but "
> -			   "planes array not provided\n");
> -		return -EINVAL;
> -	}
> -
> -	if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
> -		dprintk(1, "incorrect planes array length, "
> -			   "expected %d, got %d\n", vb->num_planes, b->length);
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -/**
> - * __verify_length() - Verify that the bytesused value for each plane fits in
> - * the plane length and that the data offset doesn't exceed the bytesused value.
> - */
> -static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> -{
> -	unsigned int length;
> -	unsigned int bytesused;
> -	unsigned int plane;
> -
> -	if (!V4L2_TYPE_IS_OUTPUT(b->type))
> -		return 0;
> -
> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> -		for (plane = 0; plane < vb->num_planes; ++plane) {
> -			length = (b->memory == V4L2_MEMORY_USERPTR ||
> -				b->memory == V4L2_MEMORY_DMABUF)
> -				? b->m.planes[plane].length
> -				: vb->planes[plane].length;
> -			bytesused = b->m.planes[plane].bytesused
> -				? b->m.planes[plane].bytesused : length;
> -
> -			if (b->m.planes[plane].bytesused > length)
> -				return -EINVAL;
> -
> -			if (b->m.planes[plane].data_offset > 0 &&
> -				b->m.planes[plane].data_offset >= bytesused)
> -				return -EINVAL;
> -		}
> -	} else {
> -		length = (b->memory == V4L2_MEMORY_USERPTR)
> -			? b->length : vb->planes[0].length;
> -
> -		if (b->bytesused > length)
> -			return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -/**
> - * __buffer_in_use() - return true if the buffer is in use and
> + * vb2_buffer_in_use() - return true if the buffer is in use and
>   * the queue cannot be freed (by the means of REQBUFS(0)) call
>   */
> -static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>  {
>  	unsigned int plane;
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
> @@ -631,6 +414,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>  	}
>  	return false;
>  }
> +EXPORT_SYMBOL_GPL(vb2_buffer_in_use);
>  
>  /**
>   * __buffers_in_use() - return true if any buffers on the queue are in use and
> @@ -640,142 +424,26 @@ static bool __buffers_in_use(struct vb2_queue *q)
>  {
>  	unsigned int buffer;
>  	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
> -		if (__buffer_in_use(q, q->bufs[buffer]))
> +		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>  			return true;
>  	}
>  	return false;
>  }
>  
>  /**
> - * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
> - * returned to userspace
> - */
> -static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
> -{
> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> -	struct vb2_queue *q = vb->vb2_queue;
> -	unsigned int plane;
> -
> -	/* Copy back data such as timestamp, flags, etc. */
> -	b->index = vb->index;
> -	b->type = vb->type;
> -	b->memory = vb->memory;
> -	b->bytesused = 0;
> -
> -	b->flags = vbuf->flags;
> -	b->field = vbuf->field;
> -	b->timestamp = vbuf->timestamp;
> -	b->timecode = vbuf->timecode;
> -	b->sequence = vbuf->sequence;
> -
> -	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
> -		/*
> -		 * Fill in plane-related data if userspace provided an array
> -		 * for it. The caller has already verified memory and size.
> -		 */
> -		b->length = vb->num_planes;
> -		for (plane = 0; plane < vb->num_planes; ++plane) {
> -			struct v4l2_plane *pdst = &b->m.planes[plane];
> -			struct vb2_plane *psrc = &vb->planes[plane];
> -
> -			pdst->bytesused = psrc->bytesused;
> -			pdst->length = psrc->length;
> -			if (q->memory == V4L2_MEMORY_MMAP)
> -				pdst->m.mem_offset = psrc->m.offset;
> -			else if (q->memory == V4L2_MEMORY_USERPTR)
> -				pdst->m.userptr = psrc->m.userptr;
> -			else if (q->memory == V4L2_MEMORY_DMABUF)
> -				pdst->m.fd = psrc->m.fd;
> -			pdst->data_offset = psrc->data_offset;
> -		}
> -	} else {
> -		/*
> -		 * We use length and offset in v4l2_planes array even for
> -		 * single-planar buffers, but userspace does not.
> -		 */
> -		b->length = vb->planes[0].length;
> -		b->bytesused = vb->planes[0].bytesused;
> -		if (q->memory == V4L2_MEMORY_MMAP)
> -			b->m.offset = vb->planes[0].m.offset;
> -		else if (q->memory == V4L2_MEMORY_USERPTR)
> -			b->m.userptr = vb->planes[0].m.userptr;
> -		else if (q->memory == V4L2_MEMORY_DMABUF)
> -			b->m.fd = vb->planes[0].m.fd;
> -	}
> -
> -	/*
> -	 * Clear any buffer state related flags.
> -	 */
> -	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
> -	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
> -	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> -			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> -		/*
> -		 * For non-COPY timestamps, drop timestamp source bits
> -		 * and obtain the timestamp source from the queue.
> -		 */
> -		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> -		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> -	}
> -
> -	switch (vb->state) {
> -	case VB2_BUF_STATE_QUEUED:
> -	case VB2_BUF_STATE_ACTIVE:
> -		b->flags |= V4L2_BUF_FLAG_QUEUED;
> -		break;
> -	case VB2_BUF_STATE_ERROR:
> -		b->flags |= V4L2_BUF_FLAG_ERROR;
> -		/* fall through */
> -	case VB2_BUF_STATE_DONE:
> -		b->flags |= V4L2_BUF_FLAG_DONE;
> -		break;
> -	case VB2_BUF_STATE_PREPARED:
> -		b->flags |= V4L2_BUF_FLAG_PREPARED;
> -		break;
> -	case VB2_BUF_STATE_PREPARING:
> -	case VB2_BUF_STATE_DEQUEUED:
> -		/* nothing */
> -		break;
> -	}
> -
> -	if (__buffer_in_use(q, vb))
> -		b->flags |= V4L2_BUF_FLAG_MAPPED;
> -}
> -
> -/**
> - * vb2_querybuf() - query video buffer information
> + * vb2_core_querybuf() - query video buffer information
>   * @q:		videobuf queue
> + * @index:	id number of the buffer
>   * @b:		buffer struct passed from userspace to vidioc_querybuf handler
>   *		in driver
> - *
> - * Should be called from vidioc_querybuf ioctl handler in driver.
> - * This function will verify the passed v4l2_buffer structure and fill the
> - * relevant information for the userspace.
> - *
> - * The return values from this function are intended to be directly returned
> - * from vidioc_querybuf handler in driver.
>   */
> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>  {
> -	struct vb2_buffer *vb;
> -	int ret;
> -
> -	if (b->type != q->type) {
> -		dprintk(1, "wrong buffer type\n");
> -		return -EINVAL;
> -	}
> +	call_bufop(q, fill_user_buffer, q->bufs[index], pb);
>  
> -	if (b->index >= q->num_buffers) {
> -		dprintk(1, "buffer index out of range\n");
> -		return -EINVAL;
> -	}
> -	vb = q->bufs[b->index];
> -	ret = __verify_planes_array(vb, b);
> -	if (!ret)
> -		__fill_v4l2_buffer(vb, b);
> -	return ret;
> +	return 0;
>  }
> -EXPORT_SYMBOL(vb2_querybuf);
> +EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>  
>  /**
>   * __verify_userptr_ops() - verify that all memory operations required for
> @@ -818,14 +486,14 @@ static int __verify_dmabuf_ops(struct vb2_queue *q)
>  }
>  
>  /**
> - * __verify_memory_type() - Check whether the memory type and buffer type
> + * vb2_verify_memory_type() - Check whether the memory type and buffer type
>   * passed to a buffer operation are compatible with the queue.
>   */
> -static int __verify_memory_type(struct vb2_queue *q,
> -		enum v4l2_memory memory, enum v4l2_buf_type type)
> +int vb2_verify_memory_type(struct vb2_queue *q,
> +		unsigned int memory, unsigned int type)
>  {
> -	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
> -			memory != V4L2_MEMORY_DMABUF) {
> +	if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
> +		memory != VB2_MEMORY_DMABUF) {
>  		dprintk(1, "unsupported memory type\n");
>  		return -EINVAL;
>  	}
> @@ -839,37 +507,30 @@ static int __verify_memory_type(struct vb2_queue *q,
>  	 * Make sure all the required memory ops for given memory type
>  	 * are available.
>  	 */
> -	if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
> +	if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
>  		dprintk(1, "MMAP for current setup unsupported\n");
>  		return -EINVAL;
>  	}
>  
> -	if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
> +	if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
>  		dprintk(1, "USERPTR for current setup unsupported\n");
>  		return -EINVAL;
>  	}
>  
> -	if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
> +	if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
>  		dprintk(1, "DMABUF for current setup unsupported\n");
>  		return -EINVAL;
>  	}
>  
> -	/*
> -	 * Place the busy tests at the end: -EBUSY can be ignored when
> -	 * create_bufs is called with count == 0, but count == 0 should still
> -	 * do the memory and type validation.
> -	 */
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(vb2_verify_memory_type);
>  
>  /**
> - * __reqbufs() - Initiate streaming
> + * vb2_core_reqbufs() - Initiate streaming
>   * @q:		videobuf2 queue
> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
> + * @memory:
> + * @count:
>   *
>   * Should be called from vidioc_reqbufs ioctl handler of a driver.
>   * This function:
> @@ -889,7 +550,8 @@ static int __verify_memory_type(struct vb2_queue *q,
>   * The return values from this function are intended to be directly returned
>   * from vidioc_reqbufs handler in driver.
>   */
> -static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
> +		unsigned int *count)
>  {
>  	unsigned int num_buffers, allocated_buffers, num_planes = 0;
>  	int ret;
> @@ -899,13 +561,13 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  		return -EBUSY;
>  	}
>  
> -	if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
> +	if (*count == 0 || q->num_buffers != 0 || q->memory != memory) {
>  		/*
>  		 * We already have buffers allocated, so first check if they
>  		 * are not in use and can be freed.
>  		 */
>  		mutex_lock(&q->mmap_lock);
> -		if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) {
> +		if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
>  			mutex_unlock(&q->mmap_lock);
>  			dprintk(1, "memory in use, cannot free\n");
>  			return -EBUSY;
> @@ -926,18 +588,18 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  		 * In case of REQBUFS(0) return immediately without calling
>  		 * driver's queue_setup() callback and allocating resources.
>  		 */
> -		if (req->count == 0)
> +		if (*count == 0)
>  			return 0;
>  	}
>  
>  	/*
>  	 * Make sure the requested values and current defaults are sane.
>  	 */
> -	num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
> +	num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME);
>  	num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed);
>  	memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
>  	memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
> -	q->memory = req->memory;
> +	q->memory = memory;
>  
>  	/*
>  	 * Ask the driver how many buffers and planes per buffer it requires.
> @@ -949,7 +611,8 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  		return ret;
>  
>  	/* Finally, allocate buffers and video memory */
> -	allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
> +	allocated_buffers =
> +		__vb2_queue_alloc(q, memory, num_buffers, num_planes);
>  	if (allocated_buffers == 0) {
>  		dprintk(1, "memory allocation failed\n");
>  		return -ENOMEM;
> @@ -998,28 +661,15 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>  	 * Return the number of successfully allocated buffers
>  	 * to the userspace.
>  	 */
> -	req->count = allocated_buffers;
> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
> +	*count = allocated_buffers;
> +	q->waiting_for_buffers = !q->is_output;
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
>  
>  /**
> - * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and
> - * type values.
> - * @q:		videobuf2 queue
> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
> - */
> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> -{
> -	int ret = __verify_memory_type(q, req->memory, req->type);
> -
> -	return ret ? ret : __reqbufs(q, req);
> -}
> -EXPORT_SYMBOL_GPL(vb2_reqbufs);
> -
> -/**
> - * __create_bufs() - Allocate buffers and any required auxiliary structs
> + * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs
>   * @q:		videobuf2 queue
>   * @create:	creation parameters, passed from userspace to vidioc_create_bufs
>   *		handler in driver
> @@ -1033,12 +683,13 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs);
>   * The return values from this function are intended to be directly returned
>   * from vidioc_create_bufs handler in driver.
>   */
> -static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
> +		unsigned int *count, void *parg)
>  {
>  	unsigned int num_planes = 0, num_buffers, allocated_buffers;
>  	int ret;
>  
> -	if (q->num_buffers == VIDEO_MAX_FRAME) {
> +	if (q->num_buffers == VB2_MAX_FRAME) {
>  		dprintk(1, "maximum number of buffers already allocated\n");
>  		return -ENOBUFS;
>  	}
> @@ -1046,23 +697,23 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  	if (!q->num_buffers) {
>  		memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
>  		memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
> -		q->memory = create->memory;
> -		q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
> +		q->memory = memory;
> +		q->waiting_for_buffers = !q->is_output;
>  	}
>  
> -	num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
> +	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
>  
>  	/*
>  	 * Ask the driver, whether the requested number of buffers, planes per
>  	 * buffer and their sizes are acceptable
>  	 */
> -	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> +	ret = call_qop(q, queue_setup, q, parg, &num_buffers,
>  			&num_planes, q->plane_sizes, q->alloc_ctx);
>  	if (ret)
>  		return ret;
>  
>  	/* Finally, allocate buffers and video memory */
> -	allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers,
> +	allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
>  				num_planes);
>  	if (allocated_buffers == 0) {
>  		dprintk(1, "memory allocation failed\n");
> @@ -1079,7 +730,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  		 * q->num_buffers contains the total number of buffers, that the
>  		 * queue driver has set up
>  		 */
> -		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
> +		ret = call_qop(q, queue_setup, q, parg, &num_buffers,
>  				&num_planes, q->plane_sizes, q->alloc_ctx);
>  
>  		if (!ret && allocated_buffers < num_buffers)
> @@ -1109,28 +760,11 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>  	 * Return the number of successfully allocated buffers
>  	 * to the userspace.
>  	 */
> -	create->count = allocated_buffers;
> +	*count = allocated_buffers;
>  
>  	return 0;
>  }
> -
> -/**
> - * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the
> - * memory and type values.
> - * @q:		videobuf2 queue
> - * @create:	creation parameters, passed from userspace to vidioc_create_bufs
> - *		handler in driver
> - */
> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
> -{
> -	int ret = __verify_memory_type(q, create->memory, create->format.type);
> -
> -	create->index = q->num_buffers;
> -	if (create->count == 0)
> -		return ret != -EBUSY ? ret : 0;
> -	return ret ? ret : __create_bufs(q, create);
> -}
> -EXPORT_SYMBOL_GPL(vb2_create_bufs);
> +EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
>  
>  /**
>   * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
> @@ -1263,7 +897,7 @@ void vb2_discard_done(struct vb2_queue *q)
>  }
>  EXPORT_SYMBOL_GPL(vb2_discard_done);
>  
> -static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>  {
>  	static bool __check_once __read_mostly;
>  
> @@ -1279,162 +913,34 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>  	else
>  		pr_warn_once("use the actual size instead.\n");
>  }
> -
> -/**
> - * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
> - * v4l2_buffer by the userspace. The caller has already verified that struct
> - * v4l2_buffer has a valid number of planes.
> - */
> -static void __fill_vb2_buffer(struct vb2_buffer *vb,
> -		const struct v4l2_buffer *b, struct vb2_plane *planes)
> -{
> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> -	unsigned int plane;
> -
> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> -		if (b->memory == V4L2_MEMORY_USERPTR) {
> -			for (plane = 0; plane < vb->num_planes; ++plane) {
> -				planes[plane].m.userptr =
> -					b->m.planes[plane].m.userptr;
> -				planes[plane].length =
> -					b->m.planes[plane].length;
> -			}
> -		}
> -		if (b->memory == V4L2_MEMORY_DMABUF) {
> -			for (plane = 0; plane < vb->num_planes; ++plane) {
> -				planes[plane].m.fd =
> -					b->m.planes[plane].m.fd;
> -				planes[plane].length =
> -					b->m.planes[plane].length;
> -			}
> -		}
> -
> -		/* Fill in driver-provided information for OUTPUT types */
> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> -			/*
> -			 * Will have to go up to b->length when API starts
> -			 * accepting variable number of planes.
> -			 *
> -			 * If bytesused == 0 for the output buffer, then fall
> -			 * back to the full buffer size. In that case
> -			 * userspace clearly never bothered to set it and
> -			 * it's a safe assumption that they really meant to
> -			 * use the full plane sizes.
> -			 *
> -			 * Some drivers, e.g. old codec drivers, use bytesused == 0
> -			 * as a way to indicate that streaming is finished.
> -			 * In that case, the driver should use the
> -			 * allow_zero_bytesused flag to keep old userspace
> -			 * applications working.
> -			 */
> -			for (plane = 0; plane < vb->num_planes; ++plane) {
> -				struct vb2_plane *pdst = &planes[plane];
> -				struct v4l2_plane *psrc = &b->m.planes[plane];
> -
> -				if (psrc->bytesused == 0)
> -					vb2_warn_zero_bytesused(vb);
> -
> -				if (vb->vb2_queue->allow_zero_bytesused)
> -					pdst->bytesused = psrc->bytesused;
> -				else
> -					pdst->bytesused = psrc->bytesused ?
> -						psrc->bytesused : pdst->length;
> -				pdst->data_offset = psrc->data_offset;
> -			}
> -		}
> -	} else {
> -		/*
> -		 * Single-planar buffers do not use planes array,
> -		 * so fill in relevant v4l2_buffer struct fields instead.
> -		 * In videobuf we use our internal V4l2_planes struct for
> -		 * single-planar buffers as well, for simplicity.
> -		 *
> -		 * If bytesused == 0 for the output buffer, then fall back
> -		 * to the full buffer size as that's a sensible default.
> -		 *
> -		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
> -		 * a way to indicate that streaming is finished. In that case,
> -		 * the driver should use the allow_zero_bytesused flag to keep
> -		 * old userspace applications working.
> -		 */
> -		if (b->memory == V4L2_MEMORY_USERPTR) {
> -			planes[0].m.userptr = b->m.userptr;
> -			planes[0].length = b->length;
> -		}
> -
> -		if (b->memory == V4L2_MEMORY_DMABUF) {
> -			planes[0].m.fd = b->m.fd;
> -			planes[0].length = b->length;
> -		}
> -
> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> -			if (b->bytesused == 0)
> -				vb2_warn_zero_bytesused(vb);
> -
> -			if (vb->vb2_queue->allow_zero_bytesused)
> -				planes[0].bytesused = b->bytesused;
> -			else
> -				planes[0].bytesused = b->bytesused ?
> -					b->bytesused : planes[0].length;
> -		} else
> -			planes[0].bytesused = 0;
> -
> -	}
> -
> -	/* Zero flags that the vb2 core handles */
> -	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> -	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> -			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
> -			!V4L2_TYPE_IS_OUTPUT(b->type)) {
> -		/*
> -		 * Non-COPY timestamps and non-OUTPUT queues will get
> -		 * their timestamp and timestamp source flags from the
> -		 * queue.
> -		 */
> -		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> -	}
> -
> -	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> -		/*
> -		 * For output buffers mask out the timecode flag:
> -		 * this will be handled later in vb2_internal_qbuf().
> -		 * The 'field' is valid metadata for this output buffer
> -		 * and so that needs to be copied here.
> -		 */
> -		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
> -		vbuf->field = b->field;
> -	} else {
> -		/* Zero any output buffer flags as this is a capture buffer */
> -		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
> -	}
> -}
> +EXPORT_SYMBOL_GPL(vb2_warn_zero_bytesused);
>  
>  /**
>   * __qbuf_mmap() - handle qbuf of an MMAP buffer
>   */
> -static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +static int __qbuf_mmap(struct vb2_buffer *vb, void *pb)
>  {
> -	__fill_vb2_buffer(vb, b, vb->planes);
> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, vb->planes);
>  	return call_vb_qop(vb, buf_prepare, vb);
>  }
>  
>  /**
>   * __qbuf_userptr() - handle qbuf of a USERPTR buffer
>   */
> -static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +static int __qbuf_userptr(struct vb2_buffer *vb, void *pb)
>  {
> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
> +	struct vb2_plane planes[VB2_MAX_PLANES];
>  	struct vb2_queue *q = vb->vb2_queue;
>  	void *mem_priv;
>  	unsigned int plane;
>  	int ret;
>  	enum dma_data_direction dma_dir =
> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>  	bool reacquired = vb->planes[0].mem_priv == NULL;
>  
>  	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
>  	/* Copy relevant information provided by the userspace */
> -	__fill_vb2_buffer(vb, b, planes);
> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
>  
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		/* Skip the plane if already verified */
> @@ -1462,7 +968,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  				reacquired = true;
>  				call_void_vb_qop(vb, buf_cleanup, vb);
>  			}
> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
> +			call_void_memop(vb, put_userptr,
> +					vb->planes[plane].mem_priv);
>  		}
>  
>  		vb->planes[plane].mem_priv = NULL;
> @@ -1533,20 +1040,20 @@ err:
>  /**
>   * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
>   */
> -static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +static int __qbuf_dmabuf(struct vb2_buffer *vb, void *pb)
>  {
> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
> +	struct vb2_plane planes[VB2_MAX_PLANES];
>  	struct vb2_queue *q = vb->vb2_queue;
>  	void *mem_priv;
>  	unsigned int plane;
>  	int ret;
>  	enum dma_data_direction dma_dir =
> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>  	bool reacquired = vb->planes[0].mem_priv == NULL;
>  
>  	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
>  	/* Copy relevant information provided by the userspace */
> -	__fill_vb2_buffer(vb, b, planes);
> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
>  
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
> @@ -1591,9 +1098,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  		vb->planes[plane].data_offset = 0;
>  
>  		/* Acquire each plane's memory */
> -		mem_priv = call_ptr_memop(vb, attach_dmabuf,
> -			q->alloc_ctx[plane], dbuf, planes[plane].length,
> -			dma_dir);
> +		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
> +			dbuf, planes[plane].length, dma_dir);
>  		if (IS_ERR(mem_priv)) {
>  			dprintk(1, "failed to attach dmabuf\n");
>  			ret = PTR_ERR(mem_priv);
> @@ -1626,7 +1132,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  	for (plane = 0; plane < vb->num_planes; ++plane) {
>  		vb->planes[plane].bytesused = planes[plane].bytesused;
>  		vb->planes[plane].length = planes[plane].length;
> -		vb->planes[plane].m.fd = planes[plane].m.userptr;
> +		vb->planes[plane].m.fd = planes[plane].m.fd;
>  		vb->planes[plane].data_offset = planes[plane].data_offset;
>  	}
>  
> @@ -1677,52 +1183,27 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
>  	call_void_vb_qop(vb, buf_queue, vb);
>  }
>  
> -static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +static int __buf_prepare(struct vb2_buffer *vb, void *pb)
>  {
> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>  	struct vb2_queue *q = vb->vb2_queue;
>  	int ret;
>  
> -	ret = __verify_length(vb, b);
> -	if (ret < 0) {
> -		dprintk(1, "plane parameters verification failed: %d\n", ret);
> -		return ret;
> -	}
> -	if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) {
> -		/*
> -		 * If the format's field is ALTERNATE, then the buffer's field
> -		 * should be either TOP or BOTTOM, not ALTERNATE since that
> -		 * makes no sense. The driver has to know whether the
> -		 * buffer represents a top or a bottom field in order to
> -		 * program any DMA correctly. Using ALTERNATE is wrong, since
> -		 * that just says that it is either a top or a bottom field,
> -		 * but not which of the two it is.
> -		 */
> -		dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
> -		return -EINVAL;
> -	}
> -
>  	if (q->error) {
>  		dprintk(1, "fatal error occurred on queue\n");
>  		return -EIO;
>  	}
>  
> -	vb->state = VB2_BUF_STATE_PREPARING;
> -	vbuf->timestamp.tv_sec = 0;
> -	vbuf->timestamp.tv_usec = 0;
> -	vbuf->sequence = 0;
> -
>  	switch (q->memory) {
> -	case V4L2_MEMORY_MMAP:
> -		ret = __qbuf_mmap(vb, b);
> +	case VB2_MEMORY_MMAP:
> +		ret = __qbuf_mmap(vb, pb);
>  		break;
> -	case V4L2_MEMORY_USERPTR:
> +	case VB2_MEMORY_USERPTR:
>  		down_read(&current->mm->mmap_sem);
> -		ret = __qbuf_userptr(vb, b);
> +		ret = __qbuf_userptr(vb, pb);
>  		up_read(&current->mm->mmap_sem);
>  		break;
> -	case V4L2_MEMORY_DMABUF:
> -		ret = __qbuf_dmabuf(vb, b);
> +	case VB2_MEMORY_DMABUF:
> +		ret = __qbuf_dmabuf(vb, pb);
>  		break;
>  	default:
>  		WARN(1, "Invalid queue type\n");
> @@ -1736,35 +1217,56 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>  	return ret;
>  }
>  
> -static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
> -					const char *opname)
> +int vb2_verify_buffer(struct vb2_queue *q,
> +			unsigned int memory, unsigned int type,
> +			unsigned int index, unsigned int nplanes,
> +			void *pplane, const char *opname)
>  {
> -	if (b->type != q->type) {
> +	if (type != q->type) {
>  		dprintk(1, "%s: invalid buffer type\n", opname);
>  		return -EINVAL;
>  	}
>  
> -	if (b->index >= q->num_buffers) {
> +	if (index >= q->num_buffers) {
>  		dprintk(1, "%s: buffer index out of range\n", opname);
>  		return -EINVAL;
>  	}
>  
> -	if (q->bufs[b->index] == NULL) {
> +	if (q->bufs[index] == NULL) {
>  		/* Should never happen */
>  		dprintk(1, "%s: buffer is NULL\n", opname);
>  		return -EINVAL;
>  	}
>  
> -	if (b->memory != q->memory) {
> +	if (memory != VB2_MEMORY_UNKNOWN && memory != q->memory) {
>  		dprintk(1, "%s: invalid memory type\n", opname);
>  		return -EINVAL;
>  	}
>  
> -	return __verify_planes_array(q->bufs[b->index], b);
> +	if (q->is_multiplanar) {
> +		struct vb2_buffer *vb = q->bufs[index];
> +
> +		/* Is memory for copying plane information present? */
> +		if (NULL == pplane) {
> +			dprintk(1, "%s: multi-planar buffer passed but "
> +				"planes array not provided\n", opname);
> +			return -EINVAL;
> +		}
> +
> +		if (nplanes < vb->num_planes || nplanes > VB2_MAX_PLANES) {
> +			dprintk(1, "%s: incorrect planes array length, "
> +				"expected %d, got %d\n",
> +				opname, vb->num_planes, nplanes);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
>  }
> +EXPORT_SYMBOL_GPL(vb2_verify_buffer);
>  
>  /**
> - * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
> + * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
>   * @q:		videobuf2 queue
>   * @b:		buffer structure passed from userspace to vidioc_prepare_buf
>   *		handler in driver
> @@ -1778,37 +1280,28 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
>   * The return values from this function are intended to be directly returned
>   * from vidioc_prepare_buf handler in driver.
>   */
> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>  {
>  	struct vb2_buffer *vb;
>  	int ret;
>  
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -
> -	ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
> -	if (ret)
> -		return ret;
> -
> -	vb = q->bufs[b->index];
> +	vb = q->bufs[index];
>  	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>  		dprintk(1, "invalid buffer state %d\n",
>  			vb->state);
>  		return -EINVAL;
>  	}
>  
> -	ret = __buf_prepare(vb, b);
> +	ret = __buf_prepare(vb, pb);
>  	if (!ret) {
>  		/* Fill buffer information for the userspace */
> -		__fill_v4l2_buffer(vb, b);
> +		call_bufop(q, fill_user_buffer, vb, pb);
>  
>  		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
>  	}
>  	return ret;
>  }
> -EXPORT_SYMBOL_GPL(vb2_prepare_buf);
> +EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
>  
>  /**
>   * vb2_start_streaming() - Attempt to start streaming.
> @@ -1873,21 +1366,16 @@ static int vb2_start_streaming(struct vb2_queue *q)
>  	return ret;
>  }
>  
> -static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
>  {
> -	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
> +	int ret;
>  	struct vb2_buffer *vb;
> -	struct vb2_v4l2_buffer *vbuf;
> -
> -	if (ret)
> -		return ret;
>  
> -	vb = q->bufs[b->index];
> -	vbuf = to_vb2_v4l2_buffer(vb);
> +	vb = q->bufs[index];
>  
>  	switch (vb->state) {
>  	case VB2_BUF_STATE_DEQUEUED:
> -		ret = __buf_prepare(vb, b);
> +		ret = __buf_prepare(vb, pb);
>  		if (ret)
>  			return ret;
>  		break;
> @@ -1909,18 +1397,9 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  	q->queued_count++;
>  	q->waiting_for_buffers = false;
>  	vb->state = VB2_BUF_STATE_QUEUED;
> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
> -		/*
> -		 * For output buffers copy the timestamp if needed,
> -		 * and the timecode field and flag if needed.
> -		 */
> -		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> -				V4L2_BUF_FLAG_TIMESTAMP_COPY)
> -			vbuf->timestamp = b->timestamp;
> -		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> -		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> -			vbuf->timecode = b->timecode;
> -	}
> +
> +	if (q->is_output)
> +		call_bufop(q, fill_vb2_timestamp, vb, pb);
>  
>  	trace_vb2_qbuf(q, vb);
>  
> @@ -1932,7 +1411,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  		__enqueue_in_driver(vb);
>  
>  	/* Fill buffer information for the userspace */
> -	__fill_v4l2_buffer(vb, b);
> +	call_bufop(q, fill_user_buffer, vb, pb);
>  
>  	/*
>  	 * If streamon has been called, and we haven't yet called
> @@ -1950,34 +1429,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>  	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
>  	return 0;
>  }
> -
> -/**
> - * vb2_qbuf() - Queue a buffer from userspace
> - * @q:		videobuf2 queue
> - * @b:		buffer structure passed from userspace to vidioc_qbuf handler
> - *		in driver
> - *
> - * Should be called from vidioc_qbuf ioctl handler of a driver.
> - * This function:
> - * 1) verifies the passed buffer,
> - * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
> - *    which driver-specific buffer initialization can be performed,
> - * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
> - *    callback for processing.
> - *
> - * The return values from this function are intended to be directly returned
> - * from vidioc_qbuf handler in driver.
> - */
> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> -{
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -
> -	return vb2_internal_qbuf(q, b);
> -}
> -EXPORT_SYMBOL_GPL(vb2_qbuf);
> +EXPORT_SYMBOL_GPL(vb2_core_qbuf);
>  
>  /**
>   * __vb2_wait_for_done_vb() - wait for a buffer to become available
> @@ -2061,7 +1513,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
>   * Will sleep if required for nonblocking == false.
>   */
>  static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
> -				struct v4l2_buffer *b, int nonblocking)
> +				int nonblocking)
>  {
>  	unsigned long flags;
>  	int ret;
> @@ -2082,10 +1534,11 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
>  	/*
>  	 * Only remove the buffer from done_list if v4l2_buffer can handle all
>  	 * the planes.
> +	 * ret = __verify_planes_array(*vb, pb);
> +	 * But, actually that's unnecessary since this is checked already
> +	 * before the buffer is queued/prepared. So it can never fails
>  	 */
> -	ret = __verify_planes_array(*vb, b);
> -	if (!ret)
> -		list_del(&(*vb)->done_entry);
> +	list_del(&(*vb)->done_entry);
>  	spin_unlock_irqrestore(&q->done_lock, flags);
>  
>  	return ret;
> @@ -2128,27 +1581,22 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
>  	vb->state = VB2_BUF_STATE_DEQUEUED;
>  
>  	/* unmap DMABUF buffer */
> -	if (q->memory == V4L2_MEMORY_DMABUF)
> +	if (q->memory == VB2_MEMORY_DMABUF)
>  		for (i = 0; i < vb->num_planes; ++i) {
>  			if (!vb->planes[i].dbuf_mapped)
>  				continue;
> -			call_void_memop(vb, unmap_dmabuf, vb->planes[i].mem_priv);
> +			call_void_memop(vb, unmap_dmabuf,
> +					vb->planes[i].mem_priv);
>  			vb->planes[i].dbuf_mapped = 0;
>  		}
>  }
>  
> -static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> -		bool nonblocking)
> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
>  {
>  	struct vb2_buffer *vb = NULL;
> -	struct vb2_v4l2_buffer *vbuf = NULL;
>  	int ret;
>  
> -	if (b->type != q->type) {
> -		dprintk(1, "invalid buffer type\n");
> -		return -EINVAL;
> -	}
> -	ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
> +	ret = __vb2_get_done_vb(q, &vb, nonblocking);
>  	if (ret < 0)
>  		return ret;
>  
> @@ -2167,16 +1615,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>  	call_void_vb_qop(vb, buf_finish, vb);
>  
>  	/* Fill buffer information for the userspace */
> -	__fill_v4l2_buffer(vb, b);
> +	call_bufop(q, fill_user_buffer, vb, pb);
>  	/* Remove from videobuf queue */
>  	list_del(&vb->queued_entry);
>  	q->queued_count--;
>  
>  	trace_vb2_dqbuf(q, vb);
>  
> -	vbuf = to_vb2_v4l2_buffer(vb);
> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
> -			vbuf->flags & V4L2_BUF_FLAG_LAST)
> +	if (!q->is_output &&
> +			call_bufop(q, is_last, vb))
>  		q->last_buffer_dequeued = true;
>  	/* go back to dequeued state */
>  	__vb2_dqbuf(vb);
> @@ -2186,37 +1633,7 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>  
>  	return 0;
>  }
> -
> -/**
> - * vb2_dqbuf() - Dequeue a buffer to the userspace
> - * @q:		videobuf2 queue
> - * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
> - *		in driver
> - * @nonblocking: if true, this call will not sleep waiting for a buffer if no
> - *		 buffers ready for dequeuing are present. Normally the driver
> - *		 would be passing (file->f_flags & O_NONBLOCK) here
> - *
> - * Should be called from vidioc_dqbuf ioctl handler of a driver.
> - * This function:
> - * 1) verifies the passed buffer,
> - * 2) calls buf_finish callback in the driver (if provided), in which
> - *    driver can perform any additional operations that may be required before
> - *    returning the buffer to userspace, such as cache sync,
> - * 3) the buffer struct members are filled with relevant information for
> - *    the userspace.
> - *
> - * The return values from this function are intended to be directly returned
> - * from vidioc_dqbuf handler in driver.
> - */
> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
> -{
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -	return vb2_internal_dqbuf(q, b, nonblocking);
> -}
> -EXPORT_SYMBOL_GPL(vb2_dqbuf);
> +EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
>  
>  /**
>   * __vb2_queue_cancel() - cancel and stop (pause) streaming
> @@ -2286,15 +1703,10 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>  	}
>  }
>  
> -static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> +int vb2_core_streamon(struct vb2_queue *q)
>  {
>  	int ret;
>  
> -	if (type != q->type) {
> -		dprintk(1, "invalid stream type\n");
> -		return -EINVAL;
> -	}
> -
>  	if (q->streaming) {
>  		dprintk(3, "already streaming\n");
>  		return 0;
> @@ -2328,6 +1740,7 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>  	dprintk(3, "successful\n");
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(vb2_core_streamon);
>  
>  /**
>   * vb2_queue_error() - signal a fatal error on the queue
> @@ -2350,36 +1763,8 @@ void vb2_queue_error(struct vb2_queue *q)
>  }
>  EXPORT_SYMBOL_GPL(vb2_queue_error);
>  
> -/**
> - * vb2_streamon - start streaming
> - * @q:		videobuf2 queue
> - * @type:	type argument passed from userspace to vidioc_streamon handler
> - *
> - * Should be called from vidioc_streamon handler of a driver.
> - * This function:
> - * 1) verifies current state
> - * 2) passes any previously queued buffers to the driver and starts streaming
> - *
> - * The return values from this function are intended to be directly returned
> - * from vidioc_streamon handler in the driver.
> - */
> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> -{
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -	return vb2_internal_streamon(q, type);
> -}
> -EXPORT_SYMBOL_GPL(vb2_streamon);
> -
> -static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> +int vb2_core_streamoff(struct vb2_queue *q)
>  {
> -	if (type != q->type) {
> -		dprintk(1, "invalid stream type\n");
> -		return -EINVAL;
> -	}
> -
>  	/*
>  	 * Cancel will pause streaming and remove all buffers from the driver
>  	 * and videobuf, effectively returning control over them to userspace.
> @@ -2390,37 +1775,13 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>  	 * their normal dequeued state.
>  	 */
>  	__vb2_queue_cancel(q);
> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
> +	q->waiting_for_buffers = !q->is_output;
>  	q->last_buffer_dequeued = false;
>  
>  	dprintk(3, "successful\n");
>  	return 0;
>  }
> -
> -/**
> - * vb2_streamoff - stop streaming
> - * @q:		videobuf2 queue
> - * @type:	type argument passed from userspace to vidioc_streamoff handler
> - *
> - * Should be called from vidioc_streamoff handler of a driver.
> - * This function:
> - * 1) verifies current state,
> - * 2) stop streaming and dequeues any queued buffers, including those previously
> - *    passed to the driver (after waiting for the driver to finish).
> - *
> - * This call can be used for pausing playback.
> - * The return values from this function are intended to be directly returned
> - * from vidioc_streamoff handler in the driver
> - */
> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> -{
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "file io in progress\n");
> -		return -EBUSY;
> -	}
> -	return vb2_internal_streamoff(q, type);
> -}
> -EXPORT_SYMBOL_GPL(vb2_streamoff);
> +EXPORT_SYMBOL_GPL(vb2_core_streamoff);
>  
>  /**
>   * __find_plane_by_offset() - find plane associated with the given offset off
> @@ -2452,7 +1813,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>  }
>  
>  /**
> - * vb2_expbuf() - Export a buffer as a file descriptor
> + * vb2_core_expbuf() - Export a buffer as a file descriptor
>   * @q:		videobuf2 queue
>   * @eb:		export buffer structure passed from userspace to vidioc_expbuf
>   *		handler in driver
> @@ -2460,14 +1821,15 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>   * The return values from this function are intended to be directly returned
>   * from vidioc_expbuf handler in driver.
>   */
> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
> +		unsigned int index, unsigned int plane, unsigned int flags)
>  {
>  	struct vb2_buffer *vb = NULL;
>  	struct vb2_plane *vb_plane;
>  	int ret;
>  	struct dma_buf *dbuf;
>  
> -	if (q->memory != V4L2_MEMORY_MMAP) {
> +	if (q->memory != VB2_MEMORY_MMAP) {
>  		dprintk(1, "queue is not currently set up for mmap\n");
>  		return -EINVAL;
>  	}
> @@ -2477,78 +1839,60 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
>  		return -EINVAL;
>  	}
>  
> -	if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
> +	if (flags & ~(O_CLOEXEC | O_ACCMODE)) {
>  		dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n");
>  		return -EINVAL;
>  	}
>  
> -	if (eb->type != q->type) {
> +	if (type != q->type) {
>  		dprintk(1, "invalid buffer type\n");
>  		return -EINVAL;
>  	}
>  
> -	if (eb->index >= q->num_buffers) {
> +	if (index >= q->num_buffers) {
>  		dprintk(1, "buffer index out of range\n");
>  		return -EINVAL;
>  	}
>  
> -	vb = q->bufs[eb->index];
> +	vb = q->bufs[index];
>  
> -	if (eb->plane >= vb->num_planes) {
> +	if (plane >= vb->num_planes) {
>  		dprintk(1, "buffer plane out of range\n");
>  		return -EINVAL;
>  	}
>  
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "expbuf: file io in progress\n");
> -		return -EBUSY;
> -	}
> +	vb_plane = &vb->planes[plane];
>  
> -	vb_plane = &vb->planes[eb->plane];
> -
> -	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
> +	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv,
> +				flags & O_ACCMODE);
>  	if (IS_ERR_OR_NULL(dbuf)) {
>  		dprintk(1, "failed to export buffer %d, plane %d\n",
> -			eb->index, eb->plane);
> +			index, plane);
>  		return -EINVAL;
>  	}
>  
> -	ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
> +	ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
>  	if (ret < 0) {
>  		dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
> -			eb->index, eb->plane, ret);
> +			index, plane, ret);
>  		dma_buf_put(dbuf);
>  		return ret;
>  	}
>  
>  	dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
> -		eb->index, eb->plane, ret);
> -	eb->fd = ret;
> +		index, plane, ret);
> +	*fd = ret;
>  
>  	return 0;
>  }
> -EXPORT_SYMBOL_GPL(vb2_expbuf);
> +EXPORT_SYMBOL_GPL(vb2_core_expbuf);
>  
>  /**
> - * vb2_mmap() - map video buffers into application address space
> + * vb2_core_mmap() - map video buffers into application address space
>   * @q:		videobuf2 queue
>   * @vma:	vma passed to the mmap file operation handler in the driver
> - *
> - * Should be called from mmap file operation handler of a driver.
> - * This function maps one plane of one of the available video buffers to
> - * userspace. To map whole video memory allocated on reqbufs, this function
> - * has to be called once per each plane per each buffer previously allocated.
> - *
> - * When the userspace application calls mmap, it passes to it an offset returned
> - * to it earlier by the means of vidioc_querybuf handler. That offset acts as
> - * a "cookie", which is then used to identify the plane to be mapped.
> - * This function finds a plane with a matching offset and a mapping is performed
> - * by the means of a provided memory operation.
> - *
> - * The return values from this function are intended to be directly returned
> - * from the mmap handler in driver.
>   */
> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  {
>  	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
>  	struct vb2_buffer *vb;
> @@ -2556,7 +1900,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  	int ret;
>  	unsigned long length;
>  
> -	if (q->memory != V4L2_MEMORY_MMAP) {
> +	if (q->memory != VB2_MEMORY_MMAP) {
>  		dprintk(1, "queue is not currently set up for mmap\n");
>  		return -EINVAL;
>  	}
> @@ -2568,7 +1912,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  		dprintk(1, "invalid vma flags, VM_SHARED needed\n");
>  		return -EINVAL;
>  	}
> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
> +	if (q->is_output) {
>  		if (!(vma->vm_flags & VM_WRITE)) {
>  			dprintk(1, "invalid vma flags, VM_WRITE needed\n");
>  			return -EINVAL;
> @@ -2579,10 +1923,6 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  			return -EINVAL;
>  		}
>  	}
> -	if (vb2_fileio_is_active(q)) {
> -		dprintk(1, "mmap: file io in progress\n");
> -		return -EBUSY;
> -	}
>  
>  	/*
>  	 * Find the plane corresponding to the offset passed by userspace.
> @@ -2614,7 +1954,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>  	dprintk(3, "buffer %d, plane %d successfully mapped\n", buffer, plane);
>  	return 0;
>  }
> -EXPORT_SYMBOL_GPL(vb2_mmap);
> +EXPORT_SYMBOL_GPL(vb2_core_mmap);
>  
>  #ifndef CONFIG_MMU
>  unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
> @@ -2629,7 +1969,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  	void *vaddr;
>  	int ret;
>  
> -	if (q->memory != V4L2_MEMORY_MMAP) {
> +	if (q->memory != VB2_MEMORY_MMAP) {
>  		dprintk(1, "queue is not currently set up for mmap\n");
>  		return -EINVAL;
>  	}
> @@ -2649,123 +1989,8 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
>  #endif
>  
> -static int __vb2_init_fileio(struct vb2_queue *q, int read);
> -static int __vb2_cleanup_fileio(struct vb2_queue *q);
> -
> -/**
> - * vb2_poll() - implements poll userspace operation
> - * @q:		videobuf2 queue
> - * @file:	file argument passed to the poll file operation handler
> - * @wait:	wait argument passed to the poll file operation handler
> - *
> - * This function implements poll file operation handler for a driver.
> - * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
> - * be informed that the file descriptor of a video device is available for
> - * reading.
> - * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
> - * will be reported as available for writing.
> - *
> - * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
> - * pending events.
> - *
> - * The return values from this function are intended to be directly returned
> - * from poll handler in driver.
> - */
> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> -{
> -	struct video_device *vfd = video_devdata(file);
> -	unsigned long req_events = poll_requested_events(wait);
> -	struct vb2_buffer *vb = NULL;
> -	unsigned int res = 0;
> -	unsigned long flags;
> -
> -	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> -		struct v4l2_fh *fh = file->private_data;
> -
> -		if (v4l2_event_pending(fh))
> -			res = POLLPRI;
> -		else if (req_events & POLLPRI)
> -			poll_wait(file, &fh->wait, wait);
> -	}
> -
> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLIN | POLLRDNORM)))
> -		return res;
> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLOUT | POLLWRNORM)))
> -		return res;
> -
> -	/*
> -	 * Start file I/O emulator only if streaming API has not been used yet.
> -	 */
> -	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
> -		if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
> -				(req_events & (POLLIN | POLLRDNORM))) {
> -			if (__vb2_init_fileio(q, 1))
> -				return res | POLLERR;
> -		}
> -		if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
> -				(req_events & (POLLOUT | POLLWRNORM))) {
> -			if (__vb2_init_fileio(q, 0))
> -				return res | POLLERR;
> -			/*
> -			 * Write to OUTPUT queue can be done immediately.
> -			 */
> -			return res | POLLOUT | POLLWRNORM;
> -		}
> -	}
> -
> -	/*
> -	 * There is nothing to wait for if the queue isn't streaming, or if the
> -	 * error flag is set.
> -	 */
> -	if (!vb2_is_streaming(q) || q->error)
> -		return res | POLLERR;
> -	/*
> -	 * For compatibility with vb1: if QBUF hasn't been called yet, then
> -	 * return POLLERR as well. This only affects capture queues, output
> -	 * queues will always initialize waiting_for_buffers to false.
> -	 */
> -	if (q->waiting_for_buffers)
> -		return res | POLLERR;
> -
> -	/*
> -	 * For output streams you can write as long as there are fewer buffers
> -	 * queued than there are buffers available.
> -	 */
> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
> -		return res | POLLOUT | POLLWRNORM;
> -
> -	if (list_empty(&q->done_list)) {
> -		/*
> -		 * If the last buffer was dequeued from a capture queue,
> -		 * return immediately. DQBUF will return -EPIPE.
> -		 */
> -		if (q->last_buffer_dequeued)
> -			return res | POLLIN | POLLRDNORM;
> -
> -		poll_wait(file, &q->done_wq, wait);
> -	}
> -
> -	/*
> -	 * Take first buffer available for dequeuing.
> -	 */
> -	spin_lock_irqsave(&q->done_lock, flags);
> -	if (!list_empty(&q->done_list))
> -		vb = list_first_entry(&q->done_list, struct vb2_buffer,
> -					done_entry);
> -	spin_unlock_irqrestore(&q->done_lock, flags);
> -
> -	if (vb && (vb->state == VB2_BUF_STATE_DONE
> -			|| vb->state == VB2_BUF_STATE_ERROR)) {
> -		return (V4L2_TYPE_IS_OUTPUT(q->type)) ?
> -				res | POLLOUT | POLLWRNORM :
> -				res | POLLIN | POLLRDNORM;
> -	}
> -	return res;
> -}
> -EXPORT_SYMBOL_GPL(vb2_poll);
> -
>  /**
> - * vb2_queue_init() - initialize a videobuf2 queue
> + * vb2_core_queue_init() - initialize a videobuf2 queue
>   * @q:		videobuf2 queue; this structure should be allocated in driver
>   *
>   * The vb2_queue structure should be allocated by the driver. The driver is
> @@ -2775,7 +2000,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
>   * to the struct vb2_queue description in include/media/videobuf2-core.h
>   * for more information.
>   */
> -int vb2_queue_init(struct vb2_queue *q)
> +int vb2_core_queue_init(struct vb2_queue *q)
>  {
>  	/*
>  	 * Sanity check
> @@ -2783,19 +2008,13 @@ int vb2_queue_init(struct vb2_queue *q)
>  	if (WARN_ON(!q)				||
>  		WARN_ON(!q->ops)		||
>  		WARN_ON(!q->mem_ops)		||
> +		WARN_ON(!q->buf_ops)		||
>  		WARN_ON(!q->type)		||
>  		WARN_ON(!q->io_modes)		||
>  		WARN_ON(!q->ops->queue_setup)	||
> -		WARN_ON(!q->ops->buf_queue)	||
> -		WARN_ON(q->timestamp_flags &
> -			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> -			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
> +		WARN_ON(!q->ops->buf_queue))
>  		return -EINVAL;
>  
> -	/* Warn that the driver should choose an appropriate timestamp type */
> -	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> -		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
> -
>  	INIT_LIST_HEAD(&q->queued_list);
>  	INIT_LIST_HEAD(&q->done_list);
>  	spin_lock_init(&q->done_lock);
> @@ -2807,822 +2026,24 @@ int vb2_queue_init(struct vb2_queue *q)
>  
>  	return 0;
>  }
> -EXPORT_SYMBOL_GPL(vb2_queue_init);
> +EXPORT_SYMBOL_GPL(vb2_core_queue_init);
>  
>  /**
> - * vb2_queue_release() - stop streaming, release the queue and free memory
> + * vb2_core_queue_release() - stop streaming, release the queue and free memory
>   * @q:		videobuf2 queue
>   *
>   * This function stops streaming and performs necessary clean ups, including
>   * freeing video buffer memory. The driver is responsible for freeing
>   * the vb2_queue structure itself.
>   */
> -void vb2_queue_release(struct vb2_queue *q)
> +void vb2_core_queue_release(struct vb2_queue *q)
>  {
> -	__vb2_cleanup_fileio(q);
>  	__vb2_queue_cancel(q);
>  	mutex_lock(&q->mmap_lock);
>  	__vb2_queue_free(q, q->num_buffers);
>  	mutex_unlock(&q->mmap_lock);
>  }
> -EXPORT_SYMBOL_GPL(vb2_queue_release);
> -
> -/**
> - * struct vb2_fileio_buf - buffer context used by file io emulator
> - *
> - * vb2 provides a compatibility layer and emulator of file io (read and
> - * write) calls on top of streaming API. This structure is used for
> - * tracking context related to the buffers.
> - */
> -struct vb2_fileio_buf {
> -	void *vaddr;
> -	unsigned int size;
> -	unsigned int pos;
> -	unsigned int queued:1;
> -};
> -
> -/**
> - * struct vb2_fileio_data - queue context used by file io emulator
> - *
> - * @cur_index:	the index of the buffer currently being read from or
> - *		written to. If equal to q->num_buffers then a new buffer
> - *		must be dequeued.
> - * @initial_index: in the read() case all buffers are queued up immediately
> - *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
> - *		buffers. However, in the write() case no buffers are initially
> - *		queued, instead whenever a buffer is full it is queued up by
> - *		__vb2_perform_fileio(). Only once all available buffers have
> - *		been queued up will __vb2_perform_fileio() start to dequeue
> - *		buffers. This means that initially __vb2_perform_fileio()
> - *		needs to know what buffer index to use when it is queuing up
> - *		the buffers for the first time. That initial index is stored
> - *		in this field. Once it is equal to q->num_buffers all
> - *		available buffers have been queued and __vb2_perform_fileio()
> - *		should start the normal dequeue/queue cycle.
> - *
> - * vb2 provides a compatibility layer and emulator of file io (read and
> - * write) calls on top of streaming API. For proper operation it required
> - * this structure to save the driver state between each call of the read
> - * or write function.
> - */
> -struct vb2_fileio_data {
> -	struct v4l2_requestbuffers req;
> -	struct v4l2_plane p;
> -	struct v4l2_buffer b;
> -	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
> -	unsigned int cur_index;
> -	unsigned int initial_index;
> -	unsigned int q_count;
> -	unsigned int dq_count;
> -	unsigned read_once:1;
> -	unsigned write_immediately:1;
> -};
> -
> -/**
> - * __vb2_init_fileio() - initialize file io emulator
> - * @q:		videobuf2 queue
> - * @read:	mode selector (1 means read, 0 means write)
> - */
> -static int __vb2_init_fileio(struct vb2_queue *q, int read)
> -{
> -	struct vb2_fileio_data *fileio;
> -	int i, ret;
> -	unsigned int count = 0;
> -
> -	/*
> -	 * Sanity check
> -	 */
> -	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
> -			(!read && !(q->io_modes & VB2_WRITE))))
> -		return -EINVAL;
> -
> -	/*
> -	 * Check if device supports mapping buffers to kernel virtual space.
> -	 */
> -	if (!q->mem_ops->vaddr)
> -		return -EBUSY;
> -
> -	/*
> -	 * Check if streaming api has not been already activated.
> -	 */
> -	if (q->streaming || q->num_buffers > 0)
> -		return -EBUSY;
> -
> -	/*
> -	 * Start with count 1, driver can increase it in queue_setup()
> -	 */
> -	count = 1;
> -
> -	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
> -		(read) ? "read" : "write", count, q->fileio_read_once,
> -		q->fileio_write_immediately);
> -
> -	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
> -	if (fileio == NULL)
> -		return -ENOMEM;
> -
> -	fileio->read_once = q->fileio_read_once;
> -	fileio->write_immediately = q->fileio_write_immediately;
> -
> -	/*
> -	 * Request buffers and use MMAP type to force driver
> -	 * to allocate buffers by itself.
> -	 */
> -	fileio->req.count = count;
> -	fileio->req.memory = V4L2_MEMORY_MMAP;
> -	fileio->req.type = q->type;
> -	q->fileio = fileio;
> -	ret = __reqbufs(q, &fileio->req);
> -	if (ret)
> -		goto err_kfree;
> -
> -	/*
> -	 * Check if plane_count is correct
> -	 * (multiplane buffers are not supported).
> -	 */
> -	if (q->bufs[0]->num_planes != 1) {
> -		ret = -EBUSY;
> -		goto err_reqbufs;
> -	}
> -
> -	/*
> -	 * Get kernel address of each buffer.
> -	 */
> -	for (i = 0; i < q->num_buffers; i++) {
> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
> -		if (fileio->bufs[i].vaddr == NULL) {
> -			ret = -EINVAL;
> -			goto err_reqbufs;
> -		}
> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
> -	}
> -
> -	/*
> -	 * Read mode requires pre queuing of all buffers.
> -	 */
> -	if (read) {
> -		bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> -
> -		/*
> -		 * Queue all buffers.
> -		 */
> -		for (i = 0; i < q->num_buffers; i++) {
> -			struct v4l2_buffer *b = &fileio->b;
> -
> -			memset(b, 0, sizeof(*b));
> -			b->type = q->type;
> -			if (is_multiplanar) {
> -				memset(&fileio->p, 0, sizeof(fileio->p));
> -				b->m.planes = &fileio->p;
> -				b->length = 1;
> -			}
> -			b->memory = q->memory;
> -			b->index = i;
> -			ret = vb2_internal_qbuf(q, b);
> -			if (ret)
> -				goto err_reqbufs;
> -			fileio->bufs[i].queued = 1;
> -		}
> -		/*
> -		 * All buffers have been queued, so mark that by setting
> -		 * initial_index to q->num_buffers
> -		 */
> -		fileio->initial_index = q->num_buffers;
> -		fileio->cur_index = q->num_buffers;
> -	}
> -
> -	/*
> -	 * Start streaming.
> -	 */
> -	ret = vb2_internal_streamon(q, q->type);
> -	if (ret)
> -		goto err_reqbufs;
> -
> -	return ret;
> -
> -err_reqbufs:
> -	fileio->req.count = 0;
> -	__reqbufs(q, &fileio->req);
> -
> -err_kfree:
> -	q->fileio = NULL;
> -	kfree(fileio);
> -	return ret;
> -}
> -
> -/**
> - * __vb2_cleanup_fileio() - free resourced used by file io emulator
> - * @q:		videobuf2 queue
> - */
> -static int __vb2_cleanup_fileio(struct vb2_queue *q)
> -{
> -	struct vb2_fileio_data *fileio = q->fileio;
> -
> -	if (fileio) {
> -		vb2_internal_streamoff(q, q->type);
> -		q->fileio = NULL;
> -		fileio->req.count = 0;
> -		vb2_reqbufs(q, &fileio->req);
> -		kfree(fileio);
> -		dprintk(3, "file io emulator closed\n");
> -	}
> -	return 0;
> -}
> -
> -/**
> - * __vb2_perform_fileio() - perform a single file io (read or write) operation
> - * @q:		videobuf2 queue
> - * @data:	pointed to target userspace buffer
> - * @count:	number of bytes to read or write
> - * @ppos:	file handle position tracking pointer
> - * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
> - * @read:	access mode selector (1 means read, 0 means write)
> - */
> -static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
> -		loff_t *ppos, int nonblock, int read)
> -{
> -	struct vb2_fileio_data *fileio;
> -	struct vb2_fileio_buf *buf;
> -	bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> -	/*
> -	 * When using write() to write data to an output video node the vb2 core
> -	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
> -	 * else is able to provide this information with the write() operation.
> -	 */
> -	bool set_timestamp = !read &&
> -		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> -		V4L2_BUF_FLAG_TIMESTAMP_COPY;
> -	int ret, index;
> -
> -	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
> -		read ? "read" : "write", (long)*ppos, count,
> -		nonblock ? "non" : "");
> -
> -	if (!data)
> -		return -EINVAL;
> -
> -	/*
> -	 * Initialize emulator on first call.
> -	 */
> -	if (!vb2_fileio_is_active(q)) {
> -		ret = __vb2_init_fileio(q, read);
> -		dprintk(3, "vb2_init_fileio result: %d\n", ret);
> -		if (ret)
> -			return ret;
> -	}
> -	fileio = q->fileio;
> -
> -	/*
> -	 * Check if we need to dequeue the buffer.
> -	 */
> -	index = fileio->cur_index;
> -	if (index >= q->num_buffers) {
> -		/*
> -		 * Call vb2_dqbuf to get buffer back.
> -		 */
> -		memset(&fileio->b, 0, sizeof(fileio->b));
> -		fileio->b.type = q->type;
> -		fileio->b.memory = q->memory;
> -		if (is_multiplanar) {
> -			memset(&fileio->p, 0, sizeof(fileio->p));
> -			fileio->b.m.planes = &fileio->p;
> -			fileio->b.length = 1;
> -		}
> -		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
> -		dprintk(5, "vb2_dqbuf result: %d\n", ret);
> -		if (ret)
> -			return ret;
> -		fileio->dq_count += 1;
> -
> -		fileio->cur_index = index = fileio->b.index;
> -		buf = &fileio->bufs[index];
> -
> -		/*
> -		 * Get number of bytes filled by the driver
> -		 */
> -		buf->pos = 0;
> -		buf->queued = 0;
> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> -				 : vb2_plane_size(q->bufs[index], 0);
> -		/*
> -		 * Compensate for data_offset on read
> -		 * in the multiplanar case
> -		 */
> -		if (is_multiplanar && read &&
> -			fileio->b.m.planes[0].data_offset < buf->size) {
> -			buf->pos = fileio->b.m.planes[0].data_offset;
> -			buf->size -= buf->pos;
> -		}
> -	} else {
> -		buf = &fileio->bufs[index];
> -	}
> -
> -	/*
> -	 * Limit count on last few bytes of the buffer.
> -	 */
> -	if (buf->pos + count > buf->size) {
> -		count = buf->size - buf->pos;
> -		dprintk(5, "reducing read count: %zd\n", count);
> -	}
> -
> -	/*
> -	 * Transfer data to userspace.
> -	 */
> -	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
> -		count, index, buf->pos);
> -	if (read)
> -		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
> -	else
> -		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
> -	if (ret) {
> -		dprintk(3, "error copying data\n");
> -		return -EFAULT;
> -	}
> -
> -	/*
> -	 * Update counters.
> -	 */
> -	buf->pos += count;
> -	*ppos += count;
> -
> -	/*
> -	 * Queue next buffer if required.
> -	 */
> -	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
> -		/*
> -		 * Check if this is the last buffer to read.
> -		 */
> -		if (read && fileio->read_once && fileio->dq_count == 1) {
> -			dprintk(3, "read limit reached\n");
> -			return __vb2_cleanup_fileio(q);
> -		}
> -
> -		/*
> -		 * Call vb2_qbuf and give buffer to the driver.
> -		 */
> -		memset(&fileio->b, 0, sizeof(fileio->b));
> -		fileio->b.type = q->type;
> -		fileio->b.memory = q->memory;
> -		fileio->b.index = index;
> -		fileio->b.bytesused = buf->pos;
> -		if (is_multiplanar) {
> -			memset(&fileio->p, 0, sizeof(fileio->p));
> -			fileio->p.bytesused = buf->pos;
> -			fileio->b.m.planes = &fileio->p;
> -			fileio->b.length = 1;
> -		}
> -		if (set_timestamp)
> -			v4l2_get_timestamp(&fileio->b.timestamp);
> -		ret = vb2_internal_qbuf(q, &fileio->b);
> -		dprintk(5, "vb2_dbuf result: %d\n", ret);
> -		if (ret)
> -			return ret;
> -
> -		/*
> -		 * Buffer has been queued, update the status
> -		 */
> -		buf->pos = 0;
> -		buf->queued = 1;
> -		buf->size = vb2_plane_size(q->bufs[index], 0);
> -		fileio->q_count += 1;
> -		/*
> -		 * If we are queuing up buffers for the first time, then
> -		 * increase initial_index by one.
> -		 */
> -		if (fileio->initial_index < q->num_buffers)
> -			fileio->initial_index++;
> -		/*
> -		 * The next buffer to use is either a buffer that's going to be
> -		 * queued for the first time (initial_index < q->num_buffers)
> -		 * or it is equal to q->num_buffers, meaning that the next
> -		 * time we need to dequeue a buffer since we've now queued up
> -		 * all the 'first time' buffers.
> -		 */
> -		fileio->cur_index = fileio->initial_index;
> -	}
> -
> -	/*
> -	 * Return proper number of bytes processed.
> -	 */
> -	if (ret == 0)
> -		ret = count;
> -	return ret;
> -}
> -
> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> -		loff_t *ppos, int nonblocking)
> -{
> -	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
> -}
> -EXPORT_SYMBOL_GPL(vb2_read);
> -
> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> -		loff_t *ppos, int nonblocking)
> -{
> -	return __vb2_perform_fileio(q, (char __user *) data, count,
> -							ppos, nonblocking, 0);
> -}
> -EXPORT_SYMBOL_GPL(vb2_write);
> -
> -struct vb2_threadio_data {
> -	struct task_struct *thread;
> -	vb2_thread_fnc fnc;
> -	void *priv;
> -	bool stop;
> -};
> -
> -static int vb2_thread(void *data)
> -{
> -	struct vb2_queue *q = data;
> -	struct vb2_threadio_data *threadio = q->threadio;
> -	struct vb2_fileio_data *fileio = q->fileio;
> -	bool set_timestamp = false;
> -	int prequeue = 0;
> -	int index = 0;
> -	int ret = 0;
> -
> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
> -		prequeue = q->num_buffers;
> -		set_timestamp =
> -			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> -			V4L2_BUF_FLAG_TIMESTAMP_COPY;
> -	}
> -
> -	set_freezable();
> -
> -	for (;;) {
> -		struct vb2_buffer *vb;
> -
> -		/*
> -		 * Call vb2_dqbuf to get buffer back.
> -		 */
> -		memset(&fileio->b, 0, sizeof(fileio->b));
> -		fileio->b.type = q->type;
> -		fileio->b.memory = q->memory;
> -		if (prequeue) {
> -			fileio->b.index = index++;
> -			prequeue--;
> -		} else {
> -			call_void_qop(q, wait_finish, q);
> -			if (!threadio->stop)
> -				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
> -			call_void_qop(q, wait_prepare, q);
> -			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
> -		}
> -		if (ret || threadio->stop)
> -			break;
> -		try_to_freeze();
> -
> -		vb = q->bufs[fileio->b.index];
> -		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
> -			if (threadio->fnc(vb, threadio->priv))
> -				break;
> -		call_void_qop(q, wait_finish, q);
> -		if (set_timestamp)
> -			v4l2_get_timestamp(&fileio->b.timestamp);
> -		if (!threadio->stop)
> -			ret = vb2_internal_qbuf(q, &fileio->b);
> -		call_void_qop(q, wait_prepare, q);
> -		if (ret || threadio->stop)
> -			break;
> -	}
> -
> -	/* Hmm, linux becomes *very* unhappy without this ... */
> -	while (!kthread_should_stop()) {
> -		set_current_state(TASK_INTERRUPTIBLE);
> -		schedule();
> -	}
> -	return 0;
> -}
> -
> -/*
> - * This function should not be used for anything else but the videobuf2-dvb
> - * support. If you think you have another good use-case for this, then please
> - * contact the linux-media mailinglist first.
> - */
> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> -			const char *thread_name)
> -{
> -	struct vb2_threadio_data *threadio;
> -	int ret = 0;
> -
> -	if (q->threadio)
> -		return -EBUSY;
> -	if (vb2_is_busy(q))
> -		return -EBUSY;
> -	if (WARN_ON(q->fileio))
> -		return -EBUSY;
> -
> -	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
> -	if (threadio == NULL)
> -		return -ENOMEM;
> -	threadio->fnc = fnc;
> -	threadio->priv = priv;
> -
> -	ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type));
> -	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
> -	if (ret)
> -		goto nomem;
> -	q->threadio = threadio;
> -	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
> -	if (IS_ERR(threadio->thread)) {
> -		ret = PTR_ERR(threadio->thread);
> -		threadio->thread = NULL;
> -		goto nothread;
> -	}
> -	return 0;
> -
> -nothread:
> -	__vb2_cleanup_fileio(q);
> -nomem:
> -	kfree(threadio);
> -	return ret;
> -}
> -EXPORT_SYMBOL_GPL(vb2_thread_start);
> -
> -int vb2_thread_stop(struct vb2_queue *q)
> -{
> -	struct vb2_threadio_data *threadio = q->threadio;
> -	int err;
> -
> -	if (threadio == NULL)
> -		return 0;
> -	threadio->stop = true;
> -	/* Wake up all pending sleeps in the thread */
> -	vb2_queue_error(q);
> -	err = kthread_stop(threadio->thread);
> -	__vb2_cleanup_fileio(q);
> -	threadio->thread = NULL;
> -	kfree(threadio);
> -	q->threadio = NULL;
> -	return err;
> -}
> -EXPORT_SYMBOL_GPL(vb2_thread_stop);
> -
> -/*
> - * The following functions are not part of the vb2 core API, but are helper
> - * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
> - * and struct vb2_ops.
> - * They contain boilerplate code that most if not all drivers have to do
> - * and so they simplify the driver code.
> - */
> -
> -/* The queue is busy if there is a owner and you are not that owner. */
> -static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
> -{
> -	return vdev->queue->owner && vdev->queue->owner != file->private_data;
> -}
> -
> -/* vb2 ioctl helpers */
> -
> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
> -			  struct v4l2_requestbuffers *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	int res = __verify_memory_type(vdev->queue, p->memory, p->type);
> -
> -	if (res)
> -		return res;
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	res = __reqbufs(vdev->queue, p);
> -	/* If count == 0, then the owner has released all buffers and he
> -	   is no longer owner of the queue. Otherwise we have a new owner. */
> -	if (res == 0)
> -		vdev->queue->owner = p->count ? file->private_data : NULL;
> -	return res;
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
> -
> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
> -			  struct v4l2_create_buffers *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	int res = __verify_memory_type(vdev->queue, p->memory, p->format.type);
> -
> -	p->index = vdev->queue->num_buffers;
> -	/* If count == 0, then just check if memory and type are valid.
> -	   Any -EBUSY result from __verify_memory_type can be mapped to 0. */
> -	if (p->count == 0)
> -		return res != -EBUSY ? res : 0;
> -	if (res)
> -		return res;
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	res = __create_bufs(vdev->queue, p);
> -	if (res == 0)
> -		vdev->queue->owner = file->private_data;
> -	return res;
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
> -
> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> -			  struct v4l2_buffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_prepare_buf(vdev->queue, p);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
> -
> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
> -	return vb2_querybuf(vdev->queue, p);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
> -
> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_qbuf(vdev->queue, p);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
> -
> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
> -
> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_streamon(vdev->queue, i);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
> -
> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_streamoff(vdev->queue, i);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
> -
> -int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (vb2_queue_is_busy(vdev, file))
> -		return -EBUSY;
> -	return vb2_expbuf(vdev->queue, p);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
> -
> -/* v4l2_file_operations helpers */
> -
> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	return vb2_mmap(vdev->queue, vma);
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_mmap);
> -
> -int _vb2_fop_release(struct file *file, struct mutex *lock)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	if (lock)
> -		mutex_lock(lock);
> -	if (file->private_data == vdev->queue->owner) {
> -		vb2_queue_release(vdev->queue);
> -		vdev->queue->owner = NULL;
> -	}
> -	if (lock)
> -		mutex_unlock(lock);
> -	return v4l2_fh_release(file);
> -}
> -EXPORT_SYMBOL_GPL(_vb2_fop_release);
> -
> -int vb2_fop_release(struct file *file)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> -
> -	return _vb2_fop_release(file, lock);
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_release);
> -
> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> -		size_t count, loff_t *ppos)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> -	int err = -EBUSY;
> -
> -	if (!(vdev->queue->io_modes & VB2_WRITE))
> -		return -EINVAL;
> -	if (lock && mutex_lock_interruptible(lock))
> -		return -ERESTARTSYS;
> -	if (vb2_queue_is_busy(vdev, file))
> -		goto exit;
> -	err = vb2_write(vdev->queue, buf, count, ppos,
> -			file->f_flags & O_NONBLOCK);
> -	if (vdev->queue->fileio)
> -		vdev->queue->owner = file->private_data;
> -exit:
> -	if (lock)
> -		mutex_unlock(lock);
> -	return err;
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_write);
> -
> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
> -		size_t count, loff_t *ppos)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> -	int err = -EBUSY;
> -
> -	if (!(vdev->queue->io_modes & VB2_READ))
> -		return -EINVAL;
> -	if (lock && mutex_lock_interruptible(lock))
> -		return -ERESTARTSYS;
> -	if (vb2_queue_is_busy(vdev, file))
> -		goto exit;
> -	err = vb2_read(vdev->queue, buf, count, ppos,
> -			file->f_flags & O_NONBLOCK);
> -	if (vdev->queue->fileio)
> -		vdev->queue->owner = file->private_data;
> -exit:
> -	if (lock)
> -		mutex_unlock(lock);
> -	return err;
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_read);
> -
> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -	struct vb2_queue *q = vdev->queue;
> -	struct mutex *lock = q->lock ? q->lock : vdev->lock;
> -	unsigned res;
> -	void *fileio;
> -
> -	/*
> -	 * If this helper doesn't know how to lock, then you shouldn't be using
> -	 * it but you should write your own.
> -	 */
> -	WARN_ON(!lock);
> -
> -	if (lock && mutex_lock_interruptible(lock))
> -		return POLLERR;
> -
> -	fileio = q->fileio;
> -
> -	res = vb2_poll(vdev->queue, file, wait);
> -
> -	/* If fileio was started, then we have a new queue owner. */
> -	if (!fileio && q->fileio)
> -		q->owner = file->private_data;
> -	if (lock)
> -		mutex_unlock(lock);
> -	return res;
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_poll);
> -
> -#ifndef CONFIG_MMU
> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> -		unsigned long len, unsigned long pgoff, unsigned long flags)
> -{
> -	struct video_device *vdev = video_devdata(file);
> -
> -	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
> -}
> -EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
> -#endif
> -
> -/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
> -
> -void vb2_ops_wait_prepare(struct vb2_queue *vq)
> -{
> -	mutex_unlock(vq->lock);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
> -
> -void vb2_ops_wait_finish(struct vb2_queue *vq)
> -{
> -	mutex_lock(vq->lock);
> -}
> -EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
> +EXPORT_SYMBOL_GPL(vb2_core_queue_release);
>  
>  MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
>  MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
> diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h
> new file mode 100644
> index 0000000..3998ac9
> --- /dev/null
> +++ b/drivers/media/v4l2-core/videobuf2-internal.h
> @@ -0,0 +1,184 @@
> +#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H
> +#define _MEDIA_VIDEOBUF2_INTERNAL_H
> +
> +#include <linux/err.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <media/videobuf2-core.h>
> +
> +extern int vb2_debug;
> +
> +#define dprintk(level, fmt, arg...)					\
> +	do {								\
> +		if (vb2_debug >= level)					\
> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
> +	} while (0)
> +
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> +
> +/*
> + * If advanced debugging is on, then count how often each op is called
> + * successfully, which can either be per-buffer or per-queue.
> + *
> + * This makes it easy to check that the 'init' and 'cleanup'
> + * (and variations thereof) stay balanced.
> + */
> +
> +#define log_memop(vb, op)						\
> +	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
> +		(vb)->vb2_queue, (vb)->index, #op,			\
> +		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
> +
> +#define call_memop(vb, op, args...)					\
> +({									\
> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
> +	int err;							\
> +									\
> +	log_memop(vb, op);						\
> +	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
> +	if (!err)							\
> +		(vb)->cnt_mem_ ## op++;					\
> +	err;								\
> +})
> +
> +#define call_ptr_memop(vb, op, args...)					\
> +({									\
> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
> +	void *ptr;							\
> +									\
> +	log_memop(vb, op);						\
> +	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
> +	if (!IS_ERR_OR_NULL(ptr))					\
> +		(vb)->cnt_mem_ ## op++;					\
> +	ptr;								\
> +})
> +
> +#define call_void_memop(vb, op, args...)				\
> +({									\
> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
> +									\
> +	log_memop(vb, op);						\
> +	if (_q->mem_ops->op)						\
> +		_q->mem_ops->op(args);					\
> +	(vb)->cnt_mem_ ## op++;						\
> +})
> +
> +#define log_qop(q, op)							\
> +	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
> +		(q)->ops->op ? "" : " (nop)")
> +
> +#define call_qop(q, op, args...)					\
> +({									\
> +	int err;							\
> +									\
> +	log_qop(q, op);							\
> +	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
> +	if (!err)							\
> +		(q)->cnt_ ## op++;					\
> +	err;								\
> +})
> +
> +#define call_void_qop(q, op, args...)					\
> +({									\
> +	log_qop(q, op);							\
> +	if ((q)->ops->op)						\
> +		(q)->ops->op(args);					\
> +	(q)->cnt_ ## op++;						\
> +})
> +
> +#define log_vb_qop(vb, op, args...)					\
> +	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
> +		(vb)->vb2_queue, (vb)->index, #op,			\
> +		(vb)->vb2_queue->ops->op ? "" : " (nop)")
> +
> +#define call_vb_qop(vb, op, args...)					\
> +({									\
> +	int err;							\
> +									\
> +	log_vb_qop(vb, op);						\
> +	err = (vb)->vb2_queue->ops->op ?				\
> +		(vb)->vb2_queue->ops->op(args) : 0;			\
> +	if (!err)							\
> +		(vb)->cnt_ ## op++;					\
> +	err;								\
> +})
> +
> +#define call_void_vb_qop(vb, op, args...)				\
> +({									\
> +	log_vb_qop(vb, op);						\
> +	if ((vb)->vb2_queue->ops->op)					\
> +		(vb)->vb2_queue->ops->op(args);				\
> +	(vb)->cnt_ ## op++;						\
> +})
> +
> +#else
> +
> +#define call_memop(vb, op, args...)					\
> +	((vb)->vb2_queue->mem_ops->op ?					\
> +		(vb)->vb2_queue->mem_ops->op(args) : 0)
> +
> +#define call_ptr_memop(vb, op, args...)					\
> +	((vb)->vb2_queue->mem_ops->op ?					\
> +		(vb)->vb2_queue->mem_ops->op(args) : NULL)
> +
> +#define call_void_memop(vb, op, args...)				\
> +	do {								\
> +		if ((vb)->vb2_queue->mem_ops->op)			\
> +			(vb)->vb2_queue->mem_ops->op(args);		\
> +	} while (0)
> +
> +#define call_qop(q, op, args...)					\
> +	((q)->ops->op ? (q)->ops->op(args) : 0)
> +
> +#define call_void_qop(q, op, args...)					\
> +	do {								\
> +		if ((q)->ops->op)					\
> +			(q)->ops->op(args);				\
> +	} while (0)
> +
> +#define call_vb_qop(vb, op, args...)					\
> +	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
> +
> +#define call_void_vb_qop(vb, op, args...)				\
> +	do {								\
> +		if ((vb)->vb2_queue->ops->op)				\
> +			(vb)->vb2_queue->ops->op(args);			\
> +	} while (0)
> +
> +#endif
> +
> +#define call_bufop(q, op, args...)					\
> +({									\
> +	int ret = 0;							\
> +	if (q && q->buf_ops && q->buf_ops->op)				\
> +		ret = q->buf_ops->op(args);				\
> +	ret;								\
> +})
> +
> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
> +int vb2_verify_memory_type(struct vb2_queue *q,
> +		unsigned int memory, unsigned int type);
> +int vb2_verify_buffer(struct vb2_queue *q,
> +			unsigned int memory, unsigned int type,
> +			unsigned int index, unsigned int nplanes,
> +			void *pplane, const char *opname);
> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb);
> +
> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb);
> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
> +		unsigned int *count);
> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
> +		unsigned int *count, void *parg);
> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb);
> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblock);
> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
> +		unsigned int index, unsigned int plane, unsigned int flags);
> +int vb2_core_streamon(struct vb2_queue *q);
> +int vb2_core_streamoff(struct vb2_queue *q);
> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
> +
> +int __must_check vb2_core_queue_init(struct vb2_queue *q);
> +void vb2_core_queue_release(struct vb2_queue *q);
> +
> +#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */
> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
> index 2f2b738..9fc6bef 100644
> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
> @@ -24,8 +24,1648 @@
>  #include <linux/freezer.h>
>  #include <linux/kthread.h>
>  
> +#include <media/v4l2-dev.h>
> +#include <media/v4l2-fh.h>
> +#include <media/v4l2-event.h>
> +#include <media/v4l2-common.h>
>  #include <media/videobuf2-v4l2.h>
>  
> +#include "videobuf2-internal.h"
> +
> +/* Flags that are set by the vb2 core */
> +#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | \
> +				V4L2_BUF_FLAG_QUEUED | \
> +				V4L2_BUF_FLAG_DONE | \
> +				V4L2_BUF_FLAG_ERROR | \
> +				V4L2_BUF_FLAG_PREPARED | \
> +				V4L2_BUF_FLAG_TIMESTAMP_MASK)
> +
> +/* Output buffer flags that should be passed on to the driver */
> +#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | \
> +				V4L2_BUF_FLAG_BFRAME | \
> +				V4L2_BUF_FLAG_KEYFRAME | \
> +				V4L2_BUF_FLAG_TIMECODE)
> +
> +/**
> + * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
> + * returned to userspace
> + */
> +static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
> +{
> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct vb2_queue *q = vb->vb2_queue;
> +	unsigned int plane;
> +
> +	/* Copy back data such as timestamp, flags, etc. */
> +	b->index = vb->index;
> +	b->type = vb->type;
> +	b->memory = vb->memory;
> +	b->bytesused = 0;
> +
> +	b->flags = vbuf->flags;
> +	b->field = vbuf->field;
> +	b->timestamp = vbuf->timestamp;
> +	b->timecode = vbuf->timecode;
> +	b->sequence = vbuf->sequence;
> +
> +	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
> +		/*
> +		 * Fill in plane-related data if userspace provided an array
> +		 * for it. The caller has already verified memory and size.
> +		 */
> +		b->length = vb->num_planes;
> +		for (plane = 0; plane < vb->num_planes; ++plane) {
> +			struct v4l2_plane *pdst = &b->m.planes[plane];
> +			struct vb2_plane *psrc = &vb->planes[plane];
> +
> +			pdst->bytesused = psrc->bytesused;
> +			pdst->length = psrc->length;
> +			if (q->memory == V4L2_MEMORY_MMAP)
> +				pdst->m.mem_offset = psrc->m.offset;
> +			else if (q->memory == V4L2_MEMORY_USERPTR)
> +				pdst->m.userptr = psrc->m.userptr;
> +			else if (q->memory == V4L2_MEMORY_DMABUF)
> +				pdst->m.fd = psrc->m.fd;
> +			pdst->data_offset = psrc->data_offset;
> +		}
> +	} else {
> +		/*
> +		 * We use length and offset in v4l2_planes array even for
> +		 * single-planar buffers, but userspace does not.
> +		 */
> +		b->length = vb->planes[0].length;
> +		b->bytesused = vb->planes[0].bytesused;
> +		if (q->memory == V4L2_MEMORY_MMAP)
> +			b->m.offset = vb->planes[0].m.offset;
> +		else if (q->memory == V4L2_MEMORY_USERPTR)
> +			b->m.userptr = vb->planes[0].m.userptr;
> +		else if (q->memory == V4L2_MEMORY_DMABUF)
> +			b->m.fd = vb->planes[0].m.fd;
> +	}
> +
> +	/*
> +	 * Clear any buffer state related flags.
> +	 */
> +	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
> +	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
> +		/*
> +		 * For non-COPY timestamps, drop timestamp source bits
> +		 * and obtain the timestamp source from the queue.
> +		 */
> +		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> +		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> +	}
> +
> +	switch (vb->state) {
> +	case VB2_BUF_STATE_QUEUED:
> +	case VB2_BUF_STATE_ACTIVE:
> +		b->flags |= V4L2_BUF_FLAG_QUEUED;
> +		break;
> +	case VB2_BUF_STATE_ERROR:
> +		b->flags |= V4L2_BUF_FLAG_ERROR;
> +		/* fall through */
> +	case VB2_BUF_STATE_DONE:
> +		b->flags |= V4L2_BUF_FLAG_DONE;
> +		break;
> +	case VB2_BUF_STATE_PREPARED:
> +		b->flags |= V4L2_BUF_FLAG_PREPARED;
> +		break;
> +	case VB2_BUF_STATE_PREPARING:
> +	case VB2_BUF_STATE_DEQUEUED:
> +		/* nothing */
> +		break;
> +	}
> +
> +	if (vb2_buffer_in_use(q, vb))
> +		b->flags |= V4L2_BUF_FLAG_MAPPED;
> +
> +	return 0;
> +}
> +
> +/**
> + * __verify_length() - Verify that the bytesused value for each plane fits in
> + * the plane length and that the data offset doesn't exceed the bytesused value.
> + */
> +static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
> +{
> +	unsigned int length;
> +	unsigned int bytesused;
> +	unsigned int plane;
> +
> +	if (!V4L2_TYPE_IS_OUTPUT(b->type))
> +		return 0;
> +
> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> +		for (plane = 0; plane < vb->num_planes; ++plane) {
> +			length = (b->memory == V4L2_MEMORY_USERPTR ||
> +				b->memory == V4L2_MEMORY_DMABUF)
> +				? b->m.planes[plane].length
> +				: vb->planes[plane].length;
> +			bytesused = b->m.planes[plane].bytesused
> +				? b->m.planes[plane].bytesused : length;
> +
> +			if (b->m.planes[plane].bytesused > length)
> +				return -EINVAL;
> +
> +			if (b->m.planes[plane].data_offset > 0 &&
> +				b->m.planes[plane].data_offset >= bytesused)
> +				return -EINVAL;
> +		}
> +	} else {
> +		length = (b->memory == V4L2_MEMORY_USERPTR)
> +			? b->length : vb->planes[0].length;
> +
> +		if (b->bytesused > length)
> +			return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
> + * v4l2_buffer by the userspace. It also verifies that struct
> + * v4l2_buffer has a valid number of planes.
> + */
> +static int __fill_vb2_buffer(struct vb2_buffer *vb, void *pb,
> +				struct vb2_plane *planes)
> +{
> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	unsigned int plane;
> +	int ret;
> +
> +	ret = __verify_length(vb, b);
> +	if (ret < 0) {
> +		dprintk(1, "plane parameters verification failed: %d\n", ret);
> +		return ret;
> +	}
> +	vb->state = VB2_BUF_STATE_PREPARING;
> +	vbuf->timestamp.tv_sec = 0;
> +	vbuf->timestamp.tv_usec = 0;
> +	vbuf->sequence = 0;
> +
> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
> +		if (b->memory == V4L2_MEMORY_USERPTR) {
> +			for (plane = 0; plane < vb->num_planes; ++plane) {
> +				planes[plane].m.userptr =
> +					b->m.planes[plane].m.userptr;
> +				planes[plane].length =
> +					b->m.planes[plane].length;
> +			}
> +		}
> +		if (b->memory == V4L2_MEMORY_DMABUF) {
> +			for (plane = 0; plane < vb->num_planes; ++plane) {
> +				planes[plane].m.fd =
> +					b->m.planes[plane].m.fd;
> +				planes[plane].length =
> +					b->m.planes[plane].length;
> +			}
> +		}
> +
> +		/* Fill in driver-provided information for OUTPUT types */
> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> +			/*
> +			 * Will have to go up to b->length when API starts
> +			 * accepting variable number of planes.
> +			 *
> +			 * If bytesused == 0 for the output buffer, then fall
> +			 * back to the full buffer size. In that case
> +			 * userspace clearly never bothered to set it and
> +			 * it's a safe assumption that they really meant to
> +			 * use the full plane sizes.
> +			 *
> +			 * Some drivers, e.g. old codec drivers, use bytesused == 0
> +			 * as a way to indicate that streaming is finished.
> +			 * In that case, the driver should use the
> +			 * allow_zero_bytesused flag to keep old userspace
> +			 * applications working.
> +			 */
> +			for (plane = 0; plane < vb->num_planes; ++plane) {
> +				struct vb2_plane *pdst = &planes[plane];
> +				struct v4l2_plane *psrc = &b->m.planes[plane];
> +
> +				if (psrc->bytesused == 0)
> +					vb2_warn_zero_bytesused(vb);
> +
> +				if (vb->vb2_queue->allow_zero_bytesused)
> +					pdst->bytesused = psrc->bytesused;
> +				else
> +					pdst->bytesused = psrc->bytesused ?
> +						psrc->bytesused : pdst->length;
> +				pdst->data_offset = psrc->data_offset;
> +			}
> +		}
> +	} else {
> +		/*
> +		 * Single-planar buffers do not use planes array,
> +		 * so fill in relevant v4l2_buffer struct fields instead.
> +		 * In videobuf we use our internal V4l2_planes struct for
> +		 * single-planar buffers as well, for simplicity.
> +		 *
> +		 * If bytesused == 0 for the output buffer, then fall back
> +		 * to the full buffer size as that's a sensible default.
> +		 *
> +		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
> +		 * a way to indicate that streaming is finished. In that case,
> +		 * the driver should use the allow_zero_bytesused flag to keep
> +		 * old userspace applications working.
> +		 */
> +		if (b->memory == V4L2_MEMORY_USERPTR) {
> +			planes[0].m.userptr = b->m.userptr;
> +			planes[0].length = b->length;
> +		}
> +
> +		if (b->memory == V4L2_MEMORY_DMABUF) {
> +			planes[0].m.fd = b->m.fd;
> +			planes[0].length = b->length;
> +		}
> +
> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> +			if (b->bytesused == 0)
> +				vb2_warn_zero_bytesused(vb);
> +
> +			if (vb->vb2_queue->allow_zero_bytesused)
> +				planes[0].bytesused = b->bytesused;
> +			else
> +				planes[0].bytesused = b->bytesused ?
> +					b->bytesused : planes[0].length;
> +		} else
> +			planes[0].bytesused = 0;
> +
> +	}
> +
> +	/* Zero flags that the vb2 core handles */
> +	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
> +	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
> +			!V4L2_TYPE_IS_OUTPUT(b->type)) {
> +		/*
> +		 * Non-COPY timestamps and non-OUTPUT queues will get
> +		 * their timestamp and timestamp source flags from the
> +		 * queue.
> +		 */
> +		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> +	}
> +
> +	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
> +		/*
> +		 * For output buffers mask out the timecode flag:
> +		 * this will be handled later in vb2_internal_qbuf().
> +		 * The 'field' is valid metadata for this output buffer
> +		 * and so that needs to be copied here.
> +		 */
> +		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
> +		vbuf->field = b->field;
> +	} else {
> +		/* Zero any output buffer flags as this is a capture buffer */
> +		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
> +	}
> +
> +	return 0;
> +}
> +
> +static int __fill_vb2_timestamp(struct vb2_buffer *vb, void *pb)
> +{
> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +	struct vb2_queue *q = vb->vb2_queue;
> +
> +	/*
> +	 * For output buffers copy the timestamp if needed,
> +	 * and the timecode field and flag if needed.
> +	 */
> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY)
> +		vbuf->timestamp = b->timestamp;
> +	vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
> +	if (b->flags & V4L2_BUF_FLAG_TIMECODE)
> +		vbuf->timecode = b->timecode;
> +
> +	return 0;
> +};
> +
> +static int __is_last(struct vb2_buffer *vb)
> +{
> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> +
> +	return (vbuf->flags & V4L2_BUF_FLAG_LAST);
> +}
> +
> +const struct vb2_buf_ops v4l2_buf_ops = {
> +	.fill_user_buffer	= __fill_v4l2_buffer,
> +	.fill_vb2_buffer	= __fill_vb2_buffer,
> +	.fill_vb2_timestamp	= __fill_vb2_timestamp,
> +	.is_last		= __is_last,
> +};
> +
> +/**
> + * vb2_querybuf() - query video buffer information
> + * @q:		videobuf queue
> + * @b:		buffer struct passed from userspace to vidioc_querybuf handler
> + *		in driver
> + *
> + * Should be called from vidioc_querybuf ioctl handler in driver.
> + * This function will verify the passed v4l2_buffer structure and fill the
> + * relevant information for the userspace.
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_querybuf handler in driver.
> + */
> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +{
> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
> +			b->length, b->m.planes, "querybuf");
> +
> +	return ret ? ret : vb2_core_querybuf(q, b->index, b);
> +}
> +EXPORT_SYMBOL(vb2_querybuf);
> +
> +/**
> + * vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies
> + * the memory and type values.
> + * @q:		videobuf2 queue
> + * @req:	struct passed from userspace to vidioc_reqbufs handler
> + *		in driver
> + */
> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
> +{
> +	int ret = vb2_verify_memory_type(q, req->memory, req->type);
> +
> +	if (ret)
> +		return ret;
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_core_reqbufs(q, req->memory, &req->count);
> +}
> +EXPORT_SYMBOL_GPL(vb2_reqbufs);
> +
> +/**
> + * vb2_create_bufs() - Wrapper for vb2_core_create_bufs() that also verifies
> + * the memory and type values.
> + * @q:		videobuf2 queue
> + * @create:	creation parameters, passed from userspace to vidioc_create_bufs
> + *		handler in driver
> + */
> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
> +{
> +	int ret = vb2_verify_memory_type(q, create->memory, create->format.type);
> +
> +	if (ret)
> +		return ret;
> +	if (create->count && vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +	return vb2_core_create_bufs(q, create->memory, &create->count, &create->format);
> +}
> +EXPORT_SYMBOL_GPL(vb2_create_bufs);
> +
> +/**
> + * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
> + * @q:		videobuf2 queue
> + * @b:		buffer structure passed from userspace to vidioc_prepare_buf
> + *		handler in driver
> + *
> + * Should be called from vidioc_prepare_buf ioctl handler of a driver.
> + * This function:
> + * 1) verifies the passed buffer,
> + * 2) calls buf_prepare callback in the driver (if provided), in which
> + *    driver-specific buffer initialization can be performed,
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_prepare_buf handler in driver.
> + */
> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
> +{
> +	int ret;
> +
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
> +			b->length, b->m.planes, "prepare_buf");
> +	if (ret)
> +		return ret;
> +
> +	if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
> +		/*
> +		 * If the format's field is ALTERNATE, then the buffer's field
> +		 * should be either TOP or BOTTOM, not ALTERNATE since that
> +		 * makes no sense. The driver has to know whether the
> +		 * buffer represents a top or a bottom field in order to
> +		 * program any DMA correctly. Using ALTERNATE is wrong, since
> +		 * that just says that it is either a top or a bottom field,
> +		 * but not which of the two it is.
> +		 */
> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
> +				"for an output buffer\n");
> +		return -EINVAL;
> +	}
> +
> +	return vb2_core_prepare_buf(q, b->index, b);
> +}
> +EXPORT_SYMBOL_GPL(vb2_prepare_buf);
> +
> +static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +{
> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
> +			b->length, b->m.planes, "qbuf");
> +	struct vb2_buffer *vb;
> +
> +	if (ret)
> +		return ret;
> +
> +	vb = q->bufs[b->index];
> +
> +	if (vb->state == VB2_BUF_STATE_DEQUEUED
> +			&& b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
> +				"for an output buffer\n");
> +		return -EINVAL;
> +	}
> +
> +	return ret ? ret : vb2_core_qbuf(q, b->index, b);
> +}
> +
> +/**
> + * vb2_qbuf() - Queue a buffer from userspace
> + * @q:		videobuf2 queue
> + * @b:		buffer structure passed from userspace to vidioc_qbuf handler
> + *		in driver
> + *
> + * Should be called from vidioc_qbuf ioctl handler of a driver.
> + * This function:
> + * 1) verifies the passed buffer,
> + * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
> + *    which driver-specific buffer initialization can be performed,
> + * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
> + *    callback for processing.
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_qbuf handler in driver.
> + */
> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_internal_qbuf(q, b);
> +}
> +EXPORT_SYMBOL_GPL(vb2_qbuf);
> +
> +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
> +			bool nonblocking)
> +{
> +	if (b->type != q->type) {
> +		dprintk(1, "invalid buffer type\n");
> +		return -EINVAL;
> +	}
> +	return vb2_core_dqbuf(q, b, nonblocking);
> +}
> +
> +/**
> + * vb2_dqbuf() - Dequeue a buffer to the userspace
> + * @q:		videobuf2 queue
> + * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
> + *		in driver
> + * @nonblocking: if true, this call will not sleep waiting for a buffer if no
> + *		 buffers ready for dequeuing are present. Normally the driver
> + *		 would be passing (file->f_flags & O_NONBLOCK) here
> + *
> + * Should be called from vidioc_dqbuf ioctl handler of a driver.
> + * This function:
> + * 1) verifies the passed buffer,
> + * 2) calls buf_finish callback in the driver (if provided), in which
> + *    driver can perform any additional operations that may be required before
> + *    returning the buffer to userspace, such as cache sync,
> + * 3) the buffer struct members are filled with relevant information for
> + *    the userspace.
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_dqbuf handler in driver.
> + */
> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +	return vb2_internal_dqbuf(q, b, nonblocking);
> +}
> +EXPORT_SYMBOL_GPL(vb2_dqbuf);
> +
> +/**
> + * vb2_expbuf() - Export a buffer as a file descriptor
> + * @q:		videobuf2 queue
> + * @eb:		export buffer structure passed from userspace to vidioc_expbuf
> + *		handler in driver
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_expbuf handler in driver.
> + */
> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index,
> +				eb->plane, eb->flags);
> +}
> +EXPORT_SYMBOL_GPL(vb2_expbuf);
> +
> +static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> +{
> +	if (type != q->type) {
> +		dprintk(1, "invalid stream type\n");
> +		return -EINVAL;
> +	}
> +	return vb2_core_streamon(q);
> +}
> +
> +/**
> + * vb2_streamon - start streaming
> + * @q:		videobuf2 queue
> + * @type:	type argument passed from userspace to vidioc_streamon handler
> + *
> + * Should be called from vidioc_streamon handler of a driver.
> + * This function:
> + * 1) verifies current state
> + * 2) passes any previously queued buffers to the driver and starts streaming
> + *
> + * The return values from this function are intended to be directly returned
> + * from vidioc_streamon handler in the driver.
> + */
> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +	return vb2_internal_streamon(q, type);
> +}
> +EXPORT_SYMBOL_GPL(vb2_streamon);
> +
> +static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> +{
> +	if (type != q->type) {
> +		dprintk(1, "invalid stream type\n");
> +		return -EINVAL;
> +	}
> +	return vb2_core_streamoff(q);
> +}
> +
> +/**
> + * vb2_streamoff - stop streaming
> + * @q:		videobuf2 queue
> + * @type:	type argument passed from userspace to vidioc_streamoff handler
> + *
> + * Should be called from vidioc_streamoff handler of a driver.
> + * This function:
> + * 1) verifies current state,
> + * 2) stop streaming and dequeues any queued buffers, including those previously
> + *    passed to the driver (after waiting for the driver to finish).
> + *
> + * This call can be used for pausing playback.
> + * The return values from this function are intended to be directly returned
> + * from vidioc_streamoff handler in the driver
> + */
> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "file io in progress\n");
> +		return -EBUSY;
> +	}
> +	return vb2_internal_streamoff(q, type);
> +}
> +EXPORT_SYMBOL_GPL(vb2_streamoff);
> +
> +/**
> + * vb2_mmap() - map video buffers into application address space
> + * @q:		videobuf2 queue
> + * @vma:	vma passed to the mmap file operation handler in the driver
> + *
> + * Should be called from mmap file operation handler of a driver.
> + * This function maps one plane of one of the available video buffers to
> + * userspace. To map whole video memory allocated on reqbufs, this function
> + * has to be called once per each plane per each buffer previously allocated.
> + *
> + * When the userspace application calls mmap, it passes to it an offset returned
> + * to it earlier by the means of vidioc_querybuf handler. That offset acts as
> + * a "cookie", which is then used to identify the plane to be mapped.
> + * This function finds a plane with a matching offset and a mapping is performed
> + * by the means of a provided memory operation.
> + *
> + * The return values from this function are intended to be directly returned
> + * from the mmap handler in driver.
> + */
> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
> +{
> +	if (vb2_fileio_is_active(q)) {
> +		dprintk(1, "mmap: file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_core_mmap(q, vma);
> +}
> +EXPORT_SYMBOL_GPL(vb2_mmap);
> +
> +static int __vb2_init_fileio(struct vb2_queue *q, int read);
> +static int __vb2_cleanup_fileio(struct vb2_queue *q);
> +
> +/**
> + * vb2_poll() - implements poll userspace operation
> + * @q:		videobuf2 queue
> + * @file:	file argument passed to the poll file operation handler
> + * @wait:	wait argument passed to the poll file operation handler
> + *
> + * This function implements poll file operation handler for a driver.
> + * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
> + * be informed that the file descriptor of a video device is available for
> + * reading.
> + * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
> + * will be reported as available for writing.
> + *
> + * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
> + * pending events.
> + *
> + * The return values from this function are intended to be directly returned
> + * from poll handler in driver.
> + */
> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
> +{
> +	struct video_device *vfd = video_devdata(file);
> +	unsigned long req_events = poll_requested_events(wait);
> +	struct vb2_buffer *vb = NULL;
> +	unsigned int res = 0;
> +	unsigned long flags;
> +
> +	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
> +		struct v4l2_fh *fh = file->private_data;
> +
> +		if (v4l2_event_pending(fh))
> +			res = POLLPRI;
> +		else if (req_events & POLLPRI)
> +			poll_wait(file, &fh->wait, wait);
> +	}
> +
> +	if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
> +		return res;
> +	if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
> +		return res;
> +
> +	/*
> +	 * Start file I/O emulator only if streaming API has not been used yet.
> +	 */
> +	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
> +		if (!q->is_output && (q->io_modes & VB2_READ) &&
> +				(req_events & (POLLIN | POLLRDNORM))) {
> +			if (__vb2_init_fileio(q, 1))
> +				return res | POLLERR;
> +		}
> +		if (q->is_output && (q->io_modes & VB2_WRITE) &&
> +				(req_events & (POLLOUT | POLLWRNORM))) {
> +			if (__vb2_init_fileio(q, 0))
> +				return res | POLLERR;
> +			/*
> +			 * Write to OUTPUT queue can be done immediately.
> +			 */
> +			return res | POLLOUT | POLLWRNORM;
> +		}
> +	}
> +
> +	/*
> +	 * There is nothing to wait for if the queue isn't streaming, or if the
> +	 * error flag is set.
> +	 */
> +	if (!vb2_is_streaming(q) || q->error)
> +		return res | POLLERR;
> +	/*
> +	 * For compatibility with vb1: if QBUF hasn't been called yet, then
> +	 * return POLLERR as well. This only affects capture queues, output
> +	 * queues will always initialize waiting_for_buffers to false.
> +	 */
> +	if (q->waiting_for_buffers)
> +		return res | POLLERR;
> +
> +	/*
> +	 * For output streams you can write as long as there are fewer buffers
> +	 * queued than there are buffers available.
> +	 */
> +	if (q->is_output && q->queued_count < q->num_buffers)
> +		return res | POLLOUT | POLLWRNORM;
> +
> +	if (list_empty(&q->done_list)) {
> +		/*
> +		 * If the last buffer was dequeued from a capture queue,
> +		 * return immediately. DQBUF will return -EPIPE.
> +		 */
> +		if (q->last_buffer_dequeued)
> +			return res | POLLIN | POLLRDNORM;
> +
> +		poll_wait(file, &q->done_wq, wait);
> +	}
> +
> +	/*
> +	 * Take first buffer available for dequeuing.
> +	 */
> +	spin_lock_irqsave(&q->done_lock, flags);
> +	if (!list_empty(&q->done_list))
> +		vb = list_first_entry(&q->done_list, struct vb2_buffer,
> +					done_entry);
> +	spin_unlock_irqrestore(&q->done_lock, flags);
> +
> +	if (vb && (vb->state == VB2_BUF_STATE_DONE
> +			|| vb->state == VB2_BUF_STATE_ERROR)) {
> +		return (q->is_output) ?
> +				res | POLLOUT | POLLWRNORM :
> +				res | POLLIN | POLLRDNORM;
> +	}
> +	return res;
> +}
> +EXPORT_SYMBOL_GPL(vb2_poll);
> +
> +/**
> + * vb2_queue_init() - initialize a videobuf2 queue
> + * @q:		videobuf2 queue; this structure should be allocated in driver
> + *
> + * The vb2_queue structure should be allocated by the driver. The driver is
> + * responsible of clearing it's content and setting initial values for some
> + * required entries before calling this function.
> + * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
> + * to the struct vb2_queue description in include/media/videobuf2-core.h
> + * for more information.
> + */
> +int vb2_queue_init(struct vb2_queue *q)
> +{
> +	if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
> +		|| WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
> +		|| WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
> +		return -EINVAL;
> +	/*
> +	 * Sanity check
> +	 */
> +	if (WARN_ON(!q)	|| WARN_ON(!q->type))
> +		return -EINVAL;
> +
> +	if (WARN_ON(q->timestamp_flags &
> +		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
> +		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
> +		return -EINVAL;
> +
> +	/* Warn that the driver should choose an appropriate timestamp type */
> +	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> +		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
> +
> +	if (q->buf_struct_size == 0)
> +		q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
> +
> +	q->buf_ops = &v4l2_buf_ops;
> +	q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
> +	q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
> +
> +	return vb2_core_queue_init(q);
> +}
> +EXPORT_SYMBOL_GPL(vb2_queue_init);
> +
> +/**
> + * vb2_queue_release() - stop streaming, release the queue and free memory
> + * @q:		videobuf2 queue
> + *
> + * This function stops streaming and performs necessary clean ups, including
> + * freeing video buffer memory. The driver is responsible for freeing
> + * the vb2_queue structure itself.
> + */
> +void vb2_queue_release(struct vb2_queue *q)
> +{
> +	__vb2_cleanup_fileio(q);
> +	vb2_core_queue_release(q);
> +}
> +EXPORT_SYMBOL_GPL(vb2_queue_release);
> +
> +/**
> + * struct vb2_fileio_buf - buffer context used by file io emulator
> + *
> + * vb2 provides a compatibility layer and emulator of file io (read and
> + * write) calls on top of streaming API. This structure is used for
> + * tracking context related to the buffers.
> + */
> +struct vb2_fileio_buf {
> +	void *vaddr;
> +	unsigned int size;
> +	unsigned int pos;
> +	unsigned int queued:1;
> +};
> +
> +/**
> + * struct vb2_fileio_data - queue context used by file io emulator
> + *
> + * @cur_index:	the index of the buffer currently being read from or
> + *		written to. If equal to q->num_buffers then a new buffer
> + *		must be dequeued.
> + * @initial_index: in the read() case all buffers are queued up immediately
> + *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
> + *		buffers. However, in the write() case no buffers are initially
> + *		queued, instead whenever a buffer is full it is queued up by
> + *		__vb2_perform_fileio(). Only once all available buffers have
> + *		been queued up will __vb2_perform_fileio() start to dequeue
> + *		buffers. This means that initially __vb2_perform_fileio()
> + *		needs to know what buffer index to use when it is queuing up
> + *		the buffers for the first time. That initial index is stored
> + *		in this field. Once it is equal to q->num_buffers all
> + *		available buffers have been queued and __vb2_perform_fileio()
> + *		should start the normal dequeue/queue cycle.
> + *
> + * vb2 provides a compatibility layer and emulator of file io (read and
> + * write) calls on top of streaming API. For proper operation it required
> + * this structure to save the driver state between each call of the read
> + * or write function.
> + */
> +struct vb2_fileio_data {
> +	struct v4l2_requestbuffers req;
> +	struct v4l2_plane p;
> +	struct v4l2_buffer b;
> +	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
> +	unsigned int cur_index;
> +	unsigned int initial_index;
> +	unsigned int q_count;
> +	unsigned int dq_count;
> +	unsigned read_once:1;
> +	unsigned write_immediately:1;
> +};
> +
> +/**
> + * __vb2_init_fileio() - initialize file io emulator
> + * @q:		videobuf2 queue
> + * @read:	mode selector (1 means read, 0 means write)
> + */
> +static int __vb2_init_fileio(struct vb2_queue *q, int read)
> +{
> +	struct vb2_fileio_data *fileio;
> +	int i, ret;
> +	unsigned int count = 0;
> +
> +	/*
> +	 * Sanity check
> +	 */
> +	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
> +			(!read && !(q->io_modes & VB2_WRITE))))
> +		return -EINVAL;
> +
> +	/*
> +	 * Check if device supports mapping buffers to kernel virtual space.
> +	 */
> +	if (!q->mem_ops->vaddr)
> +		return -EBUSY;
> +
> +	/*
> +	 * Check if streaming api has not been already activated.
> +	 */
> +	if (q->streaming || q->num_buffers > 0)
> +		return -EBUSY;
> +
> +	/*
> +	 * Start with count 1, driver can increase it in queue_setup()
> +	 */
> +	count = 1;
> +
> +	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, "
> +		"write_immediately %d\n",
> +		(read) ? "read" : "write", count, q->fileio_read_once,
> +		q->fileio_write_immediately);
> +
> +	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
> +	if (fileio == NULL)
> +		return -ENOMEM;
> +
> +	fileio->read_once = q->fileio_read_once;
> +	fileio->write_immediately = q->fileio_write_immediately;
> +
> +	/*
> +	 * Request buffers and use MMAP type to force driver
> +	 * to allocate buffers by itself.
> +	 */
> +	fileio->req.count = count;
> +	fileio->req.memory = V4L2_MEMORY_MMAP;
> +	fileio->req.type = q->type;
> +	q->fileio = fileio;
> +	ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
> +	if (ret)
> +		goto err_kfree;
> +
> +	/*
> +	 * Check if plane_count is correct
> +	 * (multiplane buffers are not supported).
> +	 */
> +	if (q->bufs[0]->num_planes != 1) {
> +		ret = -EBUSY;
> +		goto err_reqbufs;
> +	}
> +
> +	/*
> +	 * Get kernel address of each buffer.
> +	 */
> +	for (i = 0; i < q->num_buffers; i++) {
> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
> +		if (fileio->bufs[i].vaddr == NULL) {
> +			ret = -EINVAL;
> +			goto err_reqbufs;
> +		}
> +		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
> +	}
> +
> +	/*
> +	 * Read mode requires pre queuing of all buffers.
> +	 */
> +	if (read) {
> +		bool is_multiplanar = q->is_multiplanar;
> +
> +		/*
> +		 * Queue all buffers.
> +		 */
> +		for (i = 0; i < q->num_buffers; i++) {
> +			struct v4l2_buffer *b = &fileio->b;
> +
> +			memset(b, 0, sizeof(*b));
> +			b->type = q->type;
> +			if (is_multiplanar) {
> +				memset(&fileio->p, 0, sizeof(fileio->p));
> +				b->m.planes = &fileio->p;
> +				b->length = 1;
> +			}
> +			b->memory = q->memory;
> +			b->index = i;
> +			ret = vb2_internal_qbuf(q, b);
> +			if (ret)
> +				goto err_reqbufs;
> +			fileio->bufs[i].queued = 1;
> +		}
> +		/*
> +		 * All buffers have been queued, so mark that by setting
> +		 * initial_index to q->num_buffers
> +		 */
> +		fileio->initial_index = q->num_buffers;
> +		fileio->cur_index = q->num_buffers;
> +	}
> +
> +	/*
> +	 * Start streaming.
> +	 */
> +	ret = vb2_internal_streamon(q, q->type);
> +	if (ret)
> +		goto err_reqbufs;
> +
> +	return ret;
> +
> +err_reqbufs:
> +	fileio->req.count = 0;
> +	vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
> +
> +err_kfree:
> +	q->fileio = NULL;
> +	kfree(fileio);
> +	return ret;
> +}
> +
> +/**
> + * __vb2_cleanup_fileio() - free resourced used by file io emulator
> + * @q:		videobuf2 queue
> + */
> +static int __vb2_cleanup_fileio(struct vb2_queue *q)
> +{
> +	struct vb2_fileio_data *fileio = q->fileio;
> +
> +	if (fileio) {
> +		vb2_internal_streamoff(q, q->type);
> +		q->fileio = NULL;
> +		fileio->req.count = 0;
> +		vb2_reqbufs(q, &fileio->req);
> +		kfree(fileio);
> +		dprintk(3, "file io emulator closed\n");
> +	}
> +	return 0;
> +}
> +
> +/**
> + * __vb2_perform_fileio() - perform a single file io (read or write) operation
> + * @q:		videobuf2 queue
> + * @data:	pointed to target userspace buffer
> + * @count:	number of bytes to read or write
> + * @ppos:	file handle position tracking pointer
> + * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
> + * @read:	access mode selector (1 means read, 0 means write)
> + */
> +static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data,
> +		size_t count, loff_t *ppos, int nonblock, int read)
> +{
> +	struct vb2_fileio_data *fileio;
> +	struct vb2_fileio_buf *buf;
> +	bool is_multiplanar = q->is_multiplanar;
> +	/*
> +	 * When using write() to write data to an output video node the vb2 core
> +	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
> +	 * else is able to provide this information with the write() operation.
> +	 */
> +	bool set_timestamp = !read &&
> +		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> +		V4L2_BUF_FLAG_TIMESTAMP_COPY;
> +	int ret, index;
> +
> +	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
> +		read ? "read" : "write", (long)*ppos, count,
> +		nonblock ? "non" : "");
> +
> +	if (!data)
> +		return -EINVAL;
> +
> +	/*
> +	 * Initialize emulator on first call.
> +	 */
> +	if (!vb2_fileio_is_active(q)) {
> +		ret = __vb2_init_fileio(q, read);
> +		dprintk(3, "vb2_init_fileio result: %d\n", ret);
> +		if (ret)
> +			return ret;
> +	}
> +	fileio = q->fileio;
> +
> +	/*
> +	 * Check if we need to dequeue the buffer.
> +	 */
> +	index = fileio->cur_index;
> +	if (index >= q->num_buffers) {
> +		/*
> +		 * Call vb2_dqbuf to get buffer back.
> +		 */
> +		memset(&fileio->b, 0, sizeof(fileio->b));
> +		fileio->b.type = q->type;
> +		fileio->b.memory = q->memory;
> +		if (is_multiplanar) {
> +			memset(&fileio->p, 0, sizeof(fileio->p));
> +			fileio->b.m.planes = &fileio->p;
> +			fileio->b.length = 1;
> +		}
> +		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
> +		dprintk(5, "vb2_dqbuf result: %d\n", ret);
> +		if (ret)
> +			return ret;
> +		fileio->dq_count += 1;
> +
> +		fileio->cur_index = index = fileio->b.index;
> +		buf = &fileio->bufs[index];
> +
> +		/*
> +		 * Get number of bytes filled by the driver
> +		 */
> +		buf->pos = 0;
> +		buf->queued = 0;
> +		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
> +				 : vb2_plane_size(q->bufs[index], 0);
> +
> +		/*
> +		 * Compensate for data_offset on read
> +		 * in the multiplanar case.
> +		 */
> +		if (is_multiplanar && read &&
> +			fileio->b.m.planes[0].data_offset < buf->size) {
> +			buf->pos = fileio->b.m.planes[0].data_offset;
> +			buf->size -= buf->pos;
> +		}
> +	} else {
> +		buf = &fileio->bufs[index];
> +	}
> +
> +	/*
> +	 * Limit count on last few bytes of the buffer.
> +	 */
> +	if (buf->pos + count > buf->size) {
> +		count = buf->size - buf->pos;
> +		dprintk(5, "reducing read count: %zd\n", count);
> +	}
> +
> +	/*
> +	 * Transfer data to userspace.
> +	 */
> +	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
> +		count, index, buf->pos);
> +	if (read)
> +		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
> +	else
> +		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
> +	if (ret) {
> +		dprintk(3, "error copying data\n");
> +		return -EFAULT;
> +	}
> +
> +	/*
> +	 * Update counters.
> +	 */
> +	buf->pos += count;
> +	*ppos += count;
> +
> +	/*
> +	 * Queue next buffer if required.
> +	 */
> +	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
> +		/*
> +		 * Check if this is the last buffer to read.
> +		 */
> +		if (read && fileio->read_once && fileio->dq_count == 1) {
> +			dprintk(3, "read limit reached\n");
> +			return __vb2_cleanup_fileio(q);
> +		}
> +
> +		/*
> +		 * Call vb2_qbuf and give buffer to the driver.
> +		 */
> +		memset(&fileio->b, 0, sizeof(fileio->b));
> +		fileio->b.type = q->type;
> +		fileio->b.memory = q->memory;
> +		fileio->b.index = index;
> +		fileio->b.bytesused = buf->pos;
> +		if (is_multiplanar) {
> +			memset(&fileio->p, 0, sizeof(fileio->p));
> +			fileio->p.bytesused = buf->pos;
> +			fileio->b.m.planes = &fileio->p;
> +			fileio->b.length = 1;
> +		}
> +		if (set_timestamp)
> +			v4l2_get_timestamp(&fileio->b.timestamp);
> +		ret = vb2_internal_qbuf(q, &fileio->b);
> +		dprintk(5, "vb2_dbuf result: %d\n", ret);
> +		if (ret)
> +			return ret;
> +
> +		/*
> +		 * Buffer has been queued, update the status
> +		 */
> +		buf->pos = 0;
> +		buf->queued = 1;
> +		buf->size = vb2_plane_size(q->bufs[index], 0);
> +		fileio->q_count += 1;
> +		/*
> +		 * If we are queuing up buffers for the first time, then
> +		 * increase initial_index by one.
> +		 */
> +		if (fileio->initial_index < q->num_buffers)
> +			fileio->initial_index++;
> +		/*
> +		 * The next buffer to use is either a buffer that's going to be
> +		 * queued for the first time (initial_index < q->num_buffers)
> +		 * or it is equal to q->num_buffers, meaning that the next
> +		 * time we need to dequeue a buffer since we've now queued up
> +		 * all the 'first time' buffers.
> +		 */
> +		fileio->cur_index = fileio->initial_index;
> +	}
> +
> +	/*
> +	 * Return proper number of bytes processed.
> +	 */
> +	if (ret == 0)
> +		ret = count;
> +	return ret;
> +}
> +
> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> +		loff_t *ppos, int nonblocking)
> +{
> +	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
> +}
> +EXPORT_SYMBOL_GPL(vb2_read);
> +
> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> +		loff_t *ppos, int nonblocking)
> +{
> +	return __vb2_perform_fileio(q, (char __user *) data, count,
> +							ppos, nonblocking, 0);
> +}
> +EXPORT_SYMBOL_GPL(vb2_write);
> +
> +struct vb2_threadio_data {
> +	struct task_struct *thread;
> +	vb2_thread_fnc fnc;
> +	void *priv;
> +	bool stop;
> +};
> +
> +static int vb2_thread(void *data)
> +{
> +	struct vb2_queue *q = data;
> +	struct vb2_threadio_data *threadio = q->threadio;
> +	struct vb2_fileio_data *fileio = q->fileio;
> +	bool set_timestamp = false;
> +	int prequeue = 0;
> +	int index = 0;
> +	int ret = 0;
> +
> +	if (q->is_output) {
> +		prequeue = q->num_buffers;
> +		set_timestamp =
> +			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
> +			V4L2_BUF_FLAG_TIMESTAMP_COPY;
> +	}
> +
> +	set_freezable();
> +
> +	for (;;) {
> +		struct vb2_buffer *vb;
> +
> +		/*
> +		 * Call vb2_dqbuf to get buffer back.
> +		 */
> +		memset(&fileio->b, 0, sizeof(fileio->b));
> +		fileio->b.type = q->type;
> +		fileio->b.memory = q->memory;
> +		if (prequeue) {
> +			fileio->b.index = index++;
> +			prequeue--;
> +		} else {
> +			call_void_qop(q, wait_finish, q);
> +			if (!threadio->stop)
> +				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
> +			call_void_qop(q, wait_prepare, q);
> +			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
> +		}
> +		if (ret || threadio->stop)
> +			break;
> +		try_to_freeze();
> +
> +		vb = q->bufs[fileio->b.index];
> +		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
> +			if (threadio->fnc(vb, threadio->priv))
> +				break;
> +		call_void_qop(q, wait_finish, q);
> +		if (set_timestamp)
> +			v4l2_get_timestamp(&fileio->b.timestamp);
> +		if (!threadio->stop)
> +			ret = vb2_internal_qbuf(q, &fileio->b);
> +		call_void_qop(q, wait_prepare, q);
> +		if (ret || threadio->stop)
> +			break;
> +	}
> +
> +	/* Hmm, linux becomes *very* unhappy without this ... */
> +	while (!kthread_should_stop()) {
> +		set_current_state(TASK_INTERRUPTIBLE);
> +		schedule();
> +	}
> +	return 0;
> +}
> +
> +/*
> + * This function should not be used for anything else but the videobuf2-dvb
> + * support. If you think you have another good use-case for this, then please
> + * contact the linux-media mailinglist first.
> + */
> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> +			const char *thread_name)
> +{
> +	struct vb2_threadio_data *threadio;
> +	int ret = 0;
> +
> +	if (q->threadio)
> +		return -EBUSY;
> +	if (vb2_is_busy(q))
> +		return -EBUSY;
> +	if (WARN_ON(q->fileio))
> +		return -EBUSY;
> +
> +	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
> +	if (threadio == NULL)
> +		return -ENOMEM;
> +	threadio->fnc = fnc;
> +	threadio->priv = priv;
> +
> +	ret = __vb2_init_fileio(q, !q->is_output);
> +	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
> +	if (ret)
> +		goto nomem;
> +	q->threadio = threadio;
> +	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
> +	if (IS_ERR(threadio->thread)) {
> +		ret = PTR_ERR(threadio->thread);
> +		threadio->thread = NULL;
> +		goto nothread;
> +	}
> +	return 0;
> +
> +nothread:
> +	__vb2_cleanup_fileio(q);
> +nomem:
> +	kfree(threadio);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(vb2_thread_start);
> +
> +int vb2_thread_stop(struct vb2_queue *q)
> +{
> +	struct vb2_threadio_data *threadio = q->threadio;
> +	int err;
> +
> +	if (threadio == NULL)
> +		return 0;
> +	threadio->stop = true;
> +	/* Wake up all pending sleeps in the thread */
> +	vb2_queue_error(q);
> +	err = kthread_stop(threadio->thread);
> +	__vb2_cleanup_fileio(q);
> +	threadio->thread = NULL;
> +	kfree(threadio);
> +	q->threadio = NULL;
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(vb2_thread_stop);
> +
> +/*
> + * The following functions are not part of the vb2 core API, but are helper
> + * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
> + * and struct vb2_ops.
> + * They contain boilerplate code that most if not all drivers have to do
> + * and so they simplify the driver code.
> + */
> +
> +/* The queue is busy if there is a owner and you are not that owner. */
> +static inline
> +bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
> +{
> +	return vdev->queue->owner && vdev->queue->owner != file->private_data;
> +}
> +
> +/* vb2 ioctl helpers */
> +
> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
> +			  struct v4l2_requestbuffers *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
> +
> +	if (res)
> +		return res;
> +	if (vb2_fileio_is_active(vdev->queue))
> +		return -EBUSY;
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count);
> +	/* If count == 0, then the owner has released all buffers and he
> +	   is no longer owner of the queue. Otherwise we have a new owner. */
> +	if (res == 0)
> +		vdev->queue->owner = p->count ? file->private_data : NULL;
> +	return res;
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
> +
> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
> +			  struct v4l2_create_buffers *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	int res = vb2_verify_memory_type(vdev->queue,
> +				p->memory, p->format.type);
> +
> +	if (vb2_fileio_is_active(vdev->queue))
> +		return -EBUSY;
> +	p->index = vdev->queue->num_buffers;
> +	/* If count == 0, then just check if memory and type are valid.
> +	   Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. */
> +	if (p->count == 0)
> +		return res != -EBUSY ? res : 0;
> +	if (res)
> +		return res;
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	res = vb2_core_create_bufs(vdev->queue,
> +				p->memory, &p->count, &p->format);
> +	if (res == 0)
> +		vdev->queue->owner = file->private_data;
> +	return res;
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
> +
> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> +			  struct v4l2_buffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_prepare_buf(vdev->queue, p);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
> +
> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
> +	return vb2_querybuf(vdev->queue, p);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
> +
> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_qbuf(vdev->queue, p);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
> +
> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
> +
> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_streamon(vdev->queue, i);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
> +
> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_streamoff(vdev->queue, i);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
> +
> +int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_queue_is_busy(vdev, file))
> +		return -EBUSY;
> +	return vb2_expbuf(vdev->queue, p);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
> +
> +/* v4l2_file_operations helpers */
> +
> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (vb2_fileio_is_active(vdev->queue)) {
> +		dprintk(1, "mmap: file io in progress\n");
> +		return -EBUSY;
> +	}
> +
> +	return vb2_mmap(vdev->queue, vma);
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_mmap);
> +
> +int _vb2_fop_release(struct file *file, struct mutex *lock)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	if (lock)
> +		mutex_lock(lock);
> +	if (file->private_data == vdev->queue->owner) {
> +		vb2_queue_release(vdev->queue);
> +		vdev->queue->owner = NULL;
> +	}
> +	if (lock)
> +		mutex_unlock(lock);
> +	return v4l2_fh_release(file);
> +}
> +EXPORT_SYMBOL_GPL(_vb2_fop_release);
> +
> +int vb2_fop_release(struct file *file)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> +
> +	return _vb2_fop_release(file, lock);
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_release);
> +
> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> +		size_t count, loff_t *ppos)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> +	int err = -EBUSY;
> +
> +	if (!(vdev->queue->io_modes & VB2_WRITE))
> +		return -EINVAL;
> +	if (lock && mutex_lock_interruptible(lock))
> +		return -ERESTARTSYS;
> +	if (vb2_queue_is_busy(vdev, file))
> +		goto exit;
> +	err = vb2_write(vdev->queue, buf, count, ppos,
> +			file->f_flags & O_NONBLOCK);
> +	if (vdev->queue->fileio)
> +		vdev->queue->owner = file->private_data;
> +exit:
> +	if (lock)
> +		mutex_unlock(lock);
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_write);
> +
> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
> +		size_t count, loff_t *ppos)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
> +	int err = -EBUSY;
> +
> +	if (!(vdev->queue->io_modes & VB2_READ))
> +		return -EINVAL;
> +	if (lock && mutex_lock_interruptible(lock))
> +		return -ERESTARTSYS;
> +	if (vb2_queue_is_busy(vdev, file))
> +		goto exit;
> +	err = vb2_read(vdev->queue, buf, count, ppos,
> +			file->f_flags & O_NONBLOCK);
> +	if (vdev->queue->fileio)
> +		vdev->queue->owner = file->private_data;
> +exit:
> +	if (lock)
> +		mutex_unlock(lock);
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_read);
> +
> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +	struct vb2_queue *q = vdev->queue;
> +	struct mutex *lock = q->lock ? q->lock : vdev->lock;
> +	unsigned res;
> +	void *fileio;
> +
> +	/*
> +	 * If this helper doesn't know how to lock, then you shouldn't be using
> +	 * it but you should write your own.
> +	 */
> +	WARN_ON(!lock);
> +
> +	if (lock && mutex_lock_interruptible(lock))
> +		return POLLERR;
> +
> +	fileio = q->fileio;
> +
> +	res = vb2_poll(vdev->queue, file, wait);
> +
> +	/* If fileio was started, then we have a new queue owner. */
> +	if (!fileio && q->fileio)
> +		q->owner = file->private_data;
> +	if (lock)
> +		mutex_unlock(lock);
> +	return res;
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_poll);
> +
> +#ifndef CONFIG_MMU
> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> +		unsigned long len, unsigned long pgoff, unsigned long flags)
> +{
> +	struct video_device *vdev = video_devdata(file);
> +
> +	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
> +}
> +EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
> +#endif
> +
> +/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
> +
> +void vb2_ops_wait_prepare(struct vb2_queue *vq)
> +{
> +	mutex_unlock(vq->lock);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
> +
> +void vb2_ops_wait_finish(struct vb2_queue *vq)
> +{
> +	mutex_lock(vq->lock);
> +}
> +EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
> +
>  MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
>  MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
>  MODULE_LICENSE("GPL");
> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
> index 09d7529..4044bed 100644
> --- a/include/media/videobuf2-core.h
> +++ b/include/media/videobuf2-core.h
> @@ -15,9 +15,18 @@
>  #include <linux/mm_types.h>
>  #include <linux/mutex.h>
>  #include <linux/poll.h>
> -#include <linux/videodev2.h>
>  #include <linux/dma-buf.h>
>  
> +#define VB2_MAX_FRAME	(32)
> +#define VB2_MAX_PLANES	(8)
> +
> +enum vb2_memory {
> +	VB2_MEMORY_UNKNOWN	= 0,
> +	VB2_MEMORY_MMAP		= 1,
> +	VB2_MEMORY_USERPTR	= 2,
> +	VB2_MEMORY_DMABUF	= 4,
> +};
> +
>  struct vb2_alloc_ctx;
>  struct vb2_fileio_data;
>  struct vb2_threadio_data;
> @@ -198,7 +207,7 @@ struct vb2_buffer {
>  	unsigned int		type;
>  	unsigned int		memory;
>  	unsigned int		num_planes;
> -	struct vb2_plane	planes[VIDEO_MAX_PLANES];
> +	struct vb2_plane	planes[VB2_MAX_PLANES];
>  
>  #ifdef CONFIG_VIDEO_ADV_DEBUG
>  	/*
> @@ -330,18 +339,24 @@ struct vb2_ops {
>  	void (*buf_queue)(struct vb2_buffer *vb);
>  };
>  
> -struct v4l2_fh;
> +struct vb2_buf_ops {
> +	int (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
> +	int (*fill_vb2_buffer)(struct vb2_buffer *vb, void *pb,
> +				struct vb2_plane *planes);
> +	int (*fill_vb2_timestamp)(struct vb2_buffer *vb, void *pb);
> +	int (*is_last)(struct vb2_buffer *vb);
> +};
>  
>  /**
>   * struct vb2_queue - a videobuf queue
>   *
> - * @type:	queue type (see V4L2_BUF_TYPE_* in linux/videodev2.h
> + * @type:	queue type (see VB2_BUF_TYPE_*)
>   * @io_modes:	supported io methods (see vb2_io_modes enum)
>   * @fileio_read_once:		report EOF after reading the first buffer
>   * @fileio_write_immediately:	queue buffer after each write() call
>   * @allow_zero_bytesused:	allow bytesused == 0 to be passed to the driver
>   * @lock:	pointer to a mutex that protects the vb2_queue struct. The
> - *		driver can set this to a mutex to let the v4l2 core serialize
> + *		driver can set this to a mutex to let the vb2 core serialize
>   *		the queuing ioctls. If the driver wants to handle locking
>   *		itself, then this should be set to NULL. This lock is not used
>   *		by the videobuf2 core API.
> @@ -351,10 +366,13 @@ struct v4l2_fh;
>   *		drivers to easily associate an owner filehandle with the queue.
>   * @ops:	driver-specific callbacks
>   * @mem_ops:	memory allocator specific callbacks
> + * @buf_ops:	callbacks to deliver buffer information
> + *		between user-space and kernel-space
>   * @drv_priv:	driver private data
>   * @buf_struct_size: size of the driver-specific buffer structure;
>   *		"0" indicates the driver doesn't want to use a custom buffer
> - *		structure type, so sizeof(struct vb2_buffer) will is used
> + *		structure type, so, sizeof(struct vb2_v4l2_buffer) will is used
> + *		in case of v4l2.
>   * @timestamp_flags: Timestamp flags; V4L2_BUF_FLAG_TIMESTAMP_* and
>   *		V4L2_BUF_FLAG_TSTAMP_SRC_*
>   * @gfp_flags:	additional gfp flags used when allocating the buffers.
> @@ -385,6 +403,8 @@ struct v4l2_fh;
>   * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
>   *		buffers. Only set for capture queues if qbuf has not yet been
>   *		called since poll() needs to return POLLERR in that situation.
> + * @is_multiplanar: set if buffer type is multiplanar
> + * @is_output:	set if buffer type is output
>   * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
>   *		last decoded buffer was already dequeued. Set for capture queues
>   *		when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
> @@ -399,10 +419,12 @@ struct vb2_queue {
>  	unsigned			allow_zero_bytesused:1;
>  
>  	struct mutex			*lock;
> -	struct v4l2_fh			*owner;
> +	void				*owner;
>  
>  	const struct vb2_ops		*ops;
>  	const struct vb2_mem_ops	*mem_ops;
> +	const struct vb2_buf_ops	*buf_ops;
> +
>  	void				*drv_priv;
>  	unsigned int			buf_struct_size;
>  	u32				timestamp_flags;
> @@ -412,7 +434,7 @@ struct vb2_queue {
>  	/* private: internal use only */
>  	struct mutex			mmap_lock;
>  	unsigned int			memory;
> -	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
> +	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
>  	unsigned int			num_buffers;
>  
>  	struct list_head		queued_list;
> @@ -423,13 +445,15 @@ struct vb2_queue {
>  	spinlock_t			done_lock;
>  	wait_queue_head_t		done_wq;
>  
> -	void				*alloc_ctx[VIDEO_MAX_PLANES];
> -	unsigned int			plane_sizes[VIDEO_MAX_PLANES];
> +	void				*alloc_ctx[VB2_MAX_PLANES];
> +	unsigned int			plane_sizes[VB2_MAX_PLANES];
>  
>  	unsigned int			streaming:1;
>  	unsigned int			start_streaming_called:1;
>  	unsigned int			error:1;
>  	unsigned int			waiting_for_buffers:1;
> +	unsigned int			is_multiplanar:1;
> +	unsigned int			is_output:1;
>  	unsigned int			last_buffer_dequeued:1;
>  
>  	struct vb2_fileio_data		*fileio;
> @@ -455,25 +479,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
>  void vb2_discard_done(struct vb2_queue *q);
>  int vb2_wait_for_all_buffers(struct vb2_queue *q);
>  
> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
> -
> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
> -
> -int __must_check vb2_queue_init(struct vb2_queue *q);
> -
> -void vb2_queue_release(struct vb2_queue *q);
>  void vb2_queue_error(struct vb2_queue *q);
> -
> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
> -
> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
> -
> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
>  #ifndef CONFIG_MMU
>  unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  				    unsigned long addr,
> @@ -481,41 +487,6 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>  				    unsigned long pgoff,
>  				    unsigned long flags);
>  #endif
> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> -		loff_t *ppos, int nonblock);
> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> -		loff_t *ppos, int nonblock);
> -
> -/*
> - * vb2_thread_fnc - callback function for use with vb2_thread
> - *
> - * This is called whenever a buffer is dequeued in the thread.
> - */
> -typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
> -
> -/**
> - * vb2_thread_start() - start a thread for the given queue.
> - * @q:		videobuf queue
> - * @fnc:	callback function
> - * @priv:	priv pointer passed to the callback function
> - * @thread_name:the name of the thread. This will be prefixed with "vb2-".
> - *
> - * This starts a thread that will queue and dequeue until an error occurs
> - * or @vb2_thread_stop is called.
> - *
> - * This function should not be used for anything else but the videobuf2-dvb
> - * support. If you think you have another good use-case for this, then please
> - * contact the linux-media mailinglist first.
> - */
> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> -		     const char *thread_name);
> -
> -/**
> - * vb2_thread_stop() - stop the thread for the given queue.
> - * @q:		videobuf queue
> - */
> -int vb2_thread_stop(struct vb2_queue *q);
>  
>  /**
>   * vb2_is_streaming() - return streaming status of the queue
> @@ -527,23 +498,6 @@ static inline bool vb2_is_streaming(struct vb2_queue *q)
>  }
>  
>  /**
> - * vb2_fileio_is_active() - return true if fileio is active.
> - * @q:		videobuf queue
> - *
> - * This returns true if read() or write() is used to stream the data
> - * as opposed to stream I/O. This is almost never an important distinction,
> - * except in rare cases. One such case is that using read() or write() to
> - * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
> - * is no way you can pass the field information of each buffer to/from
> - * userspace. A driver that supports this field format should check for
> - * this in the queue_setup op and reject it if this function returns true.
> - */
> -static inline bool vb2_fileio_is_active(struct vb2_queue *q)
> -{
> -	return q->fileio;
> -}
> -
> -/**
>   * vb2_is_busy() - return busy status of the queue
>   * @q:		videobuf queue
>   *
> @@ -620,47 +574,4 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q)
>  	q->last_buffer_dequeued = false;
>  }
>  
> -/*
> - * The following functions are not part of the vb2 core API, but are simple
> - * helper functions that you can use in your struct v4l2_file_operations,
> - * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock
> - * or video_device->lock is set, and they will set and test vb2_queue->owner
> - * to check if the calling filehandle is permitted to do the queuing operation.
> - */
> -
> -/* struct v4l2_ioctl_ops helpers */
> -
> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
> -			  struct v4l2_requestbuffers *p);
> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
> -			  struct v4l2_create_buffers *p);
> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> -			  struct v4l2_buffer *p);
> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
> -int vb2_ioctl_expbuf(struct file *file, void *priv,
> -	struct v4l2_exportbuffer *p);
> -
> -/* struct v4l2_file_operations helpers */
> -
> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
> -int vb2_fop_release(struct file *file);
> -int _vb2_fop_release(struct file *file, struct mutex *lock);
> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> -		size_t count, loff_t *ppos);
> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
> -		size_t count, loff_t *ppos);
> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
> -#ifndef CONFIG_MMU
> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> -		unsigned long len, unsigned long pgoff, unsigned long flags);
> -#endif
> -
> -/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
> -
> -void vb2_ops_wait_prepare(struct vb2_queue *vq);
> -void vb2_ops_wait_finish(struct vb2_queue *vq);
>  #endif /* _MEDIA_VIDEOBUF2_CORE_H */
> diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
> index fc2dbe9..790cb7a 100644
> --- a/include/media/videobuf2-v4l2.h
> +++ b/include/media/videobuf2-v4l2.h
> @@ -40,4 +40,120 @@ struct vb2_v4l2_buffer {
>  #define to_vb2_v4l2_buffer(vb) \
>  	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
>  
> +
> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
> +
> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
> +
> +int __must_check vb2_queue_init(struct vb2_queue *q);
> +
> +void vb2_queue_release(struct vb2_queue *q);
> +
> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
> +
> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
> +		loff_t *ppos, int nonblock);
> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
> +		loff_t *ppos, int nonblock);
> +
> +/*
> + * vb2_thread_fnc - callback function for use with vb2_thread
> + *
> + * This is called whenever a buffer is dequeued in the thread.
> + */
> +typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
> +
> +/**
> + * vb2_thread_start() - start a thread for the given queue.
> + * @q:		videobuf queue
> + * @fnc:	callback function
> + * @priv:	priv pointer passed to the callback function
> + * @thread_name:the name of the thread. This will be prefixed with "vb2-".
> + *
> + * This starts a thread that will queue and dequeue until an error occurs
> + * or @vb2_thread_stop is called.
> + *
> + * This function should not be used for anything else but the videobuf2-dvb
> + * support. If you think you have another good use-case for this, then please
> + * contact the linux-media mailinglist first.
> + */
> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
> +		     const char *thread_name);
> +
> +/**
> + * vb2_thread_stop() - stop the thread for the given queue.
> + * @q:		videobuf queue
> + */
> +int vb2_thread_stop(struct vb2_queue *q);
> +
> +/**
> + * vb2_fileio_is_active() - return true if fileio is active.
> + * @q:		videobuf queue
> + *
> + * This returns true if read() or write() is used to stream the data
> + * as opposed to stream I/O. This is almost never an important distinction,
> + * except in rare cases. One such case is that using read() or write() to
> + * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
> + * is no way you can pass the field information of each buffer to/from
> + * userspace. A driver that supports this field format should check for
> + * this in the queue_setup op and reject it if this function returns true.
> + */
> +static inline bool vb2_fileio_is_active(struct vb2_queue *q)
> +{
> +	return q->fileio;
> +}
> +
> +/*
> + * The following functions are not part of the vb2 core API, but are simple
> + * helper functions that you can use in your struct v4l2_file_operations,
> + * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize
> + * if vb2_queue->lock or video_device->lock is set, and they will set
> + * and test vb2_queue->owner to check if the calling filehandle is permitted
> + * to do the queuing operation.
> + */
> +
> +/* struct v4l2_ioctl_ops helpers */
> +
> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
> +			  struct v4l2_requestbuffers *p);
> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
> +			  struct v4l2_create_buffers *p);
> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
> +			  struct v4l2_buffer *p);
> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
> +int vb2_ioctl_expbuf(struct file *file, void *priv,
> +	struct v4l2_exportbuffer *p);
> +
> +/* struct v4l2_file_operations helpers */
> +
> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
> +int vb2_fop_release(struct file *file);
> +int _vb2_fop_release(struct file *file, struct mutex *lock);
> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
> +		size_t count, loff_t *ppos);
> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
> +		size_t count, loff_t *ppos);
> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
> +#ifndef CONFIG_MMU
> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
> +		unsigned long len, unsigned long pgoff, unsigned long flags);
> +#endif
> +
> +/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
> +
> +void vb2_ops_wait_prepare(struct vb2_queue *vq);
> +void vb2_ops_wait_finish(struct vb2_queue *vq);
> +
>  #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
> diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
> index b015b38..f31b258 100644
> --- a/include/trace/events/v4l2.h
> +++ b/include/trace/events/v4l2.h
> @@ -5,6 +5,7 @@
>  #define _TRACE_V4L2_H
>  
>  #include <linux/tracepoint.h>
> +#include <media/videobuf2-v4l2.h>
>  
>  /* Enums require being exported to userspace, for user tool parsing */
>  #undef EM
> @@ -203,7 +204,8 @@ DECLARE_EVENT_CLASS(vb2_event_class,
>  
>  	TP_fast_assign(
>  		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> -		__entry->minor = q->owner ? q->owner->vdev->minor : -1;
> +		struct v4l2_fh *owner = (struct v4l2_fh *) q->owner;
> +		__entry->minor = owner ? owner->vdev->minor : -1;
>  		__entry->queued_count = q->queued_count;
>  		__entry->owned_by_drv_count =
>  			atomic_read(&q->owned_by_drv_count);
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer
  2015-08-28 13:31   ` Hans Verkuil
@ 2015-08-31  2:01     ` Junghak Sung
  2015-08-31  7:56       ` Junghak Sung
  0 siblings, 1 reply; 23+ messages in thread
From: Junghak Sung @ 2015-08-31  2:01 UTC (permalink / raw)
  To: Hans Verkuil, linux-media, mchehab, laurent.pinchart,
	sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

Hello Hans,

Thank you for your review.
I leave some comments in the body for reply.

Regards,
Junghak



On 08/28/2015 10:31 PM, Hans Verkuil wrote:
> Hi Junghak,
>
> Thanks for this patch, it looks much better. I do have a number of comments, though...
>
> On 08/26/2015 01:59 PM, Junghak Sung wrote:
>> Remove v4l2-specific stuff from struct vb2_buffer and add member variables
>> related with buffer management.
>>
>> struct vb2_plane {
>>          <snip>
>>          /* plane information */
>>          unsigned int            bytesused;
>>          unsigned int            length;
>>          union {
>>                  unsigned int    offset;
>>                  unsigned long   userptr;
>>                  int             fd;
>>          } m;
>>          unsigned int            data_offset;
>> }
>>
>> struct vb2_buffer {
>>          <snip>
>>          /* buffer information */
>>          unsigned int            num_planes;
>>          unsigned int            index;
>>          unsigned int            type;
>>          unsigned int            memory;
>>
>>          struct vb2_plane        planes[VIDEO_MAX_PLANES];
>>          <snip>
>> };
>>
>> And create struct vb2_v4l2_buffer as container buffer for v4l2 use.
>>
>> struct vb2_v4l2_buffer {
>>          struct vb2_buffer       vb2_buf;
>>
>>          __u32                   flags;
>>          __u32                   field;
>>          struct timeval          timestamp;
>>          struct v4l2_timecode    timecode;
>>          __u32                   sequence;
>> };
>>
>> This patch includes only changes inside of videobuf2. So, it is required to
>> modify all device drivers which use videobuf2.
>>
>> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
>> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
>> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>> Acked-by: Inki Dae <inki.dae@samsung.com>
>> ---
>>   drivers/media/v4l2-core/videobuf2-core.c |  324 +++++++++++++++++-------------
>>   include/media/videobuf2-core.h           |   50 ++---
>>   include/media/videobuf2-v4l2.h           |   26 +++
>>   3 files changed, 236 insertions(+), 164 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
>> index ab00ea0..9266d50 100644
>> --- a/drivers/media/v4l2-core/videobuf2-core.c
>> +++ b/drivers/media/v4l2-core/videobuf2-core.c
>> @@ -35,10 +35,10 @@
>>   static int debug;
>>   module_param(debug, int, 0644);
>>
>> -#define dprintk(level, fmt, arg...)					      \
>> -	do {								      \
>> -		if (debug >= level)					      \
>> -			pr_info("vb2: %s: " fmt, __func__, ## arg); \
>> +#define dprintk(level, fmt, arg...)					\
>> +	do {								\
>> +		if (debug >= level)					\
>> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
>
> These are just whitespace changes, and that is something it see *a lot* in this
> patch. And usually for no clear reason.
>
> Please remove those whitespace changes, it makes a difficult patch even harder
> to read than it already is.
>

I just wanted to remove unnecessary white spaces or adjust alignment.
OK, I will revert those whitespace changes for better review.

>>   	} while (0)
>>
>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>
> <snip>
>
>> @@ -656,12 +652,21 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>    */
>>   static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>>   {
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>   	struct vb2_queue *q = vb->vb2_queue;
>> +	unsigned int plane;
>>
>>   	/* Copy back data such as timestamp, flags, etc. */
>> -	memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
>> -	b->reserved2 = vb->v4l2_buf.reserved2;
>> -	b->reserved = vb->v4l2_buf.reserved;
>
> Hmm, I'm not sure why these reserved fields were copied here. I think it was
> for compatibility reasons for some old drivers that abused the reserved field.
> However, in the new code these reserved fields should probably be explicitly
> initialized to 0.
>
>> +	b->index = vb->index;
>> +	b->type = vb->type;
>> +	b->memory = vb->memory;
>> +	b->bytesused = 0;
>> +
>> +	b->flags = vbuf->flags;
>> +	b->field = vbuf->field;
>> +	b->timestamp = vbuf->timestamp;
>> +	b->timecode = vbuf->timecode;
>> +	b->sequence = vbuf->sequence;
>>
>>   	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>>   		/*
>> @@ -669,21 +674,33 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>>   		 * for it. The caller has already verified memory and size.
>>   		 */
>>   		b->length = vb->num_planes;
>> -		memcpy(b->m.planes, vb->v4l2_planes,
>> -			b->length * sizeof(struct v4l2_plane));
>
> A similar problem occurs here: the memcpy would have copied the reserved
> field in v4l2_plane as well, but that no longer happens, so you need to
> do an explicit memset for the reserved field in the new code.
>

It means that I'd better add reserved fields to struct vb2_buffer and 
struct vb2_plane in order to keep the information in struct v4l2_buffer
and struct v4l2_plane???


>> +		for (plane = 0; plane < vb->num_planes; ++plane) {
>> +			struct v4l2_plane *pdst = &b->m.planes[plane];
>> +			struct vb2_plane *psrc = &vb->planes[plane];
>> +
>> +			pdst->bytesused = psrc->bytesused;
>> +			pdst->length = psrc->length;
>> +			if (q->memory == V4L2_MEMORY_MMAP)
>> +				pdst->m.mem_offset = psrc->m.offset;
>> +			else if (q->memory == V4L2_MEMORY_USERPTR)
>> +				pdst->m.userptr = psrc->m.userptr;
>> +			else if (q->memory == V4L2_MEMORY_DMABUF)
>> +				pdst->m.fd = psrc->m.fd;
>> +			pdst->data_offset = psrc->data_offset;
>> +		}
>>   	} else {
>>   		/*
>>   		 * We use length and offset in v4l2_planes array even for
>>   		 * single-planar buffers, but userspace does not.
>>   		 */
>> -		b->length = vb->v4l2_planes[0].length;
>> -		b->bytesused = vb->v4l2_planes[0].bytesused;
>> +		b->length = vb->planes[0].length;
>> +		b->bytesused = vb->planes[0].bytesused;
>>   		if (q->memory == V4L2_MEMORY_MMAP)
>> -			b->m.offset = vb->v4l2_planes[0].m.mem_offset;
>> +			b->m.offset = vb->planes[0].m.offset;
>>   		else if (q->memory == V4L2_MEMORY_USERPTR)
>> -			b->m.userptr = vb->v4l2_planes[0].m.userptr;
>> +			b->m.userptr = vb->planes[0].m.userptr;
>>   		else if (q->memory == V4L2_MEMORY_DMABUF)
>> -			b->m.fd = vb->v4l2_planes[0].m.fd;
>> +			b->m.fd = vb->planes[0].m.fd;
>>   	}
>>
>>   	/*
>> @@ -692,7 +709,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>>   	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>>   	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>>   	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> -	    V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>>   		/*
>>   		 * For non-COPY timestamps, drop timestamp source bits
>>   		 * and obtain the timestamp source from the queue.
>> @@ -767,7 +784,7 @@ EXPORT_SYMBOL(vb2_querybuf);
>>   static int __verify_userptr_ops(struct vb2_queue *q)
>>   {
>>   	if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
>> -	    !q->mem_ops->put_userptr)
>> +			!q->mem_ops->put_userptr)
>>   		return -EINVAL;
>>
>>   	return 0;
>> @@ -780,7 +797,7 @@ static int __verify_userptr_ops(struct vb2_queue *q)
>>   static int __verify_mmap_ops(struct vb2_queue *q)
>>   {
>>   	if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
>> -	    !q->mem_ops->put || !q->mem_ops->mmap)
>> +			!q->mem_ops->put || !q->mem_ops->mmap)
>>   		return -EINVAL;
>>
>>   	return 0;
>> @@ -793,8 +810,8 @@ static int __verify_mmap_ops(struct vb2_queue *q)
>>   static int __verify_dmabuf_ops(struct vb2_queue *q)
>>   {
>>   	if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
>> -	    !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
>> -	    !q->mem_ops->unmap_dmabuf)
>> +		!q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
>> +		!q->mem_ops->unmap_dmabuf)
>>   		return -EINVAL;
>>
>>   	return 0;
>> @@ -808,7 +825,7 @@ static int __verify_memory_type(struct vb2_queue *q,
>>   		enum v4l2_memory memory, enum v4l2_buf_type type)
>>   {
>>   	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
>> -	    memory != V4L2_MEMORY_DMABUF) {
>> +			memory != V4L2_MEMORY_DMABUF) {
>>   		dprintk(1, "unsupported memory type\n");
>>   		return -EINVAL;
>>   	}
>> @@ -927,7 +944,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   	 * Driver also sets the size and allocator context for each plane.
>>   	 */
>>   	ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
>> -		       q->plane_sizes, q->alloc_ctx);
>> +			q->plane_sizes, q->alloc_ctx);
>>   	if (ret)
>>   		return ret;
>>
>> @@ -952,7 +969,7 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   		num_buffers = allocated_buffers;
>>
>>   		ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
>> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
>> +				&num_planes, q->plane_sizes, q->alloc_ctx);
>>
>>   		if (!ret && allocated_buffers < num_buffers)
>>   			ret = -ENOMEM;
>> @@ -1040,7 +1057,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   	 * buffer and their sizes are acceptable
>>   	 */
>>   	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>> -		       &num_planes, q->plane_sizes, q->alloc_ctx);
>> +			&num_planes, q->plane_sizes, q->alloc_ctx);
>>   	if (ret)
>>   		return ret;
>>
>> @@ -1063,7 +1080,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   		 * queue driver has set up
>>   		 */
>>   		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>> -			       &num_planes, q->plane_sizes, q->alloc_ctx);
>> +				&num_planes, q->plane_sizes, q->alloc_ctx);
>>
>>   		if (!ret && allocated_buffers < num_buffers)
>>   			ret = -ENOMEM;
>> @@ -1183,8 +1200,8 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
>>   		return;
>>
>>   	if (WARN_ON(state != VB2_BUF_STATE_DONE &&
>> -		    state != VB2_BUF_STATE_ERROR &&
>> -		    state != VB2_BUF_STATE_QUEUED))
>> +		state != VB2_BUF_STATE_ERROR &&
>> +		state != VB2_BUF_STATE_QUEUED))
>>   		state = VB2_BUF_STATE_ERROR;
>>
>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>
> All the chunks above are all spurious whitespace changes. As mentioned in the beginning,
> please remove all those pointless whitespace changes!
>
> There are a lot more of these, but I won't comment on them anymore.
>
> Basically this patch looks good to me, so once I have the next version without all the
> whitespace confusion and with the reserved field issues solved I'll do a final review.
>
> BTW, did you test this with 'v4l2-compliance -s' and with the vivid driver? Just to
> make sure you didn't break anything.
>

Actually, I've tested with v4l2-compliance for just one v4l2 drivers -
au0828.
I'll try to test with vivid driver at next round.


> Regards,
>
> 	Hans
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts
  2015-08-28 13:50   ` Hans Verkuil
@ 2015-08-31  2:08     ` Junghak Sung
  0 siblings, 0 replies; 23+ messages in thread
From: Junghak Sung @ 2015-08-31  2:08 UTC (permalink / raw)
  To: Hans Verkuil, linux-media, mchehab, laurent.pinchart,
	sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon



On 08/28/2015 10:50 PM, Hans Verkuil wrote:
> On 08/26/2015 01:59 PM, Junghak Sung wrote:
>> Divide videobuf2-core into core part and v4l2-specific part
>> - core part: videobuf2 core related with buffer management & memory
>>   allocation
>> - v4l2-specific part: v4l2-specific stuff
>>
>> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
>> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
>> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>> Acked-by: Inki Dae <inki.dae@samsung.com>
>
> As Mauro also noted, this patch is very hard to review. I think you can reduce
> the changes to some extent: the creation of the videobuf2-internal.h header
> can certainly be done first.
>
> After that you can make a patch that just moves functions from core.c to v4l2.c.
> E.g. a function like vb2_ioctl_prepare_buf() isn't changed, just moved. And there
> are lots of those.
>
> Patches that just move things around without doing any functional changes are
> easy to review and they reduce the size of the patch that actually does make
> functional changes and thus needs a much more careful review.
>
> There may well be more ways of splitting up this large patch, but I think the
> two suggestions I made above will already go a long way to making this more
> manageable.
>
> Regards,
>
> 	Hans
>
Good suggestions.
I'll do that way at next round.

Thanks and regards.
Junghak


>> ---
>>   drivers/media/v4l2-core/videobuf2-core.c     | 1933 +++-----------------------
>>   drivers/media/v4l2-core/videobuf2-internal.h |  184 +++
>>   drivers/media/v4l2-core/videobuf2-v4l2.c     | 1640 ++++++++++++++++++++++
>>   include/media/videobuf2-core.h               |  157 +--
>>   include/media/videobuf2-v4l2.h               |  116 ++
>>   include/trace/events/v4l2.h                  |    4 +-
>>   6 files changed, 2154 insertions(+), 1880 deletions(-)
>>   create mode 100644 drivers/media/v4l2-core/videobuf2-internal.h
>>
>> diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
>> index 9266d50..2cd4241 100644
>> --- a/drivers/media/v4l2-core/videobuf2-core.c
>> +++ b/drivers/media/v4l2-core/videobuf2-core.c
>> @@ -6,9 +6,6 @@
>>    * Author: Pawel Osciak <pawel@osciak.com>
>>    *	   Marek Szyprowski <m.szyprowski@samsung.com>
>>    *
>> - * The vb2_thread implementation was based on code from videobuf-dvb.c:
>> - *	(c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
>> - *
>>    * This program is free software; you can redistribute it and/or modify
>>    * it under the terms of the GNU General Public License as published by
>>    * the Free Software Foundation.
>> @@ -24,164 +21,14 @@
>>   #include <linux/freezer.h>
>>   #include <linux/kthread.h>
>>
>> -#include <media/v4l2-dev.h>
>> -#include <media/v4l2-fh.h>
>> -#include <media/v4l2-event.h>
>> -#include <media/v4l2-common.h>
>> -#include <media/videobuf2-v4l2.h>
>> +#include <media/videobuf2-core.h>
>> +#include "videobuf2-internal.h"
>>
>>   #include <trace/events/v4l2.h>
>>
>> -static int debug;
>> -module_param(debug, int, 0644);
>> -
>> -#define dprintk(level, fmt, arg...)					\
>> -	do {								\
>> -		if (debug >= level)					\
>> -			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
>> -	} while (0)
>> -
>> -#ifdef CONFIG_VIDEO_ADV_DEBUG
>> -
>> -/*
>> - * If advanced debugging is on, then count how often each op is called
>> - * successfully, which can either be per-buffer or per-queue.
>> - *
>> - * This makes it easy to check that the 'init' and 'cleanup'
>> - * (and variations thereof) stay balanced.
>> - */
>> -
>> -#define log_memop(vb, op)						\
>> -	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
>> -		(vb)->vb2_queue, (vb)->index, #op,			\
>> -		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
>> -
>> -#define call_memop(vb, op, args...)					\
>> -({									\
>> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> -	int err;							\
>> -									\
>> -	log_memop(vb, op);						\
>> -	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
>> -	if (!err)							\
>> -		(vb)->cnt_mem_ ## op++;					\
>> -	err;								\
>> -})
>> -
>> -#define call_ptr_memop(vb, op, args...)					\
>> -({									\
>> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> -	void *ptr;							\
>> -									\
>> -	log_memop(vb, op);						\
>> -	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
>> -	if (!IS_ERR_OR_NULL(ptr))					\
>> -		(vb)->cnt_mem_ ## op++;					\
>> -	ptr;								\
>> -})
>> -
>> -#define call_void_memop(vb, op, args...)				\
>> -({									\
>> -	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> -									\
>> -	log_memop(vb, op);						\
>> -	if (_q->mem_ops->op)						\
>> -		_q->mem_ops->op(args);					\
>> -	(vb)->cnt_mem_ ## op++;						\
>> -})
>> -
>> -#define log_qop(q, op)							\
>> -	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
>> -		(q)->ops->op ? "" : " (nop)")
>> -
>> -#define call_qop(q, op, args...)					\
>> -({									\
>> -	int err;							\
>> -									\
>> -	log_qop(q, op);							\
>> -	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
>> -	if (!err)							\
>> -		(q)->cnt_ ## op++;					\
>> -	err;								\
>> -})
>> -
>> -#define call_void_qop(q, op, args...)					\
>> -({									\
>> -	log_qop(q, op);							\
>> -	if ((q)->ops->op)						\
>> -		(q)->ops->op(args);					\
>> -	(q)->cnt_ ## op++;						\
>> -})
>> -
>> -#define log_vb_qop(vb, op, args...)					\
>> -	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
>> -		(vb)->vb2_queue, (vb)->index, #op,			\
>> -		(vb)->vb2_queue->ops->op ? "" : " (nop)")
>> -
>> -#define call_vb_qop(vb, op, args...)					\
>> -({									\
>> -	int err;							\
>> -									\
>> -	log_vb_qop(vb, op);						\
>> -	err = (vb)->vb2_queue->ops->op ?				\
>> -		(vb)->vb2_queue->ops->op(args) : 0;			\
>> -	if (!err)							\
>> -		(vb)->cnt_ ## op++;					\
>> -	err;								\
>> -})
>> -
>> -#define call_void_vb_qop(vb, op, args...)				\
>> -({									\
>> -	log_vb_qop(vb, op);						\
>> -	if ((vb)->vb2_queue->ops->op)					\
>> -		(vb)->vb2_queue->ops->op(args);				\
>> -	(vb)->cnt_ ## op++;						\
>> -})
>> -
>> -#else
>> -
>> -#define call_memop(vb, op, args...)					\
>> -	((vb)->vb2_queue->mem_ops->op ?					\
>> -		(vb)->vb2_queue->mem_ops->op(args) : 0)
>> -
>> -#define call_ptr_memop(vb, op, args...)					\
>> -	((vb)->vb2_queue->mem_ops->op ?					\
>> -		(vb)->vb2_queue->mem_ops->op(args) : NULL)
>> -
>> -#define call_void_memop(vb, op, args...)				\
>> -	do {								\
>> -		if ((vb)->vb2_queue->mem_ops->op)			\
>> -			(vb)->vb2_queue->mem_ops->op(args);		\
>> -	} while (0)
>> -
>> -#define call_qop(q, op, args...)					\
>> -	((q)->ops->op ? (q)->ops->op(args) : 0)
>> -
>> -#define call_void_qop(q, op, args...)					\
>> -	do {								\
>> -		if ((q)->ops->op)					\
>> -			(q)->ops->op(args);				\
>> -	} while (0)
>> -
>> -#define call_vb_qop(vb, op, args...)					\
>> -	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
>> -
>> -#define call_void_vb_qop(vb, op, args...)				\
>> -	do {								\
>> -		if ((vb)->vb2_queue->ops->op)				\
>> -			(vb)->vb2_queue->ops->op(args);			\
>> -	} while (0)
>> -
>> -#endif
>> -
>> -/* Flags that are set by the vb2 core */
>> -#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
>> -				 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
>> -				 V4L2_BUF_FLAG_PREPARED | \
>> -				 V4L2_BUF_FLAG_TIMESTAMP_MASK)
>> -/* Output buffer flags that should be passed on to the driver */
>> -#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
>> -				 V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_TIMECODE)
>> +int vb2_debug;
>> +module_param_named(debug, vb2_debug, int, 0644);
>> +EXPORT_SYMBOL_GPL(vb2_debug);
>>
>>   static void __vb2_queue_cancel(struct vb2_queue *q);
>>   static void __enqueue_in_driver(struct vb2_buffer *vb);
>> @@ -193,7 +40,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
>>   {
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	enum dma_data_direction dma_dir =
>> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>> +			q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>>   	void *mem_priv;
>>   	int plane;
>>
>> @@ -249,7 +96,8 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
>>
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		if (vb->planes[plane].mem_priv)
>> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
>> +			call_void_memop(vb, put_userptr,
>> +					vb->planes[plane].mem_priv);
>>   		vb->planes[plane].mem_priv = NULL;
>>   	}
>>   }
>> @@ -347,7 +195,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
>>    *
>>    * Returns the number of buffers successfully allocated.
>>    */
>> -static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>> +static int __vb2_queue_alloc(struct vb2_queue *q, unsigned int memory,
>>   			unsigned int num_buffers, unsigned int num_planes)
>>   {
>>   	unsigned int buffer;
>> @@ -370,7 +218,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>>   		vb->memory = memory;
>>
>>   		/* Allocate video buffer memory for the MMAP type */
>> -		if (memory == V4L2_MEMORY_MMAP) {
>> +		if (memory == VB2_MEMORY_MMAP) {
>>   			ret = __vb2_buf_mem_alloc(vb);
>>   			if (ret) {
>>   				dprintk(1, "failed allocating memory for "
>> @@ -397,7 +245,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
>>   	}
>>
>>   	__setup_lengths(q, buffer);
>> -	if (memory == V4L2_MEMORY_MMAP)
>> +	if (memory == VB2_MEMORY_MMAP)
>>   		__setup_offsets(q, buffer);
>>
>>   	dprintk(1, "allocated %d buffers, %d plane(s) each\n",
>> @@ -421,9 +269,9 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
>>   			continue;
>>
>>   		/* Free MMAP buffers or release USERPTR buffers */
>> -		if (q->memory == V4L2_MEMORY_MMAP)
>> +		if (q->memory == VB2_MEMORY_MMAP)
>>   			__vb2_buf_mem_free(vb);
>> -		else if (q->memory == V4L2_MEMORY_DMABUF)
>> +		else if (q->memory == VB2_MEMORY_DMABUF)
>>   			__vb2_buf_dmabuf_put(vb);
>>   		else
>>   			__vb2_buf_userptr_put(vb);
>> @@ -547,75 +395,10 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
>>   }
>>
>>   /**
>> - * __verify_planes_array() - verify that the planes array passed in struct
>> - * v4l2_buffer from userspace can be safely used
>> - */
>> -static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> -{
>> -	if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
>> -		return 0;
>> -
>> -	/* Is memory for copying plane information present? */
>> -	if (NULL == b->m.planes) {
>> -		dprintk(1, "multi-planar buffer passed but "
>> -			   "planes array not provided\n");
>> -		return -EINVAL;
>> -	}
>> -
>> -	if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
>> -		dprintk(1, "incorrect planes array length, "
>> -			   "expected %d, got %d\n", vb->num_planes, b->length);
>> -		return -EINVAL;
>> -	}
>> -
>> -	return 0;
>> -}
>> -
>> -/**
>> - * __verify_length() - Verify that the bytesused value for each plane fits in
>> - * the plane length and that the data offset doesn't exceed the bytesused value.
>> - */
>> -static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> -{
>> -	unsigned int length;
>> -	unsigned int bytesused;
>> -	unsigned int plane;
>> -
>> -	if (!V4L2_TYPE_IS_OUTPUT(b->type))
>> -		return 0;
>> -
>> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>> -		for (plane = 0; plane < vb->num_planes; ++plane) {
>> -			length = (b->memory == V4L2_MEMORY_USERPTR ||
>> -				b->memory == V4L2_MEMORY_DMABUF)
>> -				? b->m.planes[plane].length
>> -				: vb->planes[plane].length;
>> -			bytesused = b->m.planes[plane].bytesused
>> -				? b->m.planes[plane].bytesused : length;
>> -
>> -			if (b->m.planes[plane].bytesused > length)
>> -				return -EINVAL;
>> -
>> -			if (b->m.planes[plane].data_offset > 0 &&
>> -				b->m.planes[plane].data_offset >= bytesused)
>> -				return -EINVAL;
>> -		}
>> -	} else {
>> -		length = (b->memory == V4L2_MEMORY_USERPTR)
>> -			? b->length : vb->planes[0].length;
>> -
>> -		if (b->bytesused > length)
>> -			return -EINVAL;
>> -	}
>> -
>> -	return 0;
>> -}
>> -
>> -/**
>> - * __buffer_in_use() - return true if the buffer is in use and
>> + * vb2_buffer_in_use() - return true if the buffer is in use and
>>    * the queue cannot be freed (by the means of REQBUFS(0)) call
>>    */
>> -static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>>   {
>>   	unsigned int plane;
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>> @@ -631,6 +414,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
>>   	}
>>   	return false;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_buffer_in_use);
>>
>>   /**
>>    * __buffers_in_use() - return true if any buffers on the queue are in use and
>> @@ -640,142 +424,26 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>   {
>>   	unsigned int buffer;
>>   	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
>> -		if (__buffer_in_use(q, q->bufs[buffer]))
>> +		if (vb2_buffer_in_use(q, q->bufs[buffer]))
>>   			return true;
>>   	}
>>   	return false;
>>   }
>>
>>   /**
>> - * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
>> - * returned to userspace
>> - */
>> -static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
>> -{
>> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> -	struct vb2_queue *q = vb->vb2_queue;
>> -	unsigned int plane;
>> -
>> -	/* Copy back data such as timestamp, flags, etc. */
>> -	b->index = vb->index;
>> -	b->type = vb->type;
>> -	b->memory = vb->memory;
>> -	b->bytesused = 0;
>> -
>> -	b->flags = vbuf->flags;
>> -	b->field = vbuf->field;
>> -	b->timestamp = vbuf->timestamp;
>> -	b->timecode = vbuf->timecode;
>> -	b->sequence = vbuf->sequence;
>> -
>> -	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>> -		/*
>> -		 * Fill in plane-related data if userspace provided an array
>> -		 * for it. The caller has already verified memory and size.
>> -		 */
>> -		b->length = vb->num_planes;
>> -		for (plane = 0; plane < vb->num_planes; ++plane) {
>> -			struct v4l2_plane *pdst = &b->m.planes[plane];
>> -			struct vb2_plane *psrc = &vb->planes[plane];
>> -
>> -			pdst->bytesused = psrc->bytesused;
>> -			pdst->length = psrc->length;
>> -			if (q->memory == V4L2_MEMORY_MMAP)
>> -				pdst->m.mem_offset = psrc->m.offset;
>> -			else if (q->memory == V4L2_MEMORY_USERPTR)
>> -				pdst->m.userptr = psrc->m.userptr;
>> -			else if (q->memory == V4L2_MEMORY_DMABUF)
>> -				pdst->m.fd = psrc->m.fd;
>> -			pdst->data_offset = psrc->data_offset;
>> -		}
>> -	} else {
>> -		/*
>> -		 * We use length and offset in v4l2_planes array even for
>> -		 * single-planar buffers, but userspace does not.
>> -		 */
>> -		b->length = vb->planes[0].length;
>> -		b->bytesused = vb->planes[0].bytesused;
>> -		if (q->memory == V4L2_MEMORY_MMAP)
>> -			b->m.offset = vb->planes[0].m.offset;
>> -		else if (q->memory == V4L2_MEMORY_USERPTR)
>> -			b->m.userptr = vb->planes[0].m.userptr;
>> -		else if (q->memory == V4L2_MEMORY_DMABUF)
>> -			b->m.fd = vb->planes[0].m.fd;
>> -	}
>> -
>> -	/*
>> -	 * Clear any buffer state related flags.
>> -	 */
>> -	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>> -	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>> -	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> -			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>> -		/*
>> -		 * For non-COPY timestamps, drop timestamp source bits
>> -		 * and obtain the timestamp source from the queue.
>> -		 */
>> -		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> -		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> -	}
>> -
>> -	switch (vb->state) {
>> -	case VB2_BUF_STATE_QUEUED:
>> -	case VB2_BUF_STATE_ACTIVE:
>> -		b->flags |= V4L2_BUF_FLAG_QUEUED;
>> -		break;
>> -	case VB2_BUF_STATE_ERROR:
>> -		b->flags |= V4L2_BUF_FLAG_ERROR;
>> -		/* fall through */
>> -	case VB2_BUF_STATE_DONE:
>> -		b->flags |= V4L2_BUF_FLAG_DONE;
>> -		break;
>> -	case VB2_BUF_STATE_PREPARED:
>> -		b->flags |= V4L2_BUF_FLAG_PREPARED;
>> -		break;
>> -	case VB2_BUF_STATE_PREPARING:
>> -	case VB2_BUF_STATE_DEQUEUED:
>> -		/* nothing */
>> -		break;
>> -	}
>> -
>> -	if (__buffer_in_use(q, vb))
>> -		b->flags |= V4L2_BUF_FLAG_MAPPED;
>> -}
>> -
>> -/**
>> - * vb2_querybuf() - query video buffer information
>> + * vb2_core_querybuf() - query video buffer information
>>    * @q:		videobuf queue
>> + * @index:	id number of the buffer
>>    * @b:		buffer struct passed from userspace to vidioc_querybuf handler
>>    *		in driver
>> - *
>> - * Should be called from vidioc_querybuf ioctl handler in driver.
>> - * This function will verify the passed v4l2_buffer structure and fill the
>> - * relevant information for the userspace.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_querybuf handler in driver.
>>    */
>> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb)
>>   {
>> -	struct vb2_buffer *vb;
>> -	int ret;
>> -
>> -	if (b->type != q->type) {
>> -		dprintk(1, "wrong buffer type\n");
>> -		return -EINVAL;
>> -	}
>> +	call_bufop(q, fill_user_buffer, q->bufs[index], pb);
>>
>> -	if (b->index >= q->num_buffers) {
>> -		dprintk(1, "buffer index out of range\n");
>> -		return -EINVAL;
>> -	}
>> -	vb = q->bufs[b->index];
>> -	ret = __verify_planes_array(vb, b);
>> -	if (!ret)
>> -		__fill_v4l2_buffer(vb, b);
>> -	return ret;
>> +	return 0;
>>   }
>> -EXPORT_SYMBOL(vb2_querybuf);
>> +EXPORT_SYMBOL_GPL(vb2_core_querybuf);
>>
>>   /**
>>    * __verify_userptr_ops() - verify that all memory operations required for
>> @@ -818,14 +486,14 @@ static int __verify_dmabuf_ops(struct vb2_queue *q)
>>   }
>>
>>   /**
>> - * __verify_memory_type() - Check whether the memory type and buffer type
>> + * vb2_verify_memory_type() - Check whether the memory type and buffer type
>>    * passed to a buffer operation are compatible with the queue.
>>    */
>> -static int __verify_memory_type(struct vb2_queue *q,
>> -		enum v4l2_memory memory, enum v4l2_buf_type type)
>> +int vb2_verify_memory_type(struct vb2_queue *q,
>> +		unsigned int memory, unsigned int type)
>>   {
>> -	if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
>> -			memory != V4L2_MEMORY_DMABUF) {
>> +	if (memory != VB2_MEMORY_MMAP && memory != VB2_MEMORY_USERPTR &&
>> +		memory != VB2_MEMORY_DMABUF) {
>>   		dprintk(1, "unsupported memory type\n");
>>   		return -EINVAL;
>>   	}
>> @@ -839,37 +507,30 @@ static int __verify_memory_type(struct vb2_queue *q,
>>   	 * Make sure all the required memory ops for given memory type
>>   	 * are available.
>>   	 */
>> -	if (memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
>> +	if (memory == VB2_MEMORY_MMAP && __verify_mmap_ops(q)) {
>>   		dprintk(1, "MMAP for current setup unsupported\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
>> +	if (memory == VB2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
>>   		dprintk(1, "USERPTR for current setup unsupported\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (memory == V4L2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
>> +	if (memory == VB2_MEMORY_DMABUF && __verify_dmabuf_ops(q)) {
>>   		dprintk(1, "DMABUF for current setup unsupported\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	/*
>> -	 * Place the busy tests at the end: -EBUSY can be ignored when
>> -	 * create_bufs is called with count == 0, but count == 0 should still
>> -	 * do the memory and type validation.
>> -	 */
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>>   	return 0;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_verify_memory_type);
>>
>>   /**
>> - * __reqbufs() - Initiate streaming
>> + * vb2_core_reqbufs() - Initiate streaming
>>    * @q:		videobuf2 queue
>> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
>> + * @memory:
>> + * @count:
>>    *
>>    * Should be called from vidioc_reqbufs ioctl handler of a driver.
>>    * This function:
>> @@ -889,7 +550,8 @@ static int __verify_memory_type(struct vb2_queue *q,
>>    * The return values from this function are intended to be directly returned
>>    * from vidioc_reqbufs handler in driver.
>>    */
>> -static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
>> +		unsigned int *count)
>>   {
>>   	unsigned int num_buffers, allocated_buffers, num_planes = 0;
>>   	int ret;
>> @@ -899,13 +561,13 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   		return -EBUSY;
>>   	}
>>
>> -	if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
>> +	if (*count == 0 || q->num_buffers != 0 || q->memory != memory) {
>>   		/*
>>   		 * We already have buffers allocated, so first check if they
>>   		 * are not in use and can be freed.
>>   		 */
>>   		mutex_lock(&q->mmap_lock);
>> -		if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) {
>> +		if (q->memory == VB2_MEMORY_MMAP && __buffers_in_use(q)) {
>>   			mutex_unlock(&q->mmap_lock);
>>   			dprintk(1, "memory in use, cannot free\n");
>>   			return -EBUSY;
>> @@ -926,18 +588,18 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   		 * In case of REQBUFS(0) return immediately without calling
>>   		 * driver's queue_setup() callback and allocating resources.
>>   		 */
>> -		if (req->count == 0)
>> +		if (*count == 0)
>>   			return 0;
>>   	}
>>
>>   	/*
>>   	 * Make sure the requested values and current defaults are sane.
>>   	 */
>> -	num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
>> +	num_buffers = min_t(unsigned int, *count, VB2_MAX_FRAME);
>>   	num_buffers = max_t(unsigned int, num_buffers, q->min_buffers_needed);
>>   	memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
>>   	memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
>> -	q->memory = req->memory;
>> +	q->memory = memory;
>>
>>   	/*
>>   	 * Ask the driver how many buffers and planes per buffer it requires.
>> @@ -949,7 +611,8 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   		return ret;
>>
>>   	/* Finally, allocate buffers and video memory */
>> -	allocated_buffers = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes);
>> +	allocated_buffers =
>> +		__vb2_queue_alloc(q, memory, num_buffers, num_planes);
>>   	if (allocated_buffers == 0) {
>>   		dprintk(1, "memory allocation failed\n");
>>   		return -ENOMEM;
>> @@ -998,28 +661,15 @@ static int __reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>>   	 * Return the number of successfully allocated buffers
>>   	 * to the userspace.
>>   	 */
>> -	req->count = allocated_buffers;
>> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
>> +	*count = allocated_buffers;
>> +	q->waiting_for_buffers = !q->is_output;
>>
>>   	return 0;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_core_reqbufs);
>>
>>   /**
>> - * vb2_reqbufs() - Wrapper for __reqbufs() that also verifies the memory and
>> - * type values.
>> - * @q:		videobuf2 queue
>> - * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
>> - */
>> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>> -{
>> -	int ret = __verify_memory_type(q, req->memory, req->type);
>> -
>> -	return ret ? ret : __reqbufs(q, req);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_reqbufs);
>> -
>> -/**
>> - * __create_bufs() - Allocate buffers and any required auxiliary structs
>> + * vb2_core_create_bufs() - Allocate buffers and any required auxiliary structs
>>    * @q:		videobuf2 queue
>>    * @create:	creation parameters, passed from userspace to vidioc_create_bufs
>>    *		handler in driver
>> @@ -1033,12 +683,13 @@ EXPORT_SYMBOL_GPL(vb2_reqbufs);
>>    * The return values from this function are intended to be directly returned
>>    * from vidioc_create_bufs handler in driver.
>>    */
>> -static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
>> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
>> +		unsigned int *count, void *parg)
>>   {
>>   	unsigned int num_planes = 0, num_buffers, allocated_buffers;
>>   	int ret;
>>
>> -	if (q->num_buffers == VIDEO_MAX_FRAME) {
>> +	if (q->num_buffers == VB2_MAX_FRAME) {
>>   		dprintk(1, "maximum number of buffers already allocated\n");
>>   		return -ENOBUFS;
>>   	}
>> @@ -1046,23 +697,23 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   	if (!q->num_buffers) {
>>   		memset(q->plane_sizes, 0, sizeof(q->plane_sizes));
>>   		memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
>> -		q->memory = create->memory;
>> -		q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
>> +		q->memory = memory;
>> +		q->waiting_for_buffers = !q->is_output;
>>   	}
>>
>> -	num_buffers = min(create->count, VIDEO_MAX_FRAME - q->num_buffers);
>> +	num_buffers = min(*count, VB2_MAX_FRAME - q->num_buffers);
>>
>>   	/*
>>   	 * Ask the driver, whether the requested number of buffers, planes per
>>   	 * buffer and their sizes are acceptable
>>   	 */
>> -	ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>> +	ret = call_qop(q, queue_setup, q, parg, &num_buffers,
>>   			&num_planes, q->plane_sizes, q->alloc_ctx);
>>   	if (ret)
>>   		return ret;
>>
>>   	/* Finally, allocate buffers and video memory */
>> -	allocated_buffers = __vb2_queue_alloc(q, create->memory, num_buffers,
>> +	allocated_buffers = __vb2_queue_alloc(q, memory, num_buffers,
>>   				num_planes);
>>   	if (allocated_buffers == 0) {
>>   		dprintk(1, "memory allocation failed\n");
>> @@ -1079,7 +730,7 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   		 * q->num_buffers contains the total number of buffers, that the
>>   		 * queue driver has set up
>>   		 */
>> -		ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>> +		ret = call_qop(q, queue_setup, q, parg, &num_buffers,
>>   				&num_planes, q->plane_sizes, q->alloc_ctx);
>>
>>   		if (!ret && allocated_buffers < num_buffers)
>> @@ -1109,28 +760,11 @@ static int __create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create
>>   	 * Return the number of successfully allocated buffers
>>   	 * to the userspace.
>>   	 */
>> -	create->count = allocated_buffers;
>> +	*count = allocated_buffers;
>>
>>   	return 0;
>>   }
>> -
>> -/**
>> - * vb2_create_bufs() - Wrapper for __create_bufs() that also verifies the
>> - * memory and type values.
>> - * @q:		videobuf2 queue
>> - * @create:	creation parameters, passed from userspace to vidioc_create_bufs
>> - *		handler in driver
>> - */
>> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
>> -{
>> -	int ret = __verify_memory_type(q, create->memory, create->format.type);
>> -
>> -	create->index = q->num_buffers;
>> -	if (create->count == 0)
>> -		return ret != -EBUSY ? ret : 0;
>> -	return ret ? ret : __create_bufs(q, create);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_create_bufs);
>> +EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
>>
>>   /**
>>    * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
>> @@ -1263,7 +897,7 @@ void vb2_discard_done(struct vb2_queue *q)
>>   }
>>   EXPORT_SYMBOL_GPL(vb2_discard_done);
>>
>> -static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>>   {
>>   	static bool __check_once __read_mostly;
>>
>> @@ -1279,162 +913,34 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
>>   	else
>>   		pr_warn_once("use the actual size instead.\n");
>>   }
>> -
>> -/**
>> - * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
>> - * v4l2_buffer by the userspace. The caller has already verified that struct
>> - * v4l2_buffer has a valid number of planes.
>> - */
>> -static void __fill_vb2_buffer(struct vb2_buffer *vb,
>> -		const struct v4l2_buffer *b, struct vb2_plane *planes)
>> -{
>> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> -	unsigned int plane;
>> -
>> -	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>> -		if (b->memory == V4L2_MEMORY_USERPTR) {
>> -			for (plane = 0; plane < vb->num_planes; ++plane) {
>> -				planes[plane].m.userptr =
>> -					b->m.planes[plane].m.userptr;
>> -				planes[plane].length =
>> -					b->m.planes[plane].length;
>> -			}
>> -		}
>> -		if (b->memory == V4L2_MEMORY_DMABUF) {
>> -			for (plane = 0; plane < vb->num_planes; ++plane) {
>> -				planes[plane].m.fd =
>> -					b->m.planes[plane].m.fd;
>> -				planes[plane].length =
>> -					b->m.planes[plane].length;
>> -			}
>> -		}
>> -
>> -		/* Fill in driver-provided information for OUTPUT types */
>> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> -			/*
>> -			 * Will have to go up to b->length when API starts
>> -			 * accepting variable number of planes.
>> -			 *
>> -			 * If bytesused == 0 for the output buffer, then fall
>> -			 * back to the full buffer size. In that case
>> -			 * userspace clearly never bothered to set it and
>> -			 * it's a safe assumption that they really meant to
>> -			 * use the full plane sizes.
>> -			 *
>> -			 * Some drivers, e.g. old codec drivers, use bytesused == 0
>> -			 * as a way to indicate that streaming is finished.
>> -			 * In that case, the driver should use the
>> -			 * allow_zero_bytesused flag to keep old userspace
>> -			 * applications working.
>> -			 */
>> -			for (plane = 0; plane < vb->num_planes; ++plane) {
>> -				struct vb2_plane *pdst = &planes[plane];
>> -				struct v4l2_plane *psrc = &b->m.planes[plane];
>> -
>> -				if (psrc->bytesused == 0)
>> -					vb2_warn_zero_bytesused(vb);
>> -
>> -				if (vb->vb2_queue->allow_zero_bytesused)
>> -					pdst->bytesused = psrc->bytesused;
>> -				else
>> -					pdst->bytesused = psrc->bytesused ?
>> -						psrc->bytesused : pdst->length;
>> -				pdst->data_offset = psrc->data_offset;
>> -			}
>> -		}
>> -	} else {
>> -		/*
>> -		 * Single-planar buffers do not use planes array,
>> -		 * so fill in relevant v4l2_buffer struct fields instead.
>> -		 * In videobuf we use our internal V4l2_planes struct for
>> -		 * single-planar buffers as well, for simplicity.
>> -		 *
>> -		 * If bytesused == 0 for the output buffer, then fall back
>> -		 * to the full buffer size as that's a sensible default.
>> -		 *
>> -		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
>> -		 * a way to indicate that streaming is finished. In that case,
>> -		 * the driver should use the allow_zero_bytesused flag to keep
>> -		 * old userspace applications working.
>> -		 */
>> -		if (b->memory == V4L2_MEMORY_USERPTR) {
>> -			planes[0].m.userptr = b->m.userptr;
>> -			planes[0].length = b->length;
>> -		}
>> -
>> -		if (b->memory == V4L2_MEMORY_DMABUF) {
>> -			planes[0].m.fd = b->m.fd;
>> -			planes[0].length = b->length;
>> -		}
>> -
>> -		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> -			if (b->bytesused == 0)
>> -				vb2_warn_zero_bytesused(vb);
>> -
>> -			if (vb->vb2_queue->allow_zero_bytesused)
>> -				planes[0].bytesused = b->bytesused;
>> -			else
>> -				planes[0].bytesused = b->bytesused ?
>> -					b->bytesused : planes[0].length;
>> -		} else
>> -			planes[0].bytesused = 0;
>> -
>> -	}
>> -
>> -	/* Zero flags that the vb2 core handles */
>> -	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
>> -	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> -			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
>> -			!V4L2_TYPE_IS_OUTPUT(b->type)) {
>> -		/*
>> -		 * Non-COPY timestamps and non-OUTPUT queues will get
>> -		 * their timestamp and timestamp source flags from the
>> -		 * queue.
>> -		 */
>> -		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> -	}
>> -
>> -	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> -		/*
>> -		 * For output buffers mask out the timecode flag:
>> -		 * this will be handled later in vb2_internal_qbuf().
>> -		 * The 'field' is valid metadata for this output buffer
>> -		 * and so that needs to be copied here.
>> -		 */
>> -		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
>> -		vbuf->field = b->field;
>> -	} else {
>> -		/* Zero any output buffer flags as this is a capture buffer */
>> -		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
>> -	}
>> -}
>> +EXPORT_SYMBOL_GPL(vb2_warn_zero_bytesused);
>>
>>   /**
>>    * __qbuf_mmap() - handle qbuf of an MMAP buffer
>>    */
>> -static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +static int __qbuf_mmap(struct vb2_buffer *vb, void *pb)
>>   {
>> -	__fill_vb2_buffer(vb, b, vb->planes);
>> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, vb->planes);
>>   	return call_vb_qop(vb, buf_prepare, vb);
>>   }
>>
>>   /**
>>    * __qbuf_userptr() - handle qbuf of a USERPTR buffer
>>    */
>> -static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +static int __qbuf_userptr(struct vb2_buffer *vb, void *pb)
>>   {
>> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
>> +	struct vb2_plane planes[VB2_MAX_PLANES];
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	void *mem_priv;
>>   	unsigned int plane;
>>   	int ret;
>>   	enum dma_data_direction dma_dir =
>> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>>   	bool reacquired = vb->planes[0].mem_priv == NULL;
>>
>>   	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
>>   	/* Copy relevant information provided by the userspace */
>> -	__fill_vb2_buffer(vb, b, planes);
>> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
>>
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		/* Skip the plane if already verified */
>> @@ -1462,7 +968,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   				reacquired = true;
>>   				call_void_vb_qop(vb, buf_cleanup, vb);
>>   			}
>> -			call_void_memop(vb, put_userptr, vb->planes[plane].mem_priv);
>> +			call_void_memop(vb, put_userptr,
>> +					vb->planes[plane].mem_priv);
>>   		}
>>
>>   		vb->planes[plane].mem_priv = NULL;
>> @@ -1533,20 +1040,20 @@ err:
>>   /**
>>    * __qbuf_dmabuf() - handle qbuf of a DMABUF buffer
>>    */
>> -static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +static int __qbuf_dmabuf(struct vb2_buffer *vb, void *pb)
>>   {
>> -	struct vb2_plane planes[VIDEO_MAX_PLANES];
>> +	struct vb2_plane planes[VB2_MAX_PLANES];
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	void *mem_priv;
>>   	unsigned int plane;
>>   	int ret;
>>   	enum dma_data_direction dma_dir =
>> -		V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>> +		q->is_output ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
>>   	bool reacquired = vb->planes[0].mem_priv == NULL;
>>
>>   	memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
>>   	/* Copy relevant information provided by the userspace */
>> -	__fill_vb2_buffer(vb, b, planes);
>> +	call_bufop(vb->vb2_queue, fill_vb2_buffer, vb, pb, planes);
>>
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
>> @@ -1591,9 +1098,8 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   		vb->planes[plane].data_offset = 0;
>>
>>   		/* Acquire each plane's memory */
>> -		mem_priv = call_ptr_memop(vb, attach_dmabuf,
>> -			q->alloc_ctx[plane], dbuf, planes[plane].length,
>> -			dma_dir);
>> +		mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
>> +			dbuf, planes[plane].length, dma_dir);
>>   		if (IS_ERR(mem_priv)) {
>>   			dprintk(1, "failed to attach dmabuf\n");
>>   			ret = PTR_ERR(mem_priv);
>> @@ -1626,7 +1132,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   	for (plane = 0; plane < vb->num_planes; ++plane) {
>>   		vb->planes[plane].bytesused = planes[plane].bytesused;
>>   		vb->planes[plane].length = planes[plane].length;
>> -		vb->planes[plane].m.fd = planes[plane].m.userptr;
>> +		vb->planes[plane].m.fd = planes[plane].m.fd;
>>   		vb->planes[plane].data_offset = planes[plane].data_offset;
>>   	}
>>
>> @@ -1677,52 +1183,27 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
>>   	call_void_vb_qop(vb, buf_queue, vb);
>>   }
>>
>> -static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +static int __buf_prepare(struct vb2_buffer *vb, void *pb)
>>   {
>> -	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>   	struct vb2_queue *q = vb->vb2_queue;
>>   	int ret;
>>
>> -	ret = __verify_length(vb, b);
>> -	if (ret < 0) {
>> -		dprintk(1, "plane parameters verification failed: %d\n", ret);
>> -		return ret;
>> -	}
>> -	if (b->field == V4L2_FIELD_ALTERNATE && V4L2_TYPE_IS_OUTPUT(q->type)) {
>> -		/*
>> -		 * If the format's field is ALTERNATE, then the buffer's field
>> -		 * should be either TOP or BOTTOM, not ALTERNATE since that
>> -		 * makes no sense. The driver has to know whether the
>> -		 * buffer represents a top or a bottom field in order to
>> -		 * program any DMA correctly. Using ALTERNATE is wrong, since
>> -		 * that just says that it is either a top or a bottom field,
>> -		 * but not which of the two it is.
>> -		 */
>> -		dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
>> -		return -EINVAL;
>> -	}
>> -
>>   	if (q->error) {
>>   		dprintk(1, "fatal error occurred on queue\n");
>>   		return -EIO;
>>   	}
>>
>> -	vb->state = VB2_BUF_STATE_PREPARING;
>> -	vbuf->timestamp.tv_sec = 0;
>> -	vbuf->timestamp.tv_usec = 0;
>> -	vbuf->sequence = 0;
>> -
>>   	switch (q->memory) {
>> -	case V4L2_MEMORY_MMAP:
>> -		ret = __qbuf_mmap(vb, b);
>> +	case VB2_MEMORY_MMAP:
>> +		ret = __qbuf_mmap(vb, pb);
>>   		break;
>> -	case V4L2_MEMORY_USERPTR:
>> +	case VB2_MEMORY_USERPTR:
>>   		down_read(&current->mm->mmap_sem);
>> -		ret = __qbuf_userptr(vb, b);
>> +		ret = __qbuf_userptr(vb, pb);
>>   		up_read(&current->mm->mmap_sem);
>>   		break;
>> -	case V4L2_MEMORY_DMABUF:
>> -		ret = __qbuf_dmabuf(vb, b);
>> +	case VB2_MEMORY_DMABUF:
>> +		ret = __qbuf_dmabuf(vb, pb);
>>   		break;
>>   	default:
>>   		WARN(1, "Invalid queue type\n");
>> @@ -1736,35 +1217,56 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>>   	return ret;
>>   }
>>
>> -static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
>> -					const char *opname)
>> +int vb2_verify_buffer(struct vb2_queue *q,
>> +			unsigned int memory, unsigned int type,
>> +			unsigned int index, unsigned int nplanes,
>> +			void *pplane, const char *opname)
>>   {
>> -	if (b->type != q->type) {
>> +	if (type != q->type) {
>>   		dprintk(1, "%s: invalid buffer type\n", opname);
>>   		return -EINVAL;
>>   	}
>>
>> -	if (b->index >= q->num_buffers) {
>> +	if (index >= q->num_buffers) {
>>   		dprintk(1, "%s: buffer index out of range\n", opname);
>>   		return -EINVAL;
>>   	}
>>
>> -	if (q->bufs[b->index] == NULL) {
>> +	if (q->bufs[index] == NULL) {
>>   		/* Should never happen */
>>   		dprintk(1, "%s: buffer is NULL\n", opname);
>>   		return -EINVAL;
>>   	}
>>
>> -	if (b->memory != q->memory) {
>> +	if (memory != VB2_MEMORY_UNKNOWN && memory != q->memory) {
>>   		dprintk(1, "%s: invalid memory type\n", opname);
>>   		return -EINVAL;
>>   	}
>>
>> -	return __verify_planes_array(q->bufs[b->index], b);
>> +	if (q->is_multiplanar) {
>> +		struct vb2_buffer *vb = q->bufs[index];
>> +
>> +		/* Is memory for copying plane information present? */
>> +		if (NULL == pplane) {
>> +			dprintk(1, "%s: multi-planar buffer passed but "
>> +				"planes array not provided\n", opname);
>> +			return -EINVAL;
>> +		}
>> +
>> +		if (nplanes < vb->num_planes || nplanes > VB2_MAX_PLANES) {
>> +			dprintk(1, "%s: incorrect planes array length, "
>> +				"expected %d, got %d\n",
>> +				opname, vb->num_planes, nplanes);
>> +			return -EINVAL;
>> +		}
>> +	}
>> +
>> +	return 0;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_verify_buffer);
>>
>>   /**
>> - * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
>> + * vb2_core_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
>>    * @q:		videobuf2 queue
>>    * @b:		buffer structure passed from userspace to vidioc_prepare_buf
>>    *		handler in driver
>> @@ -1778,37 +1280,28 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
>>    * The return values from this function are intended to be directly returned
>>    * from vidioc_prepare_buf handler in driver.
>>    */
>> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
>>   {
>>   	struct vb2_buffer *vb;
>>   	int ret;
>>
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -
>> -	ret = vb2_queue_or_prepare_buf(q, b, "prepare_buf");
>> -	if (ret)
>> -		return ret;
>> -
>> -	vb = q->bufs[b->index];
>> +	vb = q->bufs[index];
>>   	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
>>   		dprintk(1, "invalid buffer state %d\n",
>>   			vb->state);
>>   		return -EINVAL;
>>   	}
>>
>> -	ret = __buf_prepare(vb, b);
>> +	ret = __buf_prepare(vb, pb);
>>   	if (!ret) {
>>   		/* Fill buffer information for the userspace */
>> -		__fill_v4l2_buffer(vb, b);
>> +		call_bufop(q, fill_user_buffer, vb, pb);
>>
>>   		dprintk(1, "prepare of buffer %d succeeded\n", vb->index);
>>   	}
>>   	return ret;
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_prepare_buf);
>> +EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
>>
>>   /**
>>    * vb2_start_streaming() - Attempt to start streaming.
>> @@ -1873,21 +1366,16 @@ static int vb2_start_streaming(struct vb2_queue *q)
>>   	return ret;
>>   }
>>
>> -static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
>>   {
>> -	int ret = vb2_queue_or_prepare_buf(q, b, "qbuf");
>> +	int ret;
>>   	struct vb2_buffer *vb;
>> -	struct vb2_v4l2_buffer *vbuf;
>> -
>> -	if (ret)
>> -		return ret;
>>
>> -	vb = q->bufs[b->index];
>> -	vbuf = to_vb2_v4l2_buffer(vb);
>> +	vb = q->bufs[index];
>>
>>   	switch (vb->state) {
>>   	case VB2_BUF_STATE_DEQUEUED:
>> -		ret = __buf_prepare(vb, b);
>> +		ret = __buf_prepare(vb, pb);
>>   		if (ret)
>>   			return ret;
>>   		break;
>> @@ -1909,18 +1397,9 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   	q->queued_count++;
>>   	q->waiting_for_buffers = false;
>>   	vb->state = VB2_BUF_STATE_QUEUED;
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
>> -		/*
>> -		 * For output buffers copy the timestamp if needed,
>> -		 * and the timecode field and flag if needed.
>> -		 */
>> -		if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> -				V4L2_BUF_FLAG_TIMESTAMP_COPY)
>> -			vbuf->timestamp = b->timestamp;
>> -		vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
>> -		if (b->flags & V4L2_BUF_FLAG_TIMECODE)
>> -			vbuf->timecode = b->timecode;
>> -	}
>> +
>> +	if (q->is_output)
>> +		call_bufop(q, fill_vb2_timestamp, vb, pb);
>>
>>   	trace_vb2_qbuf(q, vb);
>>
>> @@ -1932,7 +1411,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   		__enqueue_in_driver(vb);
>>
>>   	/* Fill buffer information for the userspace */
>> -	__fill_v4l2_buffer(vb, b);
>> +	call_bufop(q, fill_user_buffer, vb, pb);
>>
>>   	/*
>>   	 * If streamon has been called, and we haven't yet called
>> @@ -1950,34 +1429,7 @@ static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>>   	dprintk(1, "qbuf of buffer %d succeeded\n", vb->index);
>>   	return 0;
>>   }
>> -
>> -/**
>> - * vb2_qbuf() - Queue a buffer from userspace
>> - * @q:		videobuf2 queue
>> - * @b:		buffer structure passed from userspace to vidioc_qbuf handler
>> - *		in driver
>> - *
>> - * Should be called from vidioc_qbuf ioctl handler of a driver.
>> - * This function:
>> - * 1) verifies the passed buffer,
>> - * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
>> - *    which driver-specific buffer initialization can be performed,
>> - * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
>> - *    callback for processing.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_qbuf handler in driver.
>> - */
>> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> -{
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -
>> -	return vb2_internal_qbuf(q, b);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_qbuf);
>> +EXPORT_SYMBOL_GPL(vb2_core_qbuf);
>>
>>   /**
>>    * __vb2_wait_for_done_vb() - wait for a buffer to become available
>> @@ -2061,7 +1513,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
>>    * Will sleep if required for nonblocking == false.
>>    */
>>   static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
>> -				struct v4l2_buffer *b, int nonblocking)
>> +				int nonblocking)
>>   {
>>   	unsigned long flags;
>>   	int ret;
>> @@ -2082,10 +1534,11 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
>>   	/*
>>   	 * Only remove the buffer from done_list if v4l2_buffer can handle all
>>   	 * the planes.
>> +	 * ret = __verify_planes_array(*vb, pb);
>> +	 * But, actually that's unnecessary since this is checked already
>> +	 * before the buffer is queued/prepared. So it can never fails
>>   	 */
>> -	ret = __verify_planes_array(*vb, b);
>> -	if (!ret)
>> -		list_del(&(*vb)->done_entry);
>> +	list_del(&(*vb)->done_entry);
>>   	spin_unlock_irqrestore(&q->done_lock, flags);
>>
>>   	return ret;
>> @@ -2128,27 +1581,22 @@ static void __vb2_dqbuf(struct vb2_buffer *vb)
>>   	vb->state = VB2_BUF_STATE_DEQUEUED;
>>
>>   	/* unmap DMABUF buffer */
>> -	if (q->memory == V4L2_MEMORY_DMABUF)
>> +	if (q->memory == VB2_MEMORY_DMABUF)
>>   		for (i = 0; i < vb->num_planes; ++i) {
>>   			if (!vb->planes[i].dbuf_mapped)
>>   				continue;
>> -			call_void_memop(vb, unmap_dmabuf, vb->planes[i].mem_priv);
>> +			call_void_memop(vb, unmap_dmabuf,
>> +					vb->planes[i].mem_priv);
>>   			vb->planes[i].dbuf_mapped = 0;
>>   		}
>>   }
>>
>> -static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>> -		bool nonblocking)
>> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblocking)
>>   {
>>   	struct vb2_buffer *vb = NULL;
>> -	struct vb2_v4l2_buffer *vbuf = NULL;
>>   	int ret;
>>
>> -	if (b->type != q->type) {
>> -		dprintk(1, "invalid buffer type\n");
>> -		return -EINVAL;
>> -	}
>> -	ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
>> +	ret = __vb2_get_done_vb(q, &vb, nonblocking);
>>   	if (ret < 0)
>>   		return ret;
>>
>> @@ -2167,16 +1615,15 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>>   	call_void_vb_qop(vb, buf_finish, vb);
>>
>>   	/* Fill buffer information for the userspace */
>> -	__fill_v4l2_buffer(vb, b);
>> +	call_bufop(q, fill_user_buffer, vb, pb);
>>   	/* Remove from videobuf queue */
>>   	list_del(&vb->queued_entry);
>>   	q->queued_count--;
>>
>>   	trace_vb2_dqbuf(q, vb);
>>
>> -	vbuf = to_vb2_v4l2_buffer(vb);
>> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
>> -			vbuf->flags & V4L2_BUF_FLAG_LAST)
>> +	if (!q->is_output &&
>> +			call_bufop(q, is_last, vb))
>>   		q->last_buffer_dequeued = true;
>>   	/* go back to dequeued state */
>>   	__vb2_dqbuf(vb);
>> @@ -2186,37 +1633,7 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>>
>>   	return 0;
>>   }
>> -
>> -/**
>> - * vb2_dqbuf() - Dequeue a buffer to the userspace
>> - * @q:		videobuf2 queue
>> - * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
>> - *		in driver
>> - * @nonblocking: if true, this call will not sleep waiting for a buffer if no
>> - *		 buffers ready for dequeuing are present. Normally the driver
>> - *		 would be passing (file->f_flags & O_NONBLOCK) here
>> - *
>> - * Should be called from vidioc_dqbuf ioctl handler of a driver.
>> - * This function:
>> - * 1) verifies the passed buffer,
>> - * 2) calls buf_finish callback in the driver (if provided), in which
>> - *    driver can perform any additional operations that may be required before
>> - *    returning the buffer to userspace, such as cache sync,
>> - * 3) the buffer struct members are filled with relevant information for
>> - *    the userspace.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_dqbuf handler in driver.
>> - */
>> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
>> -{
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -	return vb2_internal_dqbuf(q, b, nonblocking);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_dqbuf);
>> +EXPORT_SYMBOL_GPL(vb2_core_dqbuf);
>>
>>   /**
>>    * __vb2_queue_cancel() - cancel and stop (pause) streaming
>> @@ -2286,15 +1703,10 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
>>   	}
>>   }
>>
>> -static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>> +int vb2_core_streamon(struct vb2_queue *q)
>>   {
>>   	int ret;
>>
>> -	if (type != q->type) {
>> -		dprintk(1, "invalid stream type\n");
>> -		return -EINVAL;
>> -	}
>> -
>>   	if (q->streaming) {
>>   		dprintk(3, "already streaming\n");
>>   		return 0;
>> @@ -2328,6 +1740,7 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>>   	dprintk(3, "successful\n");
>>   	return 0;
>>   }
>> +EXPORT_SYMBOL_GPL(vb2_core_streamon);
>>
>>   /**
>>    * vb2_queue_error() - signal a fatal error on the queue
>> @@ -2350,36 +1763,8 @@ void vb2_queue_error(struct vb2_queue *q)
>>   }
>>   EXPORT_SYMBOL_GPL(vb2_queue_error);
>>
>> -/**
>> - * vb2_streamon - start streaming
>> - * @q:		videobuf2 queue
>> - * @type:	type argument passed from userspace to vidioc_streamon handler
>> - *
>> - * Should be called from vidioc_streamon handler of a driver.
>> - * This function:
>> - * 1) verifies current state
>> - * 2) passes any previously queued buffers to the driver and starts streaming
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_streamon handler in the driver.
>> - */
>> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>> -{
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -	return vb2_internal_streamon(q, type);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_streamon);
>> -
>> -static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>> +int vb2_core_streamoff(struct vb2_queue *q)
>>   {
>> -	if (type != q->type) {
>> -		dprintk(1, "invalid stream type\n");
>> -		return -EINVAL;
>> -	}
>> -
>>   	/*
>>   	 * Cancel will pause streaming and remove all buffers from the driver
>>   	 * and videobuf, effectively returning control over them to userspace.
>> @@ -2390,37 +1775,13 @@ static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>>   	 * their normal dequeued state.
>>   	 */
>>   	__vb2_queue_cancel(q);
>> -	q->waiting_for_buffers = !V4L2_TYPE_IS_OUTPUT(q->type);
>> +	q->waiting_for_buffers = !q->is_output;
>>   	q->last_buffer_dequeued = false;
>>
>>   	dprintk(3, "successful\n");
>>   	return 0;
>>   }
>> -
>> -/**
>> - * vb2_streamoff - stop streaming
>> - * @q:		videobuf2 queue
>> - * @type:	type argument passed from userspace to vidioc_streamoff handler
>> - *
>> - * Should be called from vidioc_streamoff handler of a driver.
>> - * This function:
>> - * 1) verifies current state,
>> - * 2) stop streaming and dequeues any queued buffers, including those previously
>> - *    passed to the driver (after waiting for the driver to finish).
>> - *
>> - * This call can be used for pausing playback.
>> - * The return values from this function are intended to be directly returned
>> - * from vidioc_streamoff handler in the driver
>> - */
>> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>> -{
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> -	return vb2_internal_streamoff(q, type);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_streamoff);
>> +EXPORT_SYMBOL_GPL(vb2_core_streamoff);
>>
>>   /**
>>    * __find_plane_by_offset() - find plane associated with the given offset off
>> @@ -2452,7 +1813,7 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>   }
>>
>>   /**
>> - * vb2_expbuf() - Export a buffer as a file descriptor
>> + * vb2_core_expbuf() - Export a buffer as a file descriptor
>>    * @q:		videobuf2 queue
>>    * @eb:		export buffer structure passed from userspace to vidioc_expbuf
>>    *		handler in driver
>> @@ -2460,14 +1821,15 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
>>    * The return values from this function are intended to be directly returned
>>    * from vidioc_expbuf handler in driver.
>>    */
>> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
>> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>> +		unsigned int index, unsigned int plane, unsigned int flags)
>>   {
>>   	struct vb2_buffer *vb = NULL;
>>   	struct vb2_plane *vb_plane;
>>   	int ret;
>>   	struct dma_buf *dbuf;
>>
>> -	if (q->memory != V4L2_MEMORY_MMAP) {
>> +	if (q->memory != VB2_MEMORY_MMAP) {
>>   		dprintk(1, "queue is not currently set up for mmap\n");
>>   		return -EINVAL;
>>   	}
>> @@ -2477,78 +1839,60 @@ int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
>>   		return -EINVAL;
>>   	}
>>
>> -	if (eb->flags & ~(O_CLOEXEC | O_ACCMODE)) {
>> +	if (flags & ~(O_CLOEXEC | O_ACCMODE)) {
>>   		dprintk(1, "queue does support only O_CLOEXEC and access mode flags\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (eb->type != q->type) {
>> +	if (type != q->type) {
>>   		dprintk(1, "invalid buffer type\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (eb->index >= q->num_buffers) {
>> +	if (index >= q->num_buffers) {
>>   		dprintk(1, "buffer index out of range\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	vb = q->bufs[eb->index];
>> +	vb = q->bufs[index];
>>
>> -	if (eb->plane >= vb->num_planes) {
>> +	if (plane >= vb->num_planes) {
>>   		dprintk(1, "buffer plane out of range\n");
>>   		return -EINVAL;
>>   	}
>>
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "expbuf: file io in progress\n");
>> -		return -EBUSY;
>> -	}
>> +	vb_plane = &vb->planes[plane];
>>
>> -	vb_plane = &vb->planes[eb->plane];
>> -
>> -	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv, eb->flags & O_ACCMODE);
>> +	dbuf = call_ptr_memop(vb, get_dmabuf, vb_plane->mem_priv,
>> +				flags & O_ACCMODE);
>>   	if (IS_ERR_OR_NULL(dbuf)) {
>>   		dprintk(1, "failed to export buffer %d, plane %d\n",
>> -			eb->index, eb->plane);
>> +			index, plane);
>>   		return -EINVAL;
>>   	}
>>
>> -	ret = dma_buf_fd(dbuf, eb->flags & ~O_ACCMODE);
>> +	ret = dma_buf_fd(dbuf, flags & ~O_ACCMODE);
>>   	if (ret < 0) {
>>   		dprintk(3, "buffer %d, plane %d failed to export (%d)\n",
>> -			eb->index, eb->plane, ret);
>> +			index, plane, ret);
>>   		dma_buf_put(dbuf);
>>   		return ret;
>>   	}
>>
>>   	dprintk(3, "buffer %d, plane %d exported as %d descriptor\n",
>> -		eb->index, eb->plane, ret);
>> -	eb->fd = ret;
>> +		index, plane, ret);
>> +	*fd = ret;
>>
>>   	return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_expbuf);
>> +EXPORT_SYMBOL_GPL(vb2_core_expbuf);
>>
>>   /**
>> - * vb2_mmap() - map video buffers into application address space
>> + * vb2_core_mmap() - map video buffers into application address space
>>    * @q:		videobuf2 queue
>>    * @vma:	vma passed to the mmap file operation handler in the driver
>> - *
>> - * Should be called from mmap file operation handler of a driver.
>> - * This function maps one plane of one of the available video buffers to
>> - * userspace. To map whole video memory allocated on reqbufs, this function
>> - * has to be called once per each plane per each buffer previously allocated.
>> - *
>> - * When the userspace application calls mmap, it passes to it an offset returned
>> - * to it earlier by the means of vidioc_querybuf handler. That offset acts as
>> - * a "cookie", which is then used to identify the plane to be mapped.
>> - * This function finds a plane with a matching offset and a mapping is performed
>> - * by the means of a provided memory operation.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from the mmap handler in driver.
>>    */
>> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   {
>>   	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
>>   	struct vb2_buffer *vb;
>> @@ -2556,7 +1900,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   	int ret;
>>   	unsigned long length;
>>
>> -	if (q->memory != V4L2_MEMORY_MMAP) {
>> +	if (q->memory != VB2_MEMORY_MMAP) {
>>   		dprintk(1, "queue is not currently set up for mmap\n");
>>   		return -EINVAL;
>>   	}
>> @@ -2568,7 +1912,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   		dprintk(1, "invalid vma flags, VM_SHARED needed\n");
>>   		return -EINVAL;
>>   	}
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
>> +	if (q->is_output) {
>>   		if (!(vma->vm_flags & VM_WRITE)) {
>>   			dprintk(1, "invalid vma flags, VM_WRITE needed\n");
>>   			return -EINVAL;
>> @@ -2579,10 +1923,6 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   			return -EINVAL;
>>   		}
>>   	}
>> -	if (vb2_fileio_is_active(q)) {
>> -		dprintk(1, "mmap: file io in progress\n");
>> -		return -EBUSY;
>> -	}
>>
>>   	/*
>>   	 * Find the plane corresponding to the offset passed by userspace.
>> @@ -2614,7 +1954,7 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>>   	dprintk(3, "buffer %d, plane %d successfully mapped\n", buffer, plane);
>>   	return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_mmap);
>> +EXPORT_SYMBOL_GPL(vb2_core_mmap);
>>
>>   #ifndef CONFIG_MMU
>>   unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>> @@ -2629,7 +1969,7 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>   	void *vaddr;
>>   	int ret;
>>
>> -	if (q->memory != V4L2_MEMORY_MMAP) {
>> +	if (q->memory != VB2_MEMORY_MMAP) {
>>   		dprintk(1, "queue is not currently set up for mmap\n");
>>   		return -EINVAL;
>>   	}
>> @@ -2649,123 +1989,8 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>   EXPORT_SYMBOL_GPL(vb2_get_unmapped_area);
>>   #endif
>>
>> -static int __vb2_init_fileio(struct vb2_queue *q, int read);
>> -static int __vb2_cleanup_fileio(struct vb2_queue *q);
>> -
>> -/**
>> - * vb2_poll() - implements poll userspace operation
>> - * @q:		videobuf2 queue
>> - * @file:	file argument passed to the poll file operation handler
>> - * @wait:	wait argument passed to the poll file operation handler
>> - *
>> - * This function implements poll file operation handler for a driver.
>> - * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
>> - * be informed that the file descriptor of a video device is available for
>> - * reading.
>> - * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
>> - * will be reported as available for writing.
>> - *
>> - * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
>> - * pending events.
>> - *
>> - * The return values from this function are intended to be directly returned
>> - * from poll handler in driver.
>> - */
>> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
>> -{
>> -	struct video_device *vfd = video_devdata(file);
>> -	unsigned long req_events = poll_requested_events(wait);
>> -	struct vb2_buffer *vb = NULL;
>> -	unsigned int res = 0;
>> -	unsigned long flags;
>> -
>> -	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
>> -		struct v4l2_fh *fh = file->private_data;
>> -
>> -		if (v4l2_event_pending(fh))
>> -			res = POLLPRI;
>> -		else if (req_events & POLLPRI)
>> -			poll_wait(file, &fh->wait, wait);
>> -	}
>> -
>> -	if (!V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLIN | POLLRDNORM)))
>> -		return res;
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && !(req_events & (POLLOUT | POLLWRNORM)))
>> -		return res;
>> -
>> -	/*
>> -	 * Start file I/O emulator only if streaming API has not been used yet.
>> -	 */
>> -	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
>> -		if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
>> -				(req_events & (POLLIN | POLLRDNORM))) {
>> -			if (__vb2_init_fileio(q, 1))
>> -				return res | POLLERR;
>> -		}
>> -		if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
>> -				(req_events & (POLLOUT | POLLWRNORM))) {
>> -			if (__vb2_init_fileio(q, 0))
>> -				return res | POLLERR;
>> -			/*
>> -			 * Write to OUTPUT queue can be done immediately.
>> -			 */
>> -			return res | POLLOUT | POLLWRNORM;
>> -		}
>> -	}
>> -
>> -	/*
>> -	 * There is nothing to wait for if the queue isn't streaming, or if the
>> -	 * error flag is set.
>> -	 */
>> -	if (!vb2_is_streaming(q) || q->error)
>> -		return res | POLLERR;
>> -	/*
>> -	 * For compatibility with vb1: if QBUF hasn't been called yet, then
>> -	 * return POLLERR as well. This only affects capture queues, output
>> -	 * queues will always initialize waiting_for_buffers to false.
>> -	 */
>> -	if (q->waiting_for_buffers)
>> -		return res | POLLERR;
>> -
>> -	/*
>> -	 * For output streams you can write as long as there are fewer buffers
>> -	 * queued than there are buffers available.
>> -	 */
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type) && q->queued_count < q->num_buffers)
>> -		return res | POLLOUT | POLLWRNORM;
>> -
>> -	if (list_empty(&q->done_list)) {
>> -		/*
>> -		 * If the last buffer was dequeued from a capture queue,
>> -		 * return immediately. DQBUF will return -EPIPE.
>> -		 */
>> -		if (q->last_buffer_dequeued)
>> -			return res | POLLIN | POLLRDNORM;
>> -
>> -		poll_wait(file, &q->done_wq, wait);
>> -	}
>> -
>> -	/*
>> -	 * Take first buffer available for dequeuing.
>> -	 */
>> -	spin_lock_irqsave(&q->done_lock, flags);
>> -	if (!list_empty(&q->done_list))
>> -		vb = list_first_entry(&q->done_list, struct vb2_buffer,
>> -					done_entry);
>> -	spin_unlock_irqrestore(&q->done_lock, flags);
>> -
>> -	if (vb && (vb->state == VB2_BUF_STATE_DONE
>> -			|| vb->state == VB2_BUF_STATE_ERROR)) {
>> -		return (V4L2_TYPE_IS_OUTPUT(q->type)) ?
>> -				res | POLLOUT | POLLWRNORM :
>> -				res | POLLIN | POLLRDNORM;
>> -	}
>> -	return res;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_poll);
>> -
>>   /**
>> - * vb2_queue_init() - initialize a videobuf2 queue
>> + * vb2_core_queue_init() - initialize a videobuf2 queue
>>    * @q:		videobuf2 queue; this structure should be allocated in driver
>>    *
>>    * The vb2_queue structure should be allocated by the driver. The driver is
>> @@ -2775,7 +2000,7 @@ EXPORT_SYMBOL_GPL(vb2_poll);
>>    * to the struct vb2_queue description in include/media/videobuf2-core.h
>>    * for more information.
>>    */
>> -int vb2_queue_init(struct vb2_queue *q)
>> +int vb2_core_queue_init(struct vb2_queue *q)
>>   {
>>   	/*
>>   	 * Sanity check
>> @@ -2783,19 +2008,13 @@ int vb2_queue_init(struct vb2_queue *q)
>>   	if (WARN_ON(!q)				||
>>   		WARN_ON(!q->ops)		||
>>   		WARN_ON(!q->mem_ops)		||
>> +		WARN_ON(!q->buf_ops)		||
>>   		WARN_ON(!q->type)		||
>>   		WARN_ON(!q->io_modes)		||
>>   		WARN_ON(!q->ops->queue_setup)	||
>> -		WARN_ON(!q->ops->buf_queue)	||
>> -		WARN_ON(q->timestamp_flags &
>> -			~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
>> -			V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
>> +		WARN_ON(!q->ops->buf_queue))
>>   		return -EINVAL;
>>
>> -	/* Warn that the driver should choose an appropriate timestamp type */
>> -	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> -		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
>> -
>>   	INIT_LIST_HEAD(&q->queued_list);
>>   	INIT_LIST_HEAD(&q->done_list);
>>   	spin_lock_init(&q->done_lock);
>> @@ -2807,822 +2026,24 @@ int vb2_queue_init(struct vb2_queue *q)
>>
>>   	return 0;
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_queue_init);
>> +EXPORT_SYMBOL_GPL(vb2_core_queue_init);
>>
>>   /**
>> - * vb2_queue_release() - stop streaming, release the queue and free memory
>> + * vb2_core_queue_release() - stop streaming, release the queue and free memory
>>    * @q:		videobuf2 queue
>>    *
>>    * This function stops streaming and performs necessary clean ups, including
>>    * freeing video buffer memory. The driver is responsible for freeing
>>    * the vb2_queue structure itself.
>>    */
>> -void vb2_queue_release(struct vb2_queue *q)
>> +void vb2_core_queue_release(struct vb2_queue *q)
>>   {
>> -	__vb2_cleanup_fileio(q);
>>   	__vb2_queue_cancel(q);
>>   	mutex_lock(&q->mmap_lock);
>>   	__vb2_queue_free(q, q->num_buffers);
>>   	mutex_unlock(&q->mmap_lock);
>>   }
>> -EXPORT_SYMBOL_GPL(vb2_queue_release);
>> -
>> -/**
>> - * struct vb2_fileio_buf - buffer context used by file io emulator
>> - *
>> - * vb2 provides a compatibility layer and emulator of file io (read and
>> - * write) calls on top of streaming API. This structure is used for
>> - * tracking context related to the buffers.
>> - */
>> -struct vb2_fileio_buf {
>> -	void *vaddr;
>> -	unsigned int size;
>> -	unsigned int pos;
>> -	unsigned int queued:1;
>> -};
>> -
>> -/**
>> - * struct vb2_fileio_data - queue context used by file io emulator
>> - *
>> - * @cur_index:	the index of the buffer currently being read from or
>> - *		written to. If equal to q->num_buffers then a new buffer
>> - *		must be dequeued.
>> - * @initial_index: in the read() case all buffers are queued up immediately
>> - *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
>> - *		buffers. However, in the write() case no buffers are initially
>> - *		queued, instead whenever a buffer is full it is queued up by
>> - *		__vb2_perform_fileio(). Only once all available buffers have
>> - *		been queued up will __vb2_perform_fileio() start to dequeue
>> - *		buffers. This means that initially __vb2_perform_fileio()
>> - *		needs to know what buffer index to use when it is queuing up
>> - *		the buffers for the first time. That initial index is stored
>> - *		in this field. Once it is equal to q->num_buffers all
>> - *		available buffers have been queued and __vb2_perform_fileio()
>> - *		should start the normal dequeue/queue cycle.
>> - *
>> - * vb2 provides a compatibility layer and emulator of file io (read and
>> - * write) calls on top of streaming API. For proper operation it required
>> - * this structure to save the driver state between each call of the read
>> - * or write function.
>> - */
>> -struct vb2_fileio_data {
>> -	struct v4l2_requestbuffers req;
>> -	struct v4l2_plane p;
>> -	struct v4l2_buffer b;
>> -	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
>> -	unsigned int cur_index;
>> -	unsigned int initial_index;
>> -	unsigned int q_count;
>> -	unsigned int dq_count;
>> -	unsigned read_once:1;
>> -	unsigned write_immediately:1;
>> -};
>> -
>> -/**
>> - * __vb2_init_fileio() - initialize file io emulator
>> - * @q:		videobuf2 queue
>> - * @read:	mode selector (1 means read, 0 means write)
>> - */
>> -static int __vb2_init_fileio(struct vb2_queue *q, int read)
>> -{
>> -	struct vb2_fileio_data *fileio;
>> -	int i, ret;
>> -	unsigned int count = 0;
>> -
>> -	/*
>> -	 * Sanity check
>> -	 */
>> -	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
>> -			(!read && !(q->io_modes & VB2_WRITE))))
>> -		return -EINVAL;
>> -
>> -	/*
>> -	 * Check if device supports mapping buffers to kernel virtual space.
>> -	 */
>> -	if (!q->mem_ops->vaddr)
>> -		return -EBUSY;
>> -
>> -	/*
>> -	 * Check if streaming api has not been already activated.
>> -	 */
>> -	if (q->streaming || q->num_buffers > 0)
>> -		return -EBUSY;
>> -
>> -	/*
>> -	 * Start with count 1, driver can increase it in queue_setup()
>> -	 */
>> -	count = 1;
>> -
>> -	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, write_immediately %d\n",
>> -		(read) ? "read" : "write", count, q->fileio_read_once,
>> -		q->fileio_write_immediately);
>> -
>> -	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
>> -	if (fileio == NULL)
>> -		return -ENOMEM;
>> -
>> -	fileio->read_once = q->fileio_read_once;
>> -	fileio->write_immediately = q->fileio_write_immediately;
>> -
>> -	/*
>> -	 * Request buffers and use MMAP type to force driver
>> -	 * to allocate buffers by itself.
>> -	 */
>> -	fileio->req.count = count;
>> -	fileio->req.memory = V4L2_MEMORY_MMAP;
>> -	fileio->req.type = q->type;
>> -	q->fileio = fileio;
>> -	ret = __reqbufs(q, &fileio->req);
>> -	if (ret)
>> -		goto err_kfree;
>> -
>> -	/*
>> -	 * Check if plane_count is correct
>> -	 * (multiplane buffers are not supported).
>> -	 */
>> -	if (q->bufs[0]->num_planes != 1) {
>> -		ret = -EBUSY;
>> -		goto err_reqbufs;
>> -	}
>> -
>> -	/*
>> -	 * Get kernel address of each buffer.
>> -	 */
>> -	for (i = 0; i < q->num_buffers; i++) {
>> -		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>> -		if (fileio->bufs[i].vaddr == NULL) {
>> -			ret = -EINVAL;
>> -			goto err_reqbufs;
>> -		}
>> -		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>> -	}
>> -
>> -	/*
>> -	 * Read mode requires pre queuing of all buffers.
>> -	 */
>> -	if (read) {
>> -		bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
>> -
>> -		/*
>> -		 * Queue all buffers.
>> -		 */
>> -		for (i = 0; i < q->num_buffers; i++) {
>> -			struct v4l2_buffer *b = &fileio->b;
>> -
>> -			memset(b, 0, sizeof(*b));
>> -			b->type = q->type;
>> -			if (is_multiplanar) {
>> -				memset(&fileio->p, 0, sizeof(fileio->p));
>> -				b->m.planes = &fileio->p;
>> -				b->length = 1;
>> -			}
>> -			b->memory = q->memory;
>> -			b->index = i;
>> -			ret = vb2_internal_qbuf(q, b);
>> -			if (ret)
>> -				goto err_reqbufs;
>> -			fileio->bufs[i].queued = 1;
>> -		}
>> -		/*
>> -		 * All buffers have been queued, so mark that by setting
>> -		 * initial_index to q->num_buffers
>> -		 */
>> -		fileio->initial_index = q->num_buffers;
>> -		fileio->cur_index = q->num_buffers;
>> -	}
>> -
>> -	/*
>> -	 * Start streaming.
>> -	 */
>> -	ret = vb2_internal_streamon(q, q->type);
>> -	if (ret)
>> -		goto err_reqbufs;
>> -
>> -	return ret;
>> -
>> -err_reqbufs:
>> -	fileio->req.count = 0;
>> -	__reqbufs(q, &fileio->req);
>> -
>> -err_kfree:
>> -	q->fileio = NULL;
>> -	kfree(fileio);
>> -	return ret;
>> -}
>> -
>> -/**
>> - * __vb2_cleanup_fileio() - free resourced used by file io emulator
>> - * @q:		videobuf2 queue
>> - */
>> -static int __vb2_cleanup_fileio(struct vb2_queue *q)
>> -{
>> -	struct vb2_fileio_data *fileio = q->fileio;
>> -
>> -	if (fileio) {
>> -		vb2_internal_streamoff(q, q->type);
>> -		q->fileio = NULL;
>> -		fileio->req.count = 0;
>> -		vb2_reqbufs(q, &fileio->req);
>> -		kfree(fileio);
>> -		dprintk(3, "file io emulator closed\n");
>> -	}
>> -	return 0;
>> -}
>> -
>> -/**
>> - * __vb2_perform_fileio() - perform a single file io (read or write) operation
>> - * @q:		videobuf2 queue
>> - * @data:	pointed to target userspace buffer
>> - * @count:	number of bytes to read or write
>> - * @ppos:	file handle position tracking pointer
>> - * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
>> - * @read:	access mode selector (1 means read, 0 means write)
>> - */
>> -static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
>> -		loff_t *ppos, int nonblock, int read)
>> -{
>> -	struct vb2_fileio_data *fileio;
>> -	struct vb2_fileio_buf *buf;
>> -	bool is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
>> -	/*
>> -	 * When using write() to write data to an output video node the vb2 core
>> -	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
>> -	 * else is able to provide this information with the write() operation.
>> -	 */
>> -	bool set_timestamp = !read &&
>> -		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> -		V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> -	int ret, index;
>> -
>> -	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
>> -		read ? "read" : "write", (long)*ppos, count,
>> -		nonblock ? "non" : "");
>> -
>> -	if (!data)
>> -		return -EINVAL;
>> -
>> -	/*
>> -	 * Initialize emulator on first call.
>> -	 */
>> -	if (!vb2_fileio_is_active(q)) {
>> -		ret = __vb2_init_fileio(q, read);
>> -		dprintk(3, "vb2_init_fileio result: %d\n", ret);
>> -		if (ret)
>> -			return ret;
>> -	}
>> -	fileio = q->fileio;
>> -
>> -	/*
>> -	 * Check if we need to dequeue the buffer.
>> -	 */
>> -	index = fileio->cur_index;
>> -	if (index >= q->num_buffers) {
>> -		/*
>> -		 * Call vb2_dqbuf to get buffer back.
>> -		 */
>> -		memset(&fileio->b, 0, sizeof(fileio->b));
>> -		fileio->b.type = q->type;
>> -		fileio->b.memory = q->memory;
>> -		if (is_multiplanar) {
>> -			memset(&fileio->p, 0, sizeof(fileio->p));
>> -			fileio->b.m.planes = &fileio->p;
>> -			fileio->b.length = 1;
>> -		}
>> -		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
>> -		dprintk(5, "vb2_dqbuf result: %d\n", ret);
>> -		if (ret)
>> -			return ret;
>> -		fileio->dq_count += 1;
>> -
>> -		fileio->cur_index = index = fileio->b.index;
>> -		buf = &fileio->bufs[index];
>> -
>> -		/*
>> -		 * Get number of bytes filled by the driver
>> -		 */
>> -		buf->pos = 0;
>> -		buf->queued = 0;
>> -		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>> -				 : vb2_plane_size(q->bufs[index], 0);
>> -		/*
>> -		 * Compensate for data_offset on read
>> -		 * in the multiplanar case
>> -		 */
>> -		if (is_multiplanar && read &&
>> -			fileio->b.m.planes[0].data_offset < buf->size) {
>> -			buf->pos = fileio->b.m.planes[0].data_offset;
>> -			buf->size -= buf->pos;
>> -		}
>> -	} else {
>> -		buf = &fileio->bufs[index];
>> -	}
>> -
>> -	/*
>> -	 * Limit count on last few bytes of the buffer.
>> -	 */
>> -	if (buf->pos + count > buf->size) {
>> -		count = buf->size - buf->pos;
>> -		dprintk(5, "reducing read count: %zd\n", count);
>> -	}
>> -
>> -	/*
>> -	 * Transfer data to userspace.
>> -	 */
>> -	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
>> -		count, index, buf->pos);
>> -	if (read)
>> -		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
>> -	else
>> -		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
>> -	if (ret) {
>> -		dprintk(3, "error copying data\n");
>> -		return -EFAULT;
>> -	}
>> -
>> -	/*
>> -	 * Update counters.
>> -	 */
>> -	buf->pos += count;
>> -	*ppos += count;
>> -
>> -	/*
>> -	 * Queue next buffer if required.
>> -	 */
>> -	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>> -		/*
>> -		 * Check if this is the last buffer to read.
>> -		 */
>> -		if (read && fileio->read_once && fileio->dq_count == 1) {
>> -			dprintk(3, "read limit reached\n");
>> -			return __vb2_cleanup_fileio(q);
>> -		}
>> -
>> -		/*
>> -		 * Call vb2_qbuf and give buffer to the driver.
>> -		 */
>> -		memset(&fileio->b, 0, sizeof(fileio->b));
>> -		fileio->b.type = q->type;
>> -		fileio->b.memory = q->memory;
>> -		fileio->b.index = index;
>> -		fileio->b.bytesused = buf->pos;
>> -		if (is_multiplanar) {
>> -			memset(&fileio->p, 0, sizeof(fileio->p));
>> -			fileio->p.bytesused = buf->pos;
>> -			fileio->b.m.planes = &fileio->p;
>> -			fileio->b.length = 1;
>> -		}
>> -		if (set_timestamp)
>> -			v4l2_get_timestamp(&fileio->b.timestamp);
>> -		ret = vb2_internal_qbuf(q, &fileio->b);
>> -		dprintk(5, "vb2_dbuf result: %d\n", ret);
>> -		if (ret)
>> -			return ret;
>> -
>> -		/*
>> -		 * Buffer has been queued, update the status
>> -		 */
>> -		buf->pos = 0;
>> -		buf->queued = 1;
>> -		buf->size = vb2_plane_size(q->bufs[index], 0);
>> -		fileio->q_count += 1;
>> -		/*
>> -		 * If we are queuing up buffers for the first time, then
>> -		 * increase initial_index by one.
>> -		 */
>> -		if (fileio->initial_index < q->num_buffers)
>> -			fileio->initial_index++;
>> -		/*
>> -		 * The next buffer to use is either a buffer that's going to be
>> -		 * queued for the first time (initial_index < q->num_buffers)
>> -		 * or it is equal to q->num_buffers, meaning that the next
>> -		 * time we need to dequeue a buffer since we've now queued up
>> -		 * all the 'first time' buffers.
>> -		 */
>> -		fileio->cur_index = fileio->initial_index;
>> -	}
>> -
>> -	/*
>> -	 * Return proper number of bytes processed.
>> -	 */
>> -	if (ret == 0)
>> -		ret = count;
>> -	return ret;
>> -}
>> -
>> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
>> -		loff_t *ppos, int nonblocking)
>> -{
>> -	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_read);
>> -
>> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
>> -		loff_t *ppos, int nonblocking)
>> -{
>> -	return __vb2_perform_fileio(q, (char __user *) data, count,
>> -							ppos, nonblocking, 0);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_write);
>> -
>> -struct vb2_threadio_data {
>> -	struct task_struct *thread;
>> -	vb2_thread_fnc fnc;
>> -	void *priv;
>> -	bool stop;
>> -};
>> -
>> -static int vb2_thread(void *data)
>> -{
>> -	struct vb2_queue *q = data;
>> -	struct vb2_threadio_data *threadio = q->threadio;
>> -	struct vb2_fileio_data *fileio = q->fileio;
>> -	bool set_timestamp = false;
>> -	int prequeue = 0;
>> -	int index = 0;
>> -	int ret = 0;
>> -
>> -	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
>> -		prequeue = q->num_buffers;
>> -		set_timestamp =
>> -			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> -			V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> -	}
>> -
>> -	set_freezable();
>> -
>> -	for (;;) {
>> -		struct vb2_buffer *vb;
>> -
>> -		/*
>> -		 * Call vb2_dqbuf to get buffer back.
>> -		 */
>> -		memset(&fileio->b, 0, sizeof(fileio->b));
>> -		fileio->b.type = q->type;
>> -		fileio->b.memory = q->memory;
>> -		if (prequeue) {
>> -			fileio->b.index = index++;
>> -			prequeue--;
>> -		} else {
>> -			call_void_qop(q, wait_finish, q);
>> -			if (!threadio->stop)
>> -				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
>> -			call_void_qop(q, wait_prepare, q);
>> -			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
>> -		}
>> -		if (ret || threadio->stop)
>> -			break;
>> -		try_to_freeze();
>> -
>> -		vb = q->bufs[fileio->b.index];
>> -		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
>> -			if (threadio->fnc(vb, threadio->priv))
>> -				break;
>> -		call_void_qop(q, wait_finish, q);
>> -		if (set_timestamp)
>> -			v4l2_get_timestamp(&fileio->b.timestamp);
>> -		if (!threadio->stop)
>> -			ret = vb2_internal_qbuf(q, &fileio->b);
>> -		call_void_qop(q, wait_prepare, q);
>> -		if (ret || threadio->stop)
>> -			break;
>> -	}
>> -
>> -	/* Hmm, linux becomes *very* unhappy without this ... */
>> -	while (!kthread_should_stop()) {
>> -		set_current_state(TASK_INTERRUPTIBLE);
>> -		schedule();
>> -	}
>> -	return 0;
>> -}
>> -
>> -/*
>> - * This function should not be used for anything else but the videobuf2-dvb
>> - * support. If you think you have another good use-case for this, then please
>> - * contact the linux-media mailinglist first.
>> - */
>> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
>> -			const char *thread_name)
>> -{
>> -	struct vb2_threadio_data *threadio;
>> -	int ret = 0;
>> -
>> -	if (q->threadio)
>> -		return -EBUSY;
>> -	if (vb2_is_busy(q))
>> -		return -EBUSY;
>> -	if (WARN_ON(q->fileio))
>> -		return -EBUSY;
>> -
>> -	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
>> -	if (threadio == NULL)
>> -		return -ENOMEM;
>> -	threadio->fnc = fnc;
>> -	threadio->priv = priv;
>> -
>> -	ret = __vb2_init_fileio(q, !V4L2_TYPE_IS_OUTPUT(q->type));
>> -	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
>> -	if (ret)
>> -		goto nomem;
>> -	q->threadio = threadio;
>> -	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
>> -	if (IS_ERR(threadio->thread)) {
>> -		ret = PTR_ERR(threadio->thread);
>> -		threadio->thread = NULL;
>> -		goto nothread;
>> -	}
>> -	return 0;
>> -
>> -nothread:
>> -	__vb2_cleanup_fileio(q);
>> -nomem:
>> -	kfree(threadio);
>> -	return ret;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_thread_start);
>> -
>> -int vb2_thread_stop(struct vb2_queue *q)
>> -{
>> -	struct vb2_threadio_data *threadio = q->threadio;
>> -	int err;
>> -
>> -	if (threadio == NULL)
>> -		return 0;
>> -	threadio->stop = true;
>> -	/* Wake up all pending sleeps in the thread */
>> -	vb2_queue_error(q);
>> -	err = kthread_stop(threadio->thread);
>> -	__vb2_cleanup_fileio(q);
>> -	threadio->thread = NULL;
>> -	kfree(threadio);
>> -	q->threadio = NULL;
>> -	return err;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_thread_stop);
>> -
>> -/*
>> - * The following functions are not part of the vb2 core API, but are helper
>> - * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
>> - * and struct vb2_ops.
>> - * They contain boilerplate code that most if not all drivers have to do
>> - * and so they simplify the driver code.
>> - */
>> -
>> -/* The queue is busy if there is a owner and you are not that owner. */
>> -static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
>> -{
>> -	return vdev->queue->owner && vdev->queue->owner != file->private_data;
>> -}
>> -
>> -/* vb2 ioctl helpers */
>> -
>> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
>> -			  struct v4l2_requestbuffers *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	int res = __verify_memory_type(vdev->queue, p->memory, p->type);
>> -
>> -	if (res)
>> -		return res;
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	res = __reqbufs(vdev->queue, p);
>> -	/* If count == 0, then the owner has released all buffers and he
>> -	   is no longer owner of the queue. Otherwise we have a new owner. */
>> -	if (res == 0)
>> -		vdev->queue->owner = p->count ? file->private_data : NULL;
>> -	return res;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
>> -
>> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
>> -			  struct v4l2_create_buffers *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	int res = __verify_memory_type(vdev->queue, p->memory, p->format.type);
>> -
>> -	p->index = vdev->queue->num_buffers;
>> -	/* If count == 0, then just check if memory and type are valid.
>> -	   Any -EBUSY result from __verify_memory_type can be mapped to 0. */
>> -	if (p->count == 0)
>> -		return res != -EBUSY ? res : 0;
>> -	if (res)
>> -		return res;
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	res = __create_bufs(vdev->queue, p);
>> -	if (res == 0)
>> -		vdev->queue->owner = file->private_data;
>> -	return res;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
>> -
>> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
>> -			  struct v4l2_buffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_prepare_buf(vdev->queue, p);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
>> -
>> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
>> -	return vb2_querybuf(vdev->queue, p);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
>> -
>> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_qbuf(vdev->queue, p);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
>> -
>> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
>> -
>> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_streamon(vdev->queue, i);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
>> -
>> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_streamoff(vdev->queue, i);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
>> -
>> -int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		return -EBUSY;
>> -	return vb2_expbuf(vdev->queue, p);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
>> -
>> -/* v4l2_file_operations helpers */
>> -
>> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	return vb2_mmap(vdev->queue, vma);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_mmap);
>> -
>> -int _vb2_fop_release(struct file *file, struct mutex *lock)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	if (lock)
>> -		mutex_lock(lock);
>> -	if (file->private_data == vdev->queue->owner) {
>> -		vb2_queue_release(vdev->queue);
>> -		vdev->queue->owner = NULL;
>> -	}
>> -	if (lock)
>> -		mutex_unlock(lock);
>> -	return v4l2_fh_release(file);
>> -}
>> -EXPORT_SYMBOL_GPL(_vb2_fop_release);
>> -
>> -int vb2_fop_release(struct file *file)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> -
>> -	return _vb2_fop_release(file, lock);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_release);
>> -
>> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>> -		size_t count, loff_t *ppos)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> -	int err = -EBUSY;
>> -
>> -	if (!(vdev->queue->io_modes & VB2_WRITE))
>> -		return -EINVAL;
>> -	if (lock && mutex_lock_interruptible(lock))
>> -		return -ERESTARTSYS;
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		goto exit;
>> -	err = vb2_write(vdev->queue, buf, count, ppos,
>> -			file->f_flags & O_NONBLOCK);
>> -	if (vdev->queue->fileio)
>> -		vdev->queue->owner = file->private_data;
>> -exit:
>> -	if (lock)
>> -		mutex_unlock(lock);
>> -	return err;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_write);
>> -
>> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
>> -		size_t count, loff_t *ppos)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> -	int err = -EBUSY;
>> -
>> -	if (!(vdev->queue->io_modes & VB2_READ))
>> -		return -EINVAL;
>> -	if (lock && mutex_lock_interruptible(lock))
>> -		return -ERESTARTSYS;
>> -	if (vb2_queue_is_busy(vdev, file))
>> -		goto exit;
>> -	err = vb2_read(vdev->queue, buf, count, ppos,
>> -			file->f_flags & O_NONBLOCK);
>> -	if (vdev->queue->fileio)
>> -		vdev->queue->owner = file->private_data;
>> -exit:
>> -	if (lock)
>> -		mutex_unlock(lock);
>> -	return err;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_read);
>> -
>> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -	struct vb2_queue *q = vdev->queue;
>> -	struct mutex *lock = q->lock ? q->lock : vdev->lock;
>> -	unsigned res;
>> -	void *fileio;
>> -
>> -	/*
>> -	 * If this helper doesn't know how to lock, then you shouldn't be using
>> -	 * it but you should write your own.
>> -	 */
>> -	WARN_ON(!lock);
>> -
>> -	if (lock && mutex_lock_interruptible(lock))
>> -		return POLLERR;
>> -
>> -	fileio = q->fileio;
>> -
>> -	res = vb2_poll(vdev->queue, file, wait);
>> -
>> -	/* If fileio was started, then we have a new queue owner. */
>> -	if (!fileio && q->fileio)
>> -		q->owner = file->private_data;
>> -	if (lock)
>> -		mutex_unlock(lock);
>> -	return res;
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_poll);
>> -
>> -#ifndef CONFIG_MMU
>> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>> -		unsigned long len, unsigned long pgoff, unsigned long flags)
>> -{
>> -	struct video_device *vdev = video_devdata(file);
>> -
>> -	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
>> -#endif
>> -
>> -/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
>> -
>> -void vb2_ops_wait_prepare(struct vb2_queue *vq)
>> -{
>> -	mutex_unlock(vq->lock);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
>> -
>> -void vb2_ops_wait_finish(struct vb2_queue *vq)
>> -{
>> -	mutex_lock(vq->lock);
>> -}
>> -EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
>> +EXPORT_SYMBOL_GPL(vb2_core_queue_release);
>>
>>   MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
>>   MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
>> diff --git a/drivers/media/v4l2-core/videobuf2-internal.h b/drivers/media/v4l2-core/videobuf2-internal.h
>> new file mode 100644
>> index 0000000..3998ac9
>> --- /dev/null
>> +++ b/drivers/media/v4l2-core/videobuf2-internal.h
>> @@ -0,0 +1,184 @@
>> +#ifndef _MEDIA_VIDEOBUF2_INTERNAL_H
>> +#define _MEDIA_VIDEOBUF2_INTERNAL_H
>> +
>> +#include <linux/err.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <media/videobuf2-core.h>
>> +
>> +extern int vb2_debug;
>> +
>> +#define dprintk(level, fmt, arg...)					\
>> +	do {								\
>> +		if (vb2_debug >= level)					\
>> +			pr_info("vb2: %s: " fmt, __func__, ## arg);	\
>> +	} while (0)
>> +
>> +#ifdef CONFIG_VIDEO_ADV_DEBUG
>> +
>> +/*
>> + * If advanced debugging is on, then count how often each op is called
>> + * successfully, which can either be per-buffer or per-queue.
>> + *
>> + * This makes it easy to check that the 'init' and 'cleanup'
>> + * (and variations thereof) stay balanced.
>> + */
>> +
>> +#define log_memop(vb, op)						\
>> +	dprintk(2, "call_memop(%p, %d, %s)%s\n",			\
>> +		(vb)->vb2_queue, (vb)->index, #op,			\
>> +		(vb)->vb2_queue->mem_ops->op ? "" : " (nop)")
>> +
>> +#define call_memop(vb, op, args...)					\
>> +({									\
>> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> +	int err;							\
>> +									\
>> +	log_memop(vb, op);						\
>> +	err = _q->mem_ops->op ? _q->mem_ops->op(args) : 0;		\
>> +	if (!err)							\
>> +		(vb)->cnt_mem_ ## op++;					\
>> +	err;								\
>> +})
>> +
>> +#define call_ptr_memop(vb, op, args...)					\
>> +({									\
>> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> +	void *ptr;							\
>> +									\
>> +	log_memop(vb, op);						\
>> +	ptr = _q->mem_ops->op ? _q->mem_ops->op(args) : NULL;		\
>> +	if (!IS_ERR_OR_NULL(ptr))					\
>> +		(vb)->cnt_mem_ ## op++;					\
>> +	ptr;								\
>> +})
>> +
>> +#define call_void_memop(vb, op, args...)				\
>> +({									\
>> +	struct vb2_queue *_q = (vb)->vb2_queue;				\
>> +									\
>> +	log_memop(vb, op);						\
>> +	if (_q->mem_ops->op)						\
>> +		_q->mem_ops->op(args);					\
>> +	(vb)->cnt_mem_ ## op++;						\
>> +})
>> +
>> +#define log_qop(q, op)							\
>> +	dprintk(2, "call_qop(%p, %s)%s\n", q, #op,			\
>> +		(q)->ops->op ? "" : " (nop)")
>> +
>> +#define call_qop(q, op, args...)					\
>> +({									\
>> +	int err;							\
>> +									\
>> +	log_qop(q, op);							\
>> +	err = (q)->ops->op ? (q)->ops->op(args) : 0;			\
>> +	if (!err)							\
>> +		(q)->cnt_ ## op++;					\
>> +	err;								\
>> +})
>> +
>> +#define call_void_qop(q, op, args...)					\
>> +({									\
>> +	log_qop(q, op);							\
>> +	if ((q)->ops->op)						\
>> +		(q)->ops->op(args);					\
>> +	(q)->cnt_ ## op++;						\
>> +})
>> +
>> +#define log_vb_qop(vb, op, args...)					\
>> +	dprintk(2, "call_vb_qop(%p, %d, %s)%s\n",			\
>> +		(vb)->vb2_queue, (vb)->index, #op,			\
>> +		(vb)->vb2_queue->ops->op ? "" : " (nop)")
>> +
>> +#define call_vb_qop(vb, op, args...)					\
>> +({									\
>> +	int err;							\
>> +									\
>> +	log_vb_qop(vb, op);						\
>> +	err = (vb)->vb2_queue->ops->op ?				\
>> +		(vb)->vb2_queue->ops->op(args) : 0;			\
>> +	if (!err)							\
>> +		(vb)->cnt_ ## op++;					\
>> +	err;								\
>> +})
>> +
>> +#define call_void_vb_qop(vb, op, args...)				\
>> +({									\
>> +	log_vb_qop(vb, op);						\
>> +	if ((vb)->vb2_queue->ops->op)					\
>> +		(vb)->vb2_queue->ops->op(args);				\
>> +	(vb)->cnt_ ## op++;						\
>> +})
>> +
>> +#else
>> +
>> +#define call_memop(vb, op, args...)					\
>> +	((vb)->vb2_queue->mem_ops->op ?					\
>> +		(vb)->vb2_queue->mem_ops->op(args) : 0)
>> +
>> +#define call_ptr_memop(vb, op, args...)					\
>> +	((vb)->vb2_queue->mem_ops->op ?					\
>> +		(vb)->vb2_queue->mem_ops->op(args) : NULL)
>> +
>> +#define call_void_memop(vb, op, args...)				\
>> +	do {								\
>> +		if ((vb)->vb2_queue->mem_ops->op)			\
>> +			(vb)->vb2_queue->mem_ops->op(args);		\
>> +	} while (0)
>> +
>> +#define call_qop(q, op, args...)					\
>> +	((q)->ops->op ? (q)->ops->op(args) : 0)
>> +
>> +#define call_void_qop(q, op, args...)					\
>> +	do {								\
>> +		if ((q)->ops->op)					\
>> +			(q)->ops->op(args);				\
>> +	} while (0)
>> +
>> +#define call_vb_qop(vb, op, args...)					\
>> +	((vb)->vb2_queue->ops->op ? (vb)->vb2_queue->ops->op(args) : 0)
>> +
>> +#define call_void_vb_qop(vb, op, args...)				\
>> +	do {								\
>> +		if ((vb)->vb2_queue->ops->op)				\
>> +			(vb)->vb2_queue->ops->op(args);			\
>> +	} while (0)
>> +
>> +#endif
>> +
>> +#define call_bufop(q, op, args...)					\
>> +({									\
>> +	int ret = 0;							\
>> +	if (q && q->buf_ops && q->buf_ops->op)				\
>> +		ret = q->buf_ops->op(args);				\
>> +	ret;								\
>> +})
>> +
>> +bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb);
>> +int vb2_verify_memory_type(struct vb2_queue *q,
>> +		unsigned int memory, unsigned int type);
>> +int vb2_verify_buffer(struct vb2_queue *q,
>> +			unsigned int memory, unsigned int type,
>> +			unsigned int index, unsigned int nplanes,
>> +			void *pplane, const char *opname);
>> +void vb2_warn_zero_bytesused(struct vb2_buffer *vb);
>> +
>> +int vb2_core_querybuf(struct vb2_queue *q, unsigned int index, void *pb);
>> +int vb2_core_reqbufs(struct vb2_queue *q, unsigned int memory,
>> +		unsigned int *count);
>> +int vb2_core_create_bufs(struct vb2_queue *q, unsigned int memory,
>> +		unsigned int *count, void *parg);
>> +int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb);
>> +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb);
>> +int vb2_core_dqbuf(struct vb2_queue *q, void *pb, bool nonblock);
>> +int vb2_core_expbuf(struct vb2_queue *q, int *fd, unsigned int type,
>> +		unsigned int index, unsigned int plane, unsigned int flags);
>> +int vb2_core_streamon(struct vb2_queue *q);
>> +int vb2_core_streamoff(struct vb2_queue *q);
>> +int vb2_core_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
>> +
>> +int __must_check vb2_core_queue_init(struct vb2_queue *q);
>> +void vb2_core_queue_release(struct vb2_queue *q);
>> +
>> +#endif /* _MEDIA_VIDEOBUF2_INTERNAL_H */
>> diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> index 2f2b738..9fc6bef 100644
>> --- a/drivers/media/v4l2-core/videobuf2-v4l2.c
>> +++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
>> @@ -24,8 +24,1648 @@
>>   #include <linux/freezer.h>
>>   #include <linux/kthread.h>
>>
>> +#include <media/v4l2-dev.h>
>> +#include <media/v4l2-fh.h>
>> +#include <media/v4l2-event.h>
>> +#include <media/v4l2-common.h>
>>   #include <media/videobuf2-v4l2.h>
>>
>> +#include "videobuf2-internal.h"
>> +
>> +/* Flags that are set by the vb2 core */
>> +#define V4L2_BUFFER_MASK_FLAGS	(V4L2_BUF_FLAG_MAPPED | \
>> +				V4L2_BUF_FLAG_QUEUED | \
>> +				V4L2_BUF_FLAG_DONE | \
>> +				V4L2_BUF_FLAG_ERROR | \
>> +				V4L2_BUF_FLAG_PREPARED | \
>> +				V4L2_BUF_FLAG_TIMESTAMP_MASK)
>> +
>> +/* Output buffer flags that should be passed on to the driver */
>> +#define V4L2_BUFFER_OUT_FLAGS	(V4L2_BUF_FLAG_PFRAME | \
>> +				V4L2_BUF_FLAG_BFRAME | \
>> +				V4L2_BUF_FLAG_KEYFRAME | \
>> +				V4L2_BUF_FLAG_TIMECODE)
>> +
>> +/**
>> + * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
>> + * returned to userspace
>> + */
>> +static int __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
>> +{
>> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +	struct vb2_queue *q = vb->vb2_queue;
>> +	unsigned int plane;
>> +
>> +	/* Copy back data such as timestamp, flags, etc. */
>> +	b->index = vb->index;
>> +	b->type = vb->type;
>> +	b->memory = vb->memory;
>> +	b->bytesused = 0;
>> +
>> +	b->flags = vbuf->flags;
>> +	b->field = vbuf->field;
>> +	b->timestamp = vbuf->timestamp;
>> +	b->timecode = vbuf->timecode;
>> +	b->sequence = vbuf->sequence;
>> +
>> +	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>> +		/*
>> +		 * Fill in plane-related data if userspace provided an array
>> +		 * for it. The caller has already verified memory and size.
>> +		 */
>> +		b->length = vb->num_planes;
>> +		for (plane = 0; plane < vb->num_planes; ++plane) {
>> +			struct v4l2_plane *pdst = &b->m.planes[plane];
>> +			struct vb2_plane *psrc = &vb->planes[plane];
>> +
>> +			pdst->bytesused = psrc->bytesused;
>> +			pdst->length = psrc->length;
>> +			if (q->memory == V4L2_MEMORY_MMAP)
>> +				pdst->m.mem_offset = psrc->m.offset;
>> +			else if (q->memory == V4L2_MEMORY_USERPTR)
>> +				pdst->m.userptr = psrc->m.userptr;
>> +			else if (q->memory == V4L2_MEMORY_DMABUF)
>> +				pdst->m.fd = psrc->m.fd;
>> +			pdst->data_offset = psrc->data_offset;
>> +		}
>> +	} else {
>> +		/*
>> +		 * We use length and offset in v4l2_planes array even for
>> +		 * single-planar buffers, but userspace does not.
>> +		 */
>> +		b->length = vb->planes[0].length;
>> +		b->bytesused = vb->planes[0].bytesused;
>> +		if (q->memory == V4L2_MEMORY_MMAP)
>> +			b->m.offset = vb->planes[0].m.offset;
>> +		else if (q->memory == V4L2_MEMORY_USERPTR)
>> +			b->m.userptr = vb->planes[0].m.userptr;
>> +		else if (q->memory == V4L2_MEMORY_DMABUF)
>> +			b->m.fd = vb->planes[0].m.fd;
>> +	}
>> +
>> +	/*
>> +	 * Clear any buffer state related flags.
>> +	 */
>> +	b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>> +	b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>> +		/*
>> +		 * For non-COPY timestamps, drop timestamp source bits
>> +		 * and obtain the timestamp source from the queue.
>> +		 */
>> +		b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> +		b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> +	}
>> +
>> +	switch (vb->state) {
>> +	case VB2_BUF_STATE_QUEUED:
>> +	case VB2_BUF_STATE_ACTIVE:
>> +		b->flags |= V4L2_BUF_FLAG_QUEUED;
>> +		break;
>> +	case VB2_BUF_STATE_ERROR:
>> +		b->flags |= V4L2_BUF_FLAG_ERROR;
>> +		/* fall through */
>> +	case VB2_BUF_STATE_DONE:
>> +		b->flags |= V4L2_BUF_FLAG_DONE;
>> +		break;
>> +	case VB2_BUF_STATE_PREPARED:
>> +		b->flags |= V4L2_BUF_FLAG_PREPARED;
>> +		break;
>> +	case VB2_BUF_STATE_PREPARING:
>> +	case VB2_BUF_STATE_DEQUEUED:
>> +		/* nothing */
>> +		break;
>> +	}
>> +
>> +	if (vb2_buffer_in_use(q, vb))
>> +		b->flags |= V4L2_BUF_FLAG_MAPPED;
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * __verify_length() - Verify that the bytesused value for each plane fits in
>> + * the plane length and that the data offset doesn't exceed the bytesused value.
>> + */
>> +static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
>> +{
>> +	unsigned int length;
>> +	unsigned int bytesused;
>> +	unsigned int plane;
>> +
>> +	if (!V4L2_TYPE_IS_OUTPUT(b->type))
>> +		return 0;
>> +
>> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>> +		for (plane = 0; plane < vb->num_planes; ++plane) {
>> +			length = (b->memory == V4L2_MEMORY_USERPTR ||
>> +				b->memory == V4L2_MEMORY_DMABUF)
>> +				? b->m.planes[plane].length
>> +				: vb->planes[plane].length;
>> +			bytesused = b->m.planes[plane].bytesused
>> +				? b->m.planes[plane].bytesused : length;
>> +
>> +			if (b->m.planes[plane].bytesused > length)
>> +				return -EINVAL;
>> +
>> +			if (b->m.planes[plane].data_offset > 0 &&
>> +				b->m.planes[plane].data_offset >= bytesused)
>> +				return -EINVAL;
>> +		}
>> +	} else {
>> +		length = (b->memory == V4L2_MEMORY_USERPTR)
>> +			? b->length : vb->planes[0].length;
>> +
>> +		if (b->bytesused > length)
>> +			return -EINVAL;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
>> + * v4l2_buffer by the userspace. It also verifies that struct
>> + * v4l2_buffer has a valid number of planes.
>> + */
>> +static int __fill_vb2_buffer(struct vb2_buffer *vb, void *pb,
>> +				struct vb2_plane *planes)
>> +{
>> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +	unsigned int plane;
>> +	int ret;
>> +
>> +	ret = __verify_length(vb, b);
>> +	if (ret < 0) {
>> +		dprintk(1, "plane parameters verification failed: %d\n", ret);
>> +		return ret;
>> +	}
>> +	vb->state = VB2_BUF_STATE_PREPARING;
>> +	vbuf->timestamp.tv_sec = 0;
>> +	vbuf->timestamp.tv_usec = 0;
>> +	vbuf->sequence = 0;
>> +
>> +	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
>> +		if (b->memory == V4L2_MEMORY_USERPTR) {
>> +			for (plane = 0; plane < vb->num_planes; ++plane) {
>> +				planes[plane].m.userptr =
>> +					b->m.planes[plane].m.userptr;
>> +				planes[plane].length =
>> +					b->m.planes[plane].length;
>> +			}
>> +		}
>> +		if (b->memory == V4L2_MEMORY_DMABUF) {
>> +			for (plane = 0; plane < vb->num_planes; ++plane) {
>> +				planes[plane].m.fd =
>> +					b->m.planes[plane].m.fd;
>> +				planes[plane].length =
>> +					b->m.planes[plane].length;
>> +			}
>> +		}
>> +
>> +		/* Fill in driver-provided information for OUTPUT types */
>> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> +			/*
>> +			 * Will have to go up to b->length when API starts
>> +			 * accepting variable number of planes.
>> +			 *
>> +			 * If bytesused == 0 for the output buffer, then fall
>> +			 * back to the full buffer size. In that case
>> +			 * userspace clearly never bothered to set it and
>> +			 * it's a safe assumption that they really meant to
>> +			 * use the full plane sizes.
>> +			 *
>> +			 * Some drivers, e.g. old codec drivers, use bytesused == 0
>> +			 * as a way to indicate that streaming is finished.
>> +			 * In that case, the driver should use the
>> +			 * allow_zero_bytesused flag to keep old userspace
>> +			 * applications working.
>> +			 */
>> +			for (plane = 0; plane < vb->num_planes; ++plane) {
>> +				struct vb2_plane *pdst = &planes[plane];
>> +				struct v4l2_plane *psrc = &b->m.planes[plane];
>> +
>> +				if (psrc->bytesused == 0)
>> +					vb2_warn_zero_bytesused(vb);
>> +
>> +				if (vb->vb2_queue->allow_zero_bytesused)
>> +					pdst->bytesused = psrc->bytesused;
>> +				else
>> +					pdst->bytesused = psrc->bytesused ?
>> +						psrc->bytesused : pdst->length;
>> +				pdst->data_offset = psrc->data_offset;
>> +			}
>> +		}
>> +	} else {
>> +		/*
>> +		 * Single-planar buffers do not use planes array,
>> +		 * so fill in relevant v4l2_buffer struct fields instead.
>> +		 * In videobuf we use our internal V4l2_planes struct for
>> +		 * single-planar buffers as well, for simplicity.
>> +		 *
>> +		 * If bytesused == 0 for the output buffer, then fall back
>> +		 * to the full buffer size as that's a sensible default.
>> +		 *
>> +		 * Some drivers, e.g. old codec drivers, use bytesused == 0 as
>> +		 * a way to indicate that streaming is finished. In that case,
>> +		 * the driver should use the allow_zero_bytesused flag to keep
>> +		 * old userspace applications working.
>> +		 */
>> +		if (b->memory == V4L2_MEMORY_USERPTR) {
>> +			planes[0].m.userptr = b->m.userptr;
>> +			planes[0].length = b->length;
>> +		}
>> +
>> +		if (b->memory == V4L2_MEMORY_DMABUF) {
>> +			planes[0].m.fd = b->m.fd;
>> +			planes[0].length = b->length;
>> +		}
>> +
>> +		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> +			if (b->bytesused == 0)
>> +				vb2_warn_zero_bytesused(vb);
>> +
>> +			if (vb->vb2_queue->allow_zero_bytesused)
>> +				planes[0].bytesused = b->bytesused;
>> +			else
>> +				planes[0].bytesused = b->bytesused ?
>> +					b->bytesused : planes[0].length;
>> +		} else
>> +			planes[0].bytesused = 0;
>> +
>> +	}
>> +
>> +	/* Zero flags that the vb2 core handles */
>> +	vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS;
>> +	if ((vb->vb2_queue->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY ||
>> +			!V4L2_TYPE_IS_OUTPUT(b->type)) {
>> +		/*
>> +		 * Non-COPY timestamps and non-OUTPUT queues will get
>> +		 * their timestamp and timestamp source flags from the
>> +		 * queue.
>> +		 */
>> +		vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
>> +	}
>> +
>> +	if (V4L2_TYPE_IS_OUTPUT(b->type)) {
>> +		/*
>> +		 * For output buffers mask out the timecode flag:
>> +		 * this will be handled later in vb2_internal_qbuf().
>> +		 * The 'field' is valid metadata for this output buffer
>> +		 * and so that needs to be copied here.
>> +		 */
>> +		vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE;
>> +		vbuf->field = b->field;
>> +	} else {
>> +		/* Zero any output buffer flags as this is a capture buffer */
>> +		vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int __fill_vb2_timestamp(struct vb2_buffer *vb, void *pb)
>> +{
>> +	struct v4l2_buffer *b = (struct v4l2_buffer *)pb;
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +	struct vb2_queue *q = vb->vb2_queue;
>> +
>> +	/*
>> +	 * For output buffers copy the timestamp if needed,
>> +	 * and the timecode field and flag if needed.
>> +	 */
>> +	if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY)
>> +		vbuf->timestamp = b->timestamp;
>> +	vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE;
>> +	if (b->flags & V4L2_BUF_FLAG_TIMECODE)
>> +		vbuf->timecode = b->timecode;
>> +
>> +	return 0;
>> +};
>> +
>> +static int __is_last(struct vb2_buffer *vb)
>> +{
>> +	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> +
>> +	return (vbuf->flags & V4L2_BUF_FLAG_LAST);
>> +}
>> +
>> +const struct vb2_buf_ops v4l2_buf_ops = {
>> +	.fill_user_buffer	= __fill_v4l2_buffer,
>> +	.fill_vb2_buffer	= __fill_vb2_buffer,
>> +	.fill_vb2_timestamp	= __fill_vb2_timestamp,
>> +	.is_last		= __is_last,
>> +};
>> +
>> +/**
>> + * vb2_querybuf() - query video buffer information
>> + * @q:		videobuf queue
>> + * @b:		buffer struct passed from userspace to vidioc_querybuf handler
>> + *		in driver
>> + *
>> + * Should be called from vidioc_querybuf ioctl handler in driver.
>> + * This function will verify the passed v4l2_buffer structure and fill the
>> + * relevant information for the userspace.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_querybuf handler in driver.
>> + */
>> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +{
>> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
>> +			b->length, b->m.planes, "querybuf");
>> +
>> +	return ret ? ret : vb2_core_querybuf(q, b->index, b);
>> +}
>> +EXPORT_SYMBOL(vb2_querybuf);
>> +
>> +/**
>> + * vb2_reqbufs() - Wrapper for vb2_core_reqbufs() that also verifies
>> + * the memory and type values.
>> + * @q:		videobuf2 queue
>> + * @req:	struct passed from userspace to vidioc_reqbufs handler
>> + *		in driver
>> + */
>> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
>> +{
>> +	int ret = vb2_verify_memory_type(q, req->memory, req->type);
>> +
>> +	if (ret)
>> +		return ret;
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_core_reqbufs(q, req->memory, &req->count);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_reqbufs);
>> +
>> +/**
>> + * vb2_create_bufs() - Wrapper for vb2_core_create_bufs() that also verifies
>> + * the memory and type values.
>> + * @q:		videobuf2 queue
>> + * @create:	creation parameters, passed from userspace to vidioc_create_bufs
>> + *		handler in driver
>> + */
>> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create)
>> +{
>> +	int ret = vb2_verify_memory_type(q, create->memory, create->format.type);
>> +
>> +	if (ret)
>> +		return ret;
>> +	if (create->count && vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +	return vb2_core_create_bufs(q, create->memory, &create->count, &create->format);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_create_bufs);
>> +
>> +/**
>> + * vb2_prepare_buf() - Pass ownership of a buffer from userspace to the kernel
>> + * @q:		videobuf2 queue
>> + * @b:		buffer structure passed from userspace to vidioc_prepare_buf
>> + *		handler in driver
>> + *
>> + * Should be called from vidioc_prepare_buf ioctl handler of a driver.
>> + * This function:
>> + * 1) verifies the passed buffer,
>> + * 2) calls buf_prepare callback in the driver (if provided), in which
>> + *    driver-specific buffer initialization can be performed,
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_prepare_buf handler in driver.
>> + */
>> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +{
>> +	int ret;
>> +
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
>> +			b->length, b->m.planes, "prepare_buf");
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
>> +		/*
>> +		 * If the format's field is ALTERNATE, then the buffer's field
>> +		 * should be either TOP or BOTTOM, not ALTERNATE since that
>> +		 * makes no sense. The driver has to know whether the
>> +		 * buffer represents a top or a bottom field in order to
>> +		 * program any DMA correctly. Using ALTERNATE is wrong, since
>> +		 * that just says that it is either a top or a bottom field,
>> +		 * but not which of the two it is.
>> +		 */
>> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
>> +				"for an output buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	return vb2_core_prepare_buf(q, b->index, b);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_prepare_buf);
>> +
>> +static int vb2_internal_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +{
>> +	int ret = vb2_verify_buffer(q, b->memory, b->type, b->index,
>> +			b->length, b->m.planes, "qbuf");
>> +	struct vb2_buffer *vb;
>> +
>> +	if (ret)
>> +		return ret;
>> +
>> +	vb = q->bufs[b->index];
>> +
>> +	if (vb->state == VB2_BUF_STATE_DEQUEUED
>> +			&& b->field == V4L2_FIELD_ALTERNATE && q->is_output) {
>> +		dprintk(1, "the field is incorrectly set to ALTERNATE "
>> +				"for an output buffer\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	return ret ? ret : vb2_core_qbuf(q, b->index, b);
>> +}
>> +
>> +/**
>> + * vb2_qbuf() - Queue a buffer from userspace
>> + * @q:		videobuf2 queue
>> + * @b:		buffer structure passed from userspace to vidioc_qbuf handler
>> + *		in driver
>> + *
>> + * Should be called from vidioc_qbuf ioctl handler of a driver.
>> + * This function:
>> + * 1) verifies the passed buffer,
>> + * 2) if necessary, calls buf_prepare callback in the driver (if provided), in
>> + *    which driver-specific buffer initialization can be performed,
>> + * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
>> + *    callback for processing.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_qbuf handler in driver.
>> + */
>> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_internal_qbuf(q, b);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_qbuf);
>> +
>> +static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b,
>> +			bool nonblocking)
>> +{
>> +	if (b->type != q->type) {
>> +		dprintk(1, "invalid buffer type\n");
>> +		return -EINVAL;
>> +	}
>> +	return vb2_core_dqbuf(q, b, nonblocking);
>> +}
>> +
>> +/**
>> + * vb2_dqbuf() - Dequeue a buffer to the userspace
>> + * @q:		videobuf2 queue
>> + * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
>> + *		in driver
>> + * @nonblocking: if true, this call will not sleep waiting for a buffer if no
>> + *		 buffers ready for dequeuing are present. Normally the driver
>> + *		 would be passing (file->f_flags & O_NONBLOCK) here
>> + *
>> + * Should be called from vidioc_dqbuf ioctl handler of a driver.
>> + * This function:
>> + * 1) verifies the passed buffer,
>> + * 2) calls buf_finish callback in the driver (if provided), in which
>> + *    driver can perform any additional operations that may be required before
>> + *    returning the buffer to userspace, such as cache sync,
>> + * 3) the buffer struct members are filled with relevant information for
>> + *    the userspace.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_dqbuf handler in driver.
>> + */
>> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +	return vb2_internal_dqbuf(q, b, nonblocking);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_dqbuf);
>> +
>> +/**
>> + * vb2_expbuf() - Export a buffer as a file descriptor
>> + * @q:		videobuf2 queue
>> + * @eb:		export buffer structure passed from userspace to vidioc_expbuf
>> + *		handler in driver
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_expbuf handler in driver.
>> + */
>> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index,
>> +				eb->plane, eb->flags);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_expbuf);
>> +
>> +static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>> +{
>> +	if (type != q->type) {
>> +		dprintk(1, "invalid stream type\n");
>> +		return -EINVAL;
>> +	}
>> +	return vb2_core_streamon(q);
>> +}
>> +
>> +/**
>> + * vb2_streamon - start streaming
>> + * @q:		videobuf2 queue
>> + * @type:	type argument passed from userspace to vidioc_streamon handler
>> + *
>> + * Should be called from vidioc_streamon handler of a driver.
>> + * This function:
>> + * 1) verifies current state
>> + * 2) passes any previously queued buffers to the driver and starts streaming
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_streamon handler in the driver.
>> + */
>> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +	return vb2_internal_streamon(q, type);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_streamon);
>> +
>> +static int vb2_internal_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>> +{
>> +	if (type != q->type) {
>> +		dprintk(1, "invalid stream type\n");
>> +		return -EINVAL;
>> +	}
>> +	return vb2_core_streamoff(q);
>> +}
>> +
>> +/**
>> + * vb2_streamoff - stop streaming
>> + * @q:		videobuf2 queue
>> + * @type:	type argument passed from userspace to vidioc_streamoff handler
>> + *
>> + * Should be called from vidioc_streamoff handler of a driver.
>> + * This function:
>> + * 1) verifies current state,
>> + * 2) stop streaming and dequeues any queued buffers, including those previously
>> + *    passed to the driver (after waiting for the driver to finish).
>> + *
>> + * This call can be used for pausing playback.
>> + * The return values from this function are intended to be directly returned
>> + * from vidioc_streamoff handler in the driver
>> + */
>> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +	return vb2_internal_streamoff(q, type);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_streamoff);
>> +
>> +/**
>> + * vb2_mmap() - map video buffers into application address space
>> + * @q:		videobuf2 queue
>> + * @vma:	vma passed to the mmap file operation handler in the driver
>> + *
>> + * Should be called from mmap file operation handler of a driver.
>> + * This function maps one plane of one of the available video buffers to
>> + * userspace. To map whole video memory allocated on reqbufs, this function
>> + * has to be called once per each plane per each buffer previously allocated.
>> + *
>> + * When the userspace application calls mmap, it passes to it an offset returned
>> + * to it earlier by the means of vidioc_querybuf handler. That offset acts as
>> + * a "cookie", which is then used to identify the plane to be mapped.
>> + * This function finds a plane with a matching offset and a mapping is performed
>> + * by the means of a provided memory operation.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from the mmap handler in driver.
>> + */
>> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
>> +{
>> +	if (vb2_fileio_is_active(q)) {
>> +		dprintk(1, "mmap: file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_core_mmap(q, vma);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_mmap);
>> +
>> +static int __vb2_init_fileio(struct vb2_queue *q, int read);
>> +static int __vb2_cleanup_fileio(struct vb2_queue *q);
>> +
>> +/**
>> + * vb2_poll() - implements poll userspace operation
>> + * @q:		videobuf2 queue
>> + * @file:	file argument passed to the poll file operation handler
>> + * @wait:	wait argument passed to the poll file operation handler
>> + *
>> + * This function implements poll file operation handler for a driver.
>> + * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
>> + * be informed that the file descriptor of a video device is available for
>> + * reading.
>> + * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
>> + * will be reported as available for writing.
>> + *
>> + * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any
>> + * pending events.
>> + *
>> + * The return values from this function are intended to be directly returned
>> + * from poll handler in driver.
>> + */
>> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
>> +{
>> +	struct video_device *vfd = video_devdata(file);
>> +	unsigned long req_events = poll_requested_events(wait);
>> +	struct vb2_buffer *vb = NULL;
>> +	unsigned int res = 0;
>> +	unsigned long flags;
>> +
>> +	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
>> +		struct v4l2_fh *fh = file->private_data;
>> +
>> +		if (v4l2_event_pending(fh))
>> +			res = POLLPRI;
>> +		else if (req_events & POLLPRI)
>> +			poll_wait(file, &fh->wait, wait);
>> +	}
>> +
>> +	if (!q->is_output && !(req_events & (POLLIN | POLLRDNORM)))
>> +		return res;
>> +	if (q->is_output && !(req_events & (POLLOUT | POLLWRNORM)))
>> +		return res;
>> +
>> +	/*
>> +	 * Start file I/O emulator only if streaming API has not been used yet.
>> +	 */
>> +	if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
>> +		if (!q->is_output && (q->io_modes & VB2_READ) &&
>> +				(req_events & (POLLIN | POLLRDNORM))) {
>> +			if (__vb2_init_fileio(q, 1))
>> +				return res | POLLERR;
>> +		}
>> +		if (q->is_output && (q->io_modes & VB2_WRITE) &&
>> +				(req_events & (POLLOUT | POLLWRNORM))) {
>> +			if (__vb2_init_fileio(q, 0))
>> +				return res | POLLERR;
>> +			/*
>> +			 * Write to OUTPUT queue can be done immediately.
>> +			 */
>> +			return res | POLLOUT | POLLWRNORM;
>> +		}
>> +	}
>> +
>> +	/*
>> +	 * There is nothing to wait for if the queue isn't streaming, or if the
>> +	 * error flag is set.
>> +	 */
>> +	if (!vb2_is_streaming(q) || q->error)
>> +		return res | POLLERR;
>> +	/*
>> +	 * For compatibility with vb1: if QBUF hasn't been called yet, then
>> +	 * return POLLERR as well. This only affects capture queues, output
>> +	 * queues will always initialize waiting_for_buffers to false.
>> +	 */
>> +	if (q->waiting_for_buffers)
>> +		return res | POLLERR;
>> +
>> +	/*
>> +	 * For output streams you can write as long as there are fewer buffers
>> +	 * queued than there are buffers available.
>> +	 */
>> +	if (q->is_output && q->queued_count < q->num_buffers)
>> +		return res | POLLOUT | POLLWRNORM;
>> +
>> +	if (list_empty(&q->done_list)) {
>> +		/*
>> +		 * If the last buffer was dequeued from a capture queue,
>> +		 * return immediately. DQBUF will return -EPIPE.
>> +		 */
>> +		if (q->last_buffer_dequeued)
>> +			return res | POLLIN | POLLRDNORM;
>> +
>> +		poll_wait(file, &q->done_wq, wait);
>> +	}
>> +
>> +	/*
>> +	 * Take first buffer available for dequeuing.
>> +	 */
>> +	spin_lock_irqsave(&q->done_lock, flags);
>> +	if (!list_empty(&q->done_list))
>> +		vb = list_first_entry(&q->done_list, struct vb2_buffer,
>> +					done_entry);
>> +	spin_unlock_irqrestore(&q->done_lock, flags);
>> +
>> +	if (vb && (vb->state == VB2_BUF_STATE_DONE
>> +			|| vb->state == VB2_BUF_STATE_ERROR)) {
>> +		return (q->is_output) ?
>> +				res | POLLOUT | POLLWRNORM :
>> +				res | POLLIN | POLLRDNORM;
>> +	}
>> +	return res;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_poll);
>> +
>> +/**
>> + * vb2_queue_init() - initialize a videobuf2 queue
>> + * @q:		videobuf2 queue; this structure should be allocated in driver
>> + *
>> + * The vb2_queue structure should be allocated by the driver. The driver is
>> + * responsible of clearing it's content and setting initial values for some
>> + * required entries before calling this function.
>> + * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
>> + * to the struct vb2_queue description in include/media/videobuf2-core.h
>> + * for more information.
>> + */
>> +int vb2_queue_init(struct vb2_queue *q)
>> +{
>> +	if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP)
>> +		|| WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR)
>> +		|| WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF))
>> +		return -EINVAL;
>> +	/*
>> +	 * Sanity check
>> +	 */
>> +	if (WARN_ON(!q)	|| WARN_ON(!q->type))
>> +		return -EINVAL;
>> +
>> +	if (WARN_ON(q->timestamp_flags &
>> +		    ~(V4L2_BUF_FLAG_TIMESTAMP_MASK |
>> +		      V4L2_BUF_FLAG_TSTAMP_SRC_MASK)))
>> +		return -EINVAL;
>> +
>> +	/* Warn that the driver should choose an appropriate timestamp type */
>> +	WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> +		V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN);
>> +
>> +	if (q->buf_struct_size == 0)
>> +		q->buf_struct_size = sizeof(struct vb2_v4l2_buffer);
>> +
>> +	q->buf_ops = &v4l2_buf_ops;
>> +	q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type);
>> +	q->is_output = V4L2_TYPE_IS_OUTPUT(q->type);
>> +
>> +	return vb2_core_queue_init(q);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_queue_init);
>> +
>> +/**
>> + * vb2_queue_release() - stop streaming, release the queue and free memory
>> + * @q:		videobuf2 queue
>> + *
>> + * This function stops streaming and performs necessary clean ups, including
>> + * freeing video buffer memory. The driver is responsible for freeing
>> + * the vb2_queue structure itself.
>> + */
>> +void vb2_queue_release(struct vb2_queue *q)
>> +{
>> +	__vb2_cleanup_fileio(q);
>> +	vb2_core_queue_release(q);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_queue_release);
>> +
>> +/**
>> + * struct vb2_fileio_buf - buffer context used by file io emulator
>> + *
>> + * vb2 provides a compatibility layer and emulator of file io (read and
>> + * write) calls on top of streaming API. This structure is used for
>> + * tracking context related to the buffers.
>> + */
>> +struct vb2_fileio_buf {
>> +	void *vaddr;
>> +	unsigned int size;
>> +	unsigned int pos;
>> +	unsigned int queued:1;
>> +};
>> +
>> +/**
>> + * struct vb2_fileio_data - queue context used by file io emulator
>> + *
>> + * @cur_index:	the index of the buffer currently being read from or
>> + *		written to. If equal to q->num_buffers then a new buffer
>> + *		must be dequeued.
>> + * @initial_index: in the read() case all buffers are queued up immediately
>> + *		in __vb2_init_fileio() and __vb2_perform_fileio() just cycles
>> + *		buffers. However, in the write() case no buffers are initially
>> + *		queued, instead whenever a buffer is full it is queued up by
>> + *		__vb2_perform_fileio(). Only once all available buffers have
>> + *		been queued up will __vb2_perform_fileio() start to dequeue
>> + *		buffers. This means that initially __vb2_perform_fileio()
>> + *		needs to know what buffer index to use when it is queuing up
>> + *		the buffers for the first time. That initial index is stored
>> + *		in this field. Once it is equal to q->num_buffers all
>> + *		available buffers have been queued and __vb2_perform_fileio()
>> + *		should start the normal dequeue/queue cycle.
>> + *
>> + * vb2 provides a compatibility layer and emulator of file io (read and
>> + * write) calls on top of streaming API. For proper operation it required
>> + * this structure to save the driver state between each call of the read
>> + * or write function.
>> + */
>> +struct vb2_fileio_data {
>> +	struct v4l2_requestbuffers req;
>> +	struct v4l2_plane p;
>> +	struct v4l2_buffer b;
>> +	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
>> +	unsigned int cur_index;
>> +	unsigned int initial_index;
>> +	unsigned int q_count;
>> +	unsigned int dq_count;
>> +	unsigned read_once:1;
>> +	unsigned write_immediately:1;
>> +};
>> +
>> +/**
>> + * __vb2_init_fileio() - initialize file io emulator
>> + * @q:		videobuf2 queue
>> + * @read:	mode selector (1 means read, 0 means write)
>> + */
>> +static int __vb2_init_fileio(struct vb2_queue *q, int read)
>> +{
>> +	struct vb2_fileio_data *fileio;
>> +	int i, ret;
>> +	unsigned int count = 0;
>> +
>> +	/*
>> +	 * Sanity check
>> +	 */
>> +	if (WARN_ON((read && !(q->io_modes & VB2_READ)) ||
>> +			(!read && !(q->io_modes & VB2_WRITE))))
>> +		return -EINVAL;
>> +
>> +	/*
>> +	 * Check if device supports mapping buffers to kernel virtual space.
>> +	 */
>> +	if (!q->mem_ops->vaddr)
>> +		return -EBUSY;
>> +
>> +	/*
>> +	 * Check if streaming api has not been already activated.
>> +	 */
>> +	if (q->streaming || q->num_buffers > 0)
>> +		return -EBUSY;
>> +
>> +	/*
>> +	 * Start with count 1, driver can increase it in queue_setup()
>> +	 */
>> +	count = 1;
>> +
>> +	dprintk(3, "setting up file io: mode %s, count %d, read_once %d, "
>> +		"write_immediately %d\n",
>> +		(read) ? "read" : "write", count, q->fileio_read_once,
>> +		q->fileio_write_immediately);
>> +
>> +	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
>> +	if (fileio == NULL)
>> +		return -ENOMEM;
>> +
>> +	fileio->read_once = q->fileio_read_once;
>> +	fileio->write_immediately = q->fileio_write_immediately;
>> +
>> +	/*
>> +	 * Request buffers and use MMAP type to force driver
>> +	 * to allocate buffers by itself.
>> +	 */
>> +	fileio->req.count = count;
>> +	fileio->req.memory = V4L2_MEMORY_MMAP;
>> +	fileio->req.type = q->type;
>> +	q->fileio = fileio;
>> +	ret = vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
>> +	if (ret)
>> +		goto err_kfree;
>> +
>> +	/*
>> +	 * Check if plane_count is correct
>> +	 * (multiplane buffers are not supported).
>> +	 */
>> +	if (q->bufs[0]->num_planes != 1) {
>> +		ret = -EBUSY;
>> +		goto err_reqbufs;
>> +	}
>> +
>> +	/*
>> +	 * Get kernel address of each buffer.
>> +	 */
>> +	for (i = 0; i < q->num_buffers; i++) {
>> +		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
>> +		if (fileio->bufs[i].vaddr == NULL) {
>> +			ret = -EINVAL;
>> +			goto err_reqbufs;
>> +		}
>> +		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
>> +	}
>> +
>> +	/*
>> +	 * Read mode requires pre queuing of all buffers.
>> +	 */
>> +	if (read) {
>> +		bool is_multiplanar = q->is_multiplanar;
>> +
>> +		/*
>> +		 * Queue all buffers.
>> +		 */
>> +		for (i = 0; i < q->num_buffers; i++) {
>> +			struct v4l2_buffer *b = &fileio->b;
>> +
>> +			memset(b, 0, sizeof(*b));
>> +			b->type = q->type;
>> +			if (is_multiplanar) {
>> +				memset(&fileio->p, 0, sizeof(fileio->p));
>> +				b->m.planes = &fileio->p;
>> +				b->length = 1;
>> +			}
>> +			b->memory = q->memory;
>> +			b->index = i;
>> +			ret = vb2_internal_qbuf(q, b);
>> +			if (ret)
>> +				goto err_reqbufs;
>> +			fileio->bufs[i].queued = 1;
>> +		}
>> +		/*
>> +		 * All buffers have been queued, so mark that by setting
>> +		 * initial_index to q->num_buffers
>> +		 */
>> +		fileio->initial_index = q->num_buffers;
>> +		fileio->cur_index = q->num_buffers;
>> +	}
>> +
>> +	/*
>> +	 * Start streaming.
>> +	 */
>> +	ret = vb2_internal_streamon(q, q->type);
>> +	if (ret)
>> +		goto err_reqbufs;
>> +
>> +	return ret;
>> +
>> +err_reqbufs:
>> +	fileio->req.count = 0;
>> +	vb2_core_reqbufs(q, fileio->req.memory, &fileio->req.count);
>> +
>> +err_kfree:
>> +	q->fileio = NULL;
>> +	kfree(fileio);
>> +	return ret;
>> +}
>> +
>> +/**
>> + * __vb2_cleanup_fileio() - free resourced used by file io emulator
>> + * @q:		videobuf2 queue
>> + */
>> +static int __vb2_cleanup_fileio(struct vb2_queue *q)
>> +{
>> +	struct vb2_fileio_data *fileio = q->fileio;
>> +
>> +	if (fileio) {
>> +		vb2_internal_streamoff(q, q->type);
>> +		q->fileio = NULL;
>> +		fileio->req.count = 0;
>> +		vb2_reqbufs(q, &fileio->req);
>> +		kfree(fileio);
>> +		dprintk(3, "file io emulator closed\n");
>> +	}
>> +	return 0;
>> +}
>> +
>> +/**
>> + * __vb2_perform_fileio() - perform a single file io (read or write) operation
>> + * @q:		videobuf2 queue
>> + * @data:	pointed to target userspace buffer
>> + * @count:	number of bytes to read or write
>> + * @ppos:	file handle position tracking pointer
>> + * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
>> + * @read:	access mode selector (1 means read, 0 means write)
>> + */
>> +static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data,
>> +		size_t count, loff_t *ppos, int nonblock, int read)
>> +{
>> +	struct vb2_fileio_data *fileio;
>> +	struct vb2_fileio_buf *buf;
>> +	bool is_multiplanar = q->is_multiplanar;
>> +	/*
>> +	 * When using write() to write data to an output video node the vb2 core
>> +	 * should set timestamps if V4L2_BUF_FLAG_TIMESTAMP_COPY is set. Nobody
>> +	 * else is able to provide this information with the write() operation.
>> +	 */
>> +	bool set_timestamp = !read &&
>> +		(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> +		V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> +	int ret, index;
>> +
>> +	dprintk(3, "mode %s, offset %ld, count %zd, %sblocking\n",
>> +		read ? "read" : "write", (long)*ppos, count,
>> +		nonblock ? "non" : "");
>> +
>> +	if (!data)
>> +		return -EINVAL;
>> +
>> +	/*
>> +	 * Initialize emulator on first call.
>> +	 */
>> +	if (!vb2_fileio_is_active(q)) {
>> +		ret = __vb2_init_fileio(q, read);
>> +		dprintk(3, "vb2_init_fileio result: %d\n", ret);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +	fileio = q->fileio;
>> +
>> +	/*
>> +	 * Check if we need to dequeue the buffer.
>> +	 */
>> +	index = fileio->cur_index;
>> +	if (index >= q->num_buffers) {
>> +		/*
>> +		 * Call vb2_dqbuf to get buffer back.
>> +		 */
>> +		memset(&fileio->b, 0, sizeof(fileio->b));
>> +		fileio->b.type = q->type;
>> +		fileio->b.memory = q->memory;
>> +		if (is_multiplanar) {
>> +			memset(&fileio->p, 0, sizeof(fileio->p));
>> +			fileio->b.m.planes = &fileio->p;
>> +			fileio->b.length = 1;
>> +		}
>> +		ret = vb2_internal_dqbuf(q, &fileio->b, nonblock);
>> +		dprintk(5, "vb2_dqbuf result: %d\n", ret);
>> +		if (ret)
>> +			return ret;
>> +		fileio->dq_count += 1;
>> +
>> +		fileio->cur_index = index = fileio->b.index;
>> +		buf = &fileio->bufs[index];
>> +
>> +		/*
>> +		 * Get number of bytes filled by the driver
>> +		 */
>> +		buf->pos = 0;
>> +		buf->queued = 0;
>> +		buf->size = read ? vb2_get_plane_payload(q->bufs[index], 0)
>> +				 : vb2_plane_size(q->bufs[index], 0);
>> +
>> +		/*
>> +		 * Compensate for data_offset on read
>> +		 * in the multiplanar case.
>> +		 */
>> +		if (is_multiplanar && read &&
>> +			fileio->b.m.planes[0].data_offset < buf->size) {
>> +			buf->pos = fileio->b.m.planes[0].data_offset;
>> +			buf->size -= buf->pos;
>> +		}
>> +	} else {
>> +		buf = &fileio->bufs[index];
>> +	}
>> +
>> +	/*
>> +	 * Limit count on last few bytes of the buffer.
>> +	 */
>> +	if (buf->pos + count > buf->size) {
>> +		count = buf->size - buf->pos;
>> +		dprintk(5, "reducing read count: %zd\n", count);
>> +	}
>> +
>> +	/*
>> +	 * Transfer data to userspace.
>> +	 */
>> +	dprintk(3, "copying %zd bytes - buffer %d, offset %u\n",
>> +		count, index, buf->pos);
>> +	if (read)
>> +		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
>> +	else
>> +		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
>> +	if (ret) {
>> +		dprintk(3, "error copying data\n");
>> +		return -EFAULT;
>> +	}
>> +
>> +	/*
>> +	 * Update counters.
>> +	 */
>> +	buf->pos += count;
>> +	*ppos += count;
>> +
>> +	/*
>> +	 * Queue next buffer if required.
>> +	 */
>> +	if (buf->pos == buf->size || (!read && fileio->write_immediately)) {
>> +		/*
>> +		 * Check if this is the last buffer to read.
>> +		 */
>> +		if (read && fileio->read_once && fileio->dq_count == 1) {
>> +			dprintk(3, "read limit reached\n");
>> +			return __vb2_cleanup_fileio(q);
>> +		}
>> +
>> +		/*
>> +		 * Call vb2_qbuf and give buffer to the driver.
>> +		 */
>> +		memset(&fileio->b, 0, sizeof(fileio->b));
>> +		fileio->b.type = q->type;
>> +		fileio->b.memory = q->memory;
>> +		fileio->b.index = index;
>> +		fileio->b.bytesused = buf->pos;
>> +		if (is_multiplanar) {
>> +			memset(&fileio->p, 0, sizeof(fileio->p));
>> +			fileio->p.bytesused = buf->pos;
>> +			fileio->b.m.planes = &fileio->p;
>> +			fileio->b.length = 1;
>> +		}
>> +		if (set_timestamp)
>> +			v4l2_get_timestamp(&fileio->b.timestamp);
>> +		ret = vb2_internal_qbuf(q, &fileio->b);
>> +		dprintk(5, "vb2_dbuf result: %d\n", ret);
>> +		if (ret)
>> +			return ret;
>> +
>> +		/*
>> +		 * Buffer has been queued, update the status
>> +		 */
>> +		buf->pos = 0;
>> +		buf->queued = 1;
>> +		buf->size = vb2_plane_size(q->bufs[index], 0);
>> +		fileio->q_count += 1;
>> +		/*
>> +		 * If we are queuing up buffers for the first time, then
>> +		 * increase initial_index by one.
>> +		 */
>> +		if (fileio->initial_index < q->num_buffers)
>> +			fileio->initial_index++;
>> +		/*
>> +		 * The next buffer to use is either a buffer that's going to be
>> +		 * queued for the first time (initial_index < q->num_buffers)
>> +		 * or it is equal to q->num_buffers, meaning that the next
>> +		 * time we need to dequeue a buffer since we've now queued up
>> +		 * all the 'first time' buffers.
>> +		 */
>> +		fileio->cur_index = fileio->initial_index;
>> +	}
>> +
>> +	/*
>> +	 * Return proper number of bytes processed.
>> +	 */
>> +	if (ret == 0)
>> +		ret = count;
>> +	return ret;
>> +}
>> +
>> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
>> +		loff_t *ppos, int nonblocking)
>> +{
>> +	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_read);
>> +
>> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
>> +		loff_t *ppos, int nonblocking)
>> +{
>> +	return __vb2_perform_fileio(q, (char __user *) data, count,
>> +							ppos, nonblocking, 0);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_write);
>> +
>> +struct vb2_threadio_data {
>> +	struct task_struct *thread;
>> +	vb2_thread_fnc fnc;
>> +	void *priv;
>> +	bool stop;
>> +};
>> +
>> +static int vb2_thread(void *data)
>> +{
>> +	struct vb2_queue *q = data;
>> +	struct vb2_threadio_data *threadio = q->threadio;
>> +	struct vb2_fileio_data *fileio = q->fileio;
>> +	bool set_timestamp = false;
>> +	int prequeue = 0;
>> +	int index = 0;
>> +	int ret = 0;
>> +
>> +	if (q->is_output) {
>> +		prequeue = q->num_buffers;
>> +		set_timestamp =
>> +			(q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) ==
>> +			V4L2_BUF_FLAG_TIMESTAMP_COPY;
>> +	}
>> +
>> +	set_freezable();
>> +
>> +	for (;;) {
>> +		struct vb2_buffer *vb;
>> +
>> +		/*
>> +		 * Call vb2_dqbuf to get buffer back.
>> +		 */
>> +		memset(&fileio->b, 0, sizeof(fileio->b));
>> +		fileio->b.type = q->type;
>> +		fileio->b.memory = q->memory;
>> +		if (prequeue) {
>> +			fileio->b.index = index++;
>> +			prequeue--;
>> +		} else {
>> +			call_void_qop(q, wait_finish, q);
>> +			if (!threadio->stop)
>> +				ret = vb2_internal_dqbuf(q, &fileio->b, 0);
>> +			call_void_qop(q, wait_prepare, q);
>> +			dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
>> +		}
>> +		if (ret || threadio->stop)
>> +			break;
>> +		try_to_freeze();
>> +
>> +		vb = q->bufs[fileio->b.index];
>> +		if (!(fileio->b.flags & V4L2_BUF_FLAG_ERROR))
>> +			if (threadio->fnc(vb, threadio->priv))
>> +				break;
>> +		call_void_qop(q, wait_finish, q);
>> +		if (set_timestamp)
>> +			v4l2_get_timestamp(&fileio->b.timestamp);
>> +		if (!threadio->stop)
>> +			ret = vb2_internal_qbuf(q, &fileio->b);
>> +		call_void_qop(q, wait_prepare, q);
>> +		if (ret || threadio->stop)
>> +			break;
>> +	}
>> +
>> +	/* Hmm, linux becomes *very* unhappy without this ... */
>> +	while (!kthread_should_stop()) {
>> +		set_current_state(TASK_INTERRUPTIBLE);
>> +		schedule();
>> +	}
>> +	return 0;
>> +}
>> +
>> +/*
>> + * This function should not be used for anything else but the videobuf2-dvb
>> + * support. If you think you have another good use-case for this, then please
>> + * contact the linux-media mailinglist first.
>> + */
>> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
>> +			const char *thread_name)
>> +{
>> +	struct vb2_threadio_data *threadio;
>> +	int ret = 0;
>> +
>> +	if (q->threadio)
>> +		return -EBUSY;
>> +	if (vb2_is_busy(q))
>> +		return -EBUSY;
>> +	if (WARN_ON(q->fileio))
>> +		return -EBUSY;
>> +
>> +	threadio = kzalloc(sizeof(*threadio), GFP_KERNEL);
>> +	if (threadio == NULL)
>> +		return -ENOMEM;
>> +	threadio->fnc = fnc;
>> +	threadio->priv = priv;
>> +
>> +	ret = __vb2_init_fileio(q, !q->is_output);
>> +	dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
>> +	if (ret)
>> +		goto nomem;
>> +	q->threadio = threadio;
>> +	threadio->thread = kthread_run(vb2_thread, q, "vb2-%s", thread_name);
>> +	if (IS_ERR(threadio->thread)) {
>> +		ret = PTR_ERR(threadio->thread);
>> +		threadio->thread = NULL;
>> +		goto nothread;
>> +	}
>> +	return 0;
>> +
>> +nothread:
>> +	__vb2_cleanup_fileio(q);
>> +nomem:
>> +	kfree(threadio);
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_thread_start);
>> +
>> +int vb2_thread_stop(struct vb2_queue *q)
>> +{
>> +	struct vb2_threadio_data *threadio = q->threadio;
>> +	int err;
>> +
>> +	if (threadio == NULL)
>> +		return 0;
>> +	threadio->stop = true;
>> +	/* Wake up all pending sleeps in the thread */
>> +	vb2_queue_error(q);
>> +	err = kthread_stop(threadio->thread);
>> +	__vb2_cleanup_fileio(q);
>> +	threadio->thread = NULL;
>> +	kfree(threadio);
>> +	q->threadio = NULL;
>> +	return err;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_thread_stop);
>> +
>> +/*
>> + * The following functions are not part of the vb2 core API, but are helper
>> + * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations
>> + * and struct vb2_ops.
>> + * They contain boilerplate code that most if not all drivers have to do
>> + * and so they simplify the driver code.
>> + */
>> +
>> +/* The queue is busy if there is a owner and you are not that owner. */
>> +static inline
>> +bool vb2_queue_is_busy(struct video_device *vdev, struct file *file)
>> +{
>> +	return vdev->queue->owner && vdev->queue->owner != file->private_data;
>> +}
>> +
>> +/* vb2 ioctl helpers */
>> +
>> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
>> +			  struct v4l2_requestbuffers *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type);
>> +
>> +	if (res)
>> +		return res;
>> +	if (vb2_fileio_is_active(vdev->queue))
>> +		return -EBUSY;
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	res = vb2_core_reqbufs(vdev->queue, p->memory, &p->count);
>> +	/* If count == 0, then the owner has released all buffers and he
>> +	   is no longer owner of the queue. Otherwise we have a new owner. */
>> +	if (res == 0)
>> +		vdev->queue->owner = p->count ? file->private_data : NULL;
>> +	return res;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
>> +
>> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
>> +			  struct v4l2_create_buffers *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	int res = vb2_verify_memory_type(vdev->queue,
>> +				p->memory, p->format.type);
>> +
>> +	if (vb2_fileio_is_active(vdev->queue))
>> +		return -EBUSY;
>> +	p->index = vdev->queue->num_buffers;
>> +	/* If count == 0, then just check if memory and type are valid.
>> +	   Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. */
>> +	if (p->count == 0)
>> +		return res != -EBUSY ? res : 0;
>> +	if (res)
>> +		return res;
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	res = vb2_core_create_bufs(vdev->queue,
>> +				p->memory, &p->count, &p->format);
>> +	if (res == 0)
>> +		vdev->queue->owner = file->private_data;
>> +	return res;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
>> +
>> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
>> +			  struct v4l2_buffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_prepare_buf(vdev->queue, p);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
>> +
>> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	/* No need to call vb2_queue_is_busy(), anyone can query buffers. */
>> +	return vb2_querybuf(vdev->queue, p);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
>> +
>> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_qbuf(vdev->queue, p);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
>> +
>> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
>> +
>> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_streamon(vdev->queue, i);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
>> +
>> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_streamoff(vdev->queue, i);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
>> +
>> +int vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		return -EBUSY;
>> +	return vb2_expbuf(vdev->queue, p);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ioctl_expbuf);
>> +
>> +/* v4l2_file_operations helpers */
>> +
>> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (vb2_fileio_is_active(vdev->queue)) {
>> +		dprintk(1, "mmap: file io in progress\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	return vb2_mmap(vdev->queue, vma);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_mmap);
>> +
>> +int _vb2_fop_release(struct file *file, struct mutex *lock)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	if (lock)
>> +		mutex_lock(lock);
>> +	if (file->private_data == vdev->queue->owner) {
>> +		vb2_queue_release(vdev->queue);
>> +		vdev->queue->owner = NULL;
>> +	}
>> +	if (lock)
>> +		mutex_unlock(lock);
>> +	return v4l2_fh_release(file);
>> +}
>> +EXPORT_SYMBOL_GPL(_vb2_fop_release);
>> +
>> +int vb2_fop_release(struct file *file)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> +
>> +	return _vb2_fop_release(file, lock);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_release);
>> +
>> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>> +		size_t count, loff_t *ppos)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> +	int err = -EBUSY;
>> +
>> +	if (!(vdev->queue->io_modes & VB2_WRITE))
>> +		return -EINVAL;
>> +	if (lock && mutex_lock_interruptible(lock))
>> +		return -ERESTARTSYS;
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		goto exit;
>> +	err = vb2_write(vdev->queue, buf, count, ppos,
>> +			file->f_flags & O_NONBLOCK);
>> +	if (vdev->queue->fileio)
>> +		vdev->queue->owner = file->private_data;
>> +exit:
>> +	if (lock)
>> +		mutex_unlock(lock);
>> +	return err;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_write);
>> +
>> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
>> +		size_t count, loff_t *ppos)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
>> +	int err = -EBUSY;
>> +
>> +	if (!(vdev->queue->io_modes & VB2_READ))
>> +		return -EINVAL;
>> +	if (lock && mutex_lock_interruptible(lock))
>> +		return -ERESTARTSYS;
>> +	if (vb2_queue_is_busy(vdev, file))
>> +		goto exit;
>> +	err = vb2_read(vdev->queue, buf, count, ppos,
>> +			file->f_flags & O_NONBLOCK);
>> +	if (vdev->queue->fileio)
>> +		vdev->queue->owner = file->private_data;
>> +exit:
>> +	if (lock)
>> +		mutex_unlock(lock);
>> +	return err;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_read);
>> +
>> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +	struct vb2_queue *q = vdev->queue;
>> +	struct mutex *lock = q->lock ? q->lock : vdev->lock;
>> +	unsigned res;
>> +	void *fileio;
>> +
>> +	/*
>> +	 * If this helper doesn't know how to lock, then you shouldn't be using
>> +	 * it but you should write your own.
>> +	 */
>> +	WARN_ON(!lock);
>> +
>> +	if (lock && mutex_lock_interruptible(lock))
>> +		return POLLERR;
>> +
>> +	fileio = q->fileio;
>> +
>> +	res = vb2_poll(vdev->queue, file, wait);
>> +
>> +	/* If fileio was started, then we have a new queue owner. */
>> +	if (!fileio && q->fileio)
>> +		q->owner = file->private_data;
>> +	if (lock)
>> +		mutex_unlock(lock);
>> +	return res;
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_poll);
>> +
>> +#ifndef CONFIG_MMU
>> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>> +		unsigned long len, unsigned long pgoff, unsigned long flags)
>> +{
>> +	struct video_device *vdev = video_devdata(file);
>> +
>> +	return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
>> +#endif
>> +
>> +/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
>> +
>> +void vb2_ops_wait_prepare(struct vb2_queue *vq)
>> +{
>> +	mutex_unlock(vq->lock);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
>> +
>> +void vb2_ops_wait_finish(struct vb2_queue *vq)
>> +{
>> +	mutex_lock(vq->lock);
>> +}
>> +EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
>> +
>>   MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
>>   MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
>>   MODULE_LICENSE("GPL");
>> diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
>> index 09d7529..4044bed 100644
>> --- a/include/media/videobuf2-core.h
>> +++ b/include/media/videobuf2-core.h
>> @@ -15,9 +15,18 @@
>>   #include <linux/mm_types.h>
>>   #include <linux/mutex.h>
>>   #include <linux/poll.h>
>> -#include <linux/videodev2.h>
>>   #include <linux/dma-buf.h>
>>
>> +#define VB2_MAX_FRAME	(32)
>> +#define VB2_MAX_PLANES	(8)
>> +
>> +enum vb2_memory {
>> +	VB2_MEMORY_UNKNOWN	= 0,
>> +	VB2_MEMORY_MMAP		= 1,
>> +	VB2_MEMORY_USERPTR	= 2,
>> +	VB2_MEMORY_DMABUF	= 4,
>> +};
>> +
>>   struct vb2_alloc_ctx;
>>   struct vb2_fileio_data;
>>   struct vb2_threadio_data;
>> @@ -198,7 +207,7 @@ struct vb2_buffer {
>>   	unsigned int		type;
>>   	unsigned int		memory;
>>   	unsigned int		num_planes;
>> -	struct vb2_plane	planes[VIDEO_MAX_PLANES];
>> +	struct vb2_plane	planes[VB2_MAX_PLANES];
>>
>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>>   	/*
>> @@ -330,18 +339,24 @@ struct vb2_ops {
>>   	void (*buf_queue)(struct vb2_buffer *vb);
>>   };
>>
>> -struct v4l2_fh;
>> +struct vb2_buf_ops {
>> +	int (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
>> +	int (*fill_vb2_buffer)(struct vb2_buffer *vb, void *pb,
>> +				struct vb2_plane *planes);
>> +	int (*fill_vb2_timestamp)(struct vb2_buffer *vb, void *pb);
>> +	int (*is_last)(struct vb2_buffer *vb);
>> +};
>>
>>   /**
>>    * struct vb2_queue - a videobuf queue
>>    *
>> - * @type:	queue type (see V4L2_BUF_TYPE_* in linux/videodev2.h
>> + * @type:	queue type (see VB2_BUF_TYPE_*)
>>    * @io_modes:	supported io methods (see vb2_io_modes enum)
>>    * @fileio_read_once:		report EOF after reading the first buffer
>>    * @fileio_write_immediately:	queue buffer after each write() call
>>    * @allow_zero_bytesused:	allow bytesused == 0 to be passed to the driver
>>    * @lock:	pointer to a mutex that protects the vb2_queue struct. The
>> - *		driver can set this to a mutex to let the v4l2 core serialize
>> + *		driver can set this to a mutex to let the vb2 core serialize
>>    *		the queuing ioctls. If the driver wants to handle locking
>>    *		itself, then this should be set to NULL. This lock is not used
>>    *		by the videobuf2 core API.
>> @@ -351,10 +366,13 @@ struct v4l2_fh;
>>    *		drivers to easily associate an owner filehandle with the queue.
>>    * @ops:	driver-specific callbacks
>>    * @mem_ops:	memory allocator specific callbacks
>> + * @buf_ops:	callbacks to deliver buffer information
>> + *		between user-space and kernel-space
>>    * @drv_priv:	driver private data
>>    * @buf_struct_size: size of the driver-specific buffer structure;
>>    *		"0" indicates the driver doesn't want to use a custom buffer
>> - *		structure type, so sizeof(struct vb2_buffer) will is used
>> + *		structure type, so, sizeof(struct vb2_v4l2_buffer) will is used
>> + *		in case of v4l2.
>>    * @timestamp_flags: Timestamp flags; V4L2_BUF_FLAG_TIMESTAMP_* and
>>    *		V4L2_BUF_FLAG_TSTAMP_SRC_*
>>    * @gfp_flags:	additional gfp flags used when allocating the buffers.
>> @@ -385,6 +403,8 @@ struct v4l2_fh;
>>    * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
>>    *		buffers. Only set for capture queues if qbuf has not yet been
>>    *		called since poll() needs to return POLLERR in that situation.
>> + * @is_multiplanar: set if buffer type is multiplanar
>> + * @is_output:	set if buffer type is output
>>    * @last_buffer_dequeued: used in poll() and DQBUF to immediately return if the
>>    *		last decoded buffer was already dequeued. Set for capture queues
>>    *		when a buffer with the V4L2_BUF_FLAG_LAST is dequeued.
>> @@ -399,10 +419,12 @@ struct vb2_queue {
>>   	unsigned			allow_zero_bytesused:1;
>>
>>   	struct mutex			*lock;
>> -	struct v4l2_fh			*owner;
>> +	void				*owner;
>>
>>   	const struct vb2_ops		*ops;
>>   	const struct vb2_mem_ops	*mem_ops;
>> +	const struct vb2_buf_ops	*buf_ops;
>> +
>>   	void				*drv_priv;
>>   	unsigned int			buf_struct_size;
>>   	u32				timestamp_flags;
>> @@ -412,7 +434,7 @@ struct vb2_queue {
>>   	/* private: internal use only */
>>   	struct mutex			mmap_lock;
>>   	unsigned int			memory;
>> -	struct vb2_buffer		*bufs[VIDEO_MAX_FRAME];
>> +	struct vb2_buffer		*bufs[VB2_MAX_FRAME];
>>   	unsigned int			num_buffers;
>>
>>   	struct list_head		queued_list;
>> @@ -423,13 +445,15 @@ struct vb2_queue {
>>   	spinlock_t			done_lock;
>>   	wait_queue_head_t		done_wq;
>>
>> -	void				*alloc_ctx[VIDEO_MAX_PLANES];
>> -	unsigned int			plane_sizes[VIDEO_MAX_PLANES];
>> +	void				*alloc_ctx[VB2_MAX_PLANES];
>> +	unsigned int			plane_sizes[VB2_MAX_PLANES];
>>
>>   	unsigned int			streaming:1;
>>   	unsigned int			start_streaming_called:1;
>>   	unsigned int			error:1;
>>   	unsigned int			waiting_for_buffers:1;
>> +	unsigned int			is_multiplanar:1;
>> +	unsigned int			is_output:1;
>>   	unsigned int			last_buffer_dequeued:1;
>>
>>   	struct vb2_fileio_data		*fileio;
>> @@ -455,25 +479,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state);
>>   void vb2_discard_done(struct vb2_queue *q);
>>   int vb2_wait_for_all_buffers(struct vb2_queue *q);
>>
>> -int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
>> -int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
>> -
>> -int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
>> -int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
>> -
>> -int __must_check vb2_queue_init(struct vb2_queue *q);
>> -
>> -void vb2_queue_release(struct vb2_queue *q);
>>   void vb2_queue_error(struct vb2_queue *q);
>> -
>> -int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
>> -int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
>> -int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
>> -
>> -int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
>> -int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
>> -
>> -int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
>>   #ifndef CONFIG_MMU
>>   unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>   				    unsigned long addr,
>> @@ -481,41 +487,6 @@ unsigned long vb2_get_unmapped_area(struct vb2_queue *q,
>>   				    unsigned long pgoff,
>>   				    unsigned long flags);
>>   #endif
>> -unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
>> -size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
>> -		loff_t *ppos, int nonblock);
>> -size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
>> -		loff_t *ppos, int nonblock);
>> -
>> -/*
>> - * vb2_thread_fnc - callback function for use with vb2_thread
>> - *
>> - * This is called whenever a buffer is dequeued in the thread.
>> - */
>> -typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
>> -
>> -/**
>> - * vb2_thread_start() - start a thread for the given queue.
>> - * @q:		videobuf queue
>> - * @fnc:	callback function
>> - * @priv:	priv pointer passed to the callback function
>> - * @thread_name:the name of the thread. This will be prefixed with "vb2-".
>> - *
>> - * This starts a thread that will queue and dequeue until an error occurs
>> - * or @vb2_thread_stop is called.
>> - *
>> - * This function should not be used for anything else but the videobuf2-dvb
>> - * support. If you think you have another good use-case for this, then please
>> - * contact the linux-media mailinglist first.
>> - */
>> -int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
>> -		     const char *thread_name);
>> -
>> -/**
>> - * vb2_thread_stop() - stop the thread for the given queue.
>> - * @q:		videobuf queue
>> - */
>> -int vb2_thread_stop(struct vb2_queue *q);
>>
>>   /**
>>    * vb2_is_streaming() - return streaming status of the queue
>> @@ -527,23 +498,6 @@ static inline bool vb2_is_streaming(struct vb2_queue *q)
>>   }
>>
>>   /**
>> - * vb2_fileio_is_active() - return true if fileio is active.
>> - * @q:		videobuf queue
>> - *
>> - * This returns true if read() or write() is used to stream the data
>> - * as opposed to stream I/O. This is almost never an important distinction,
>> - * except in rare cases. One such case is that using read() or write() to
>> - * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
>> - * is no way you can pass the field information of each buffer to/from
>> - * userspace. A driver that supports this field format should check for
>> - * this in the queue_setup op and reject it if this function returns true.
>> - */
>> -static inline bool vb2_fileio_is_active(struct vb2_queue *q)
>> -{
>> -	return q->fileio;
>> -}
>> -
>> -/**
>>    * vb2_is_busy() - return busy status of the queue
>>    * @q:		videobuf queue
>>    *
>> @@ -620,47 +574,4 @@ static inline void vb2_clear_last_buffer_dequeued(struct vb2_queue *q)
>>   	q->last_buffer_dequeued = false;
>>   }
>>
>> -/*
>> - * The following functions are not part of the vb2 core API, but are simple
>> - * helper functions that you can use in your struct v4l2_file_operations,
>> - * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock
>> - * or video_device->lock is set, and they will set and test vb2_queue->owner
>> - * to check if the calling filehandle is permitted to do the queuing operation.
>> - */
>> -
>> -/* struct v4l2_ioctl_ops helpers */
>> -
>> -int vb2_ioctl_reqbufs(struct file *file, void *priv,
>> -			  struct v4l2_requestbuffers *p);
>> -int vb2_ioctl_create_bufs(struct file *file, void *priv,
>> -			  struct v4l2_create_buffers *p);
>> -int vb2_ioctl_prepare_buf(struct file *file, void *priv,
>> -			  struct v4l2_buffer *p);
>> -int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> -int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> -int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> -int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
>> -int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
>> -int vb2_ioctl_expbuf(struct file *file, void *priv,
>> -	struct v4l2_exportbuffer *p);
>> -
>> -/* struct v4l2_file_operations helpers */
>> -
>> -int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
>> -int vb2_fop_release(struct file *file);
>> -int _vb2_fop_release(struct file *file, struct mutex *lock);
>> -ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>> -		size_t count, loff_t *ppos);
>> -ssize_t vb2_fop_read(struct file *file, char __user *buf,
>> -		size_t count, loff_t *ppos);
>> -unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
>> -#ifndef CONFIG_MMU
>> -unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>> -		unsigned long len, unsigned long pgoff, unsigned long flags);
>> -#endif
>> -
>> -/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
>> -
>> -void vb2_ops_wait_prepare(struct vb2_queue *vq);
>> -void vb2_ops_wait_finish(struct vb2_queue *vq);
>>   #endif /* _MEDIA_VIDEOBUF2_CORE_H */
>> diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
>> index fc2dbe9..790cb7a 100644
>> --- a/include/media/videobuf2-v4l2.h
>> +++ b/include/media/videobuf2-v4l2.h
>> @@ -40,4 +40,120 @@ struct vb2_v4l2_buffer {
>>   #define to_vb2_v4l2_buffer(vb) \
>>   	(container_of(vb, struct vb2_v4l2_buffer, vb2_buf))
>>
>> +
>> +int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b);
>> +int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
>> +
>> +int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
>> +int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
>> +
>> +int __must_check vb2_queue_init(struct vb2_queue *q);
>> +
>> +void vb2_queue_release(struct vb2_queue *q);
>> +
>> +int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
>> +int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
>> +int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking);
>> +
>> +int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type);
>> +int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type);
>> +int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma);
>> +unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait);
>> +size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
>> +		loff_t *ppos, int nonblock);
>> +size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
>> +		loff_t *ppos, int nonblock);
>> +
>> +/*
>> + * vb2_thread_fnc - callback function for use with vb2_thread
>> + *
>> + * This is called whenever a buffer is dequeued in the thread.
>> + */
>> +typedef int (*vb2_thread_fnc)(struct vb2_buffer *vb, void *priv);
>> +
>> +/**
>> + * vb2_thread_start() - start a thread for the given queue.
>> + * @q:		videobuf queue
>> + * @fnc:	callback function
>> + * @priv:	priv pointer passed to the callback function
>> + * @thread_name:the name of the thread. This will be prefixed with "vb2-".
>> + *
>> + * This starts a thread that will queue and dequeue until an error occurs
>> + * or @vb2_thread_stop is called.
>> + *
>> + * This function should not be used for anything else but the videobuf2-dvb
>> + * support. If you think you have another good use-case for this, then please
>> + * contact the linux-media mailinglist first.
>> + */
>> +int vb2_thread_start(struct vb2_queue *q, vb2_thread_fnc fnc, void *priv,
>> +		     const char *thread_name);
>> +
>> +/**
>> + * vb2_thread_stop() - stop the thread for the given queue.
>> + * @q:		videobuf queue
>> + */
>> +int vb2_thread_stop(struct vb2_queue *q);
>> +
>> +/**
>> + * vb2_fileio_is_active() - return true if fileio is active.
>> + * @q:		videobuf queue
>> + *
>> + * This returns true if read() or write() is used to stream the data
>> + * as opposed to stream I/O. This is almost never an important distinction,
>> + * except in rare cases. One such case is that using read() or write() to
>> + * stream a format using V4L2_FIELD_ALTERNATE is not allowed since there
>> + * is no way you can pass the field information of each buffer to/from
>> + * userspace. A driver that supports this field format should check for
>> + * this in the queue_setup op and reject it if this function returns true.
>> + */
>> +static inline bool vb2_fileio_is_active(struct vb2_queue *q)
>> +{
>> +	return q->fileio;
>> +}
>> +
>> +/*
>> + * The following functions are not part of the vb2 core API, but are simple
>> + * helper functions that you can use in your struct v4l2_file_operations,
>> + * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize
>> + * if vb2_queue->lock or video_device->lock is set, and they will set
>> + * and test vb2_queue->owner to check if the calling filehandle is permitted
>> + * to do the queuing operation.
>> + */
>> +
>> +/* struct v4l2_ioctl_ops helpers */
>> +
>> +int vb2_ioctl_reqbufs(struct file *file, void *priv,
>> +			  struct v4l2_requestbuffers *p);
>> +int vb2_ioctl_create_bufs(struct file *file, void *priv,
>> +			  struct v4l2_create_buffers *p);
>> +int vb2_ioctl_prepare_buf(struct file *file, void *priv,
>> +			  struct v4l2_buffer *p);
>> +int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> +int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> +int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p);
>> +int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i);
>> +int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i);
>> +int vb2_ioctl_expbuf(struct file *file, void *priv,
>> +	struct v4l2_exportbuffer *p);
>> +
>> +/* struct v4l2_file_operations helpers */
>> +
>> +int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma);
>> +int vb2_fop_release(struct file *file);
>> +int _vb2_fop_release(struct file *file, struct mutex *lock);
>> +ssize_t vb2_fop_write(struct file *file, const char __user *buf,
>> +		size_t count, loff_t *ppos);
>> +ssize_t vb2_fop_read(struct file *file, char __user *buf,
>> +		size_t count, loff_t *ppos);
>> +unsigned int vb2_fop_poll(struct file *file, poll_table *wait);
>> +#ifndef CONFIG_MMU
>> +unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr,
>> +		unsigned long len, unsigned long pgoff, unsigned long flags);
>> +#endif
>> +
>> +/* struct vb2_ops helpers, only use if vq->lock is non-NULL. */
>> +
>> +void vb2_ops_wait_prepare(struct vb2_queue *vq);
>> +void vb2_ops_wait_finish(struct vb2_queue *vq);
>> +
>>   #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
>> diff --git a/include/trace/events/v4l2.h b/include/trace/events/v4l2.h
>> index b015b38..f31b258 100644
>> --- a/include/trace/events/v4l2.h
>> +++ b/include/trace/events/v4l2.h
>> @@ -5,6 +5,7 @@
>>   #define _TRACE_V4L2_H
>>
>>   #include <linux/tracepoint.h>
>> +#include <media/videobuf2-v4l2.h>
>>
>>   /* Enums require being exported to userspace, for user tool parsing */
>>   #undef EM
>> @@ -203,7 +204,8 @@ DECLARE_EVENT_CLASS(vb2_event_class,
>>
>>   	TP_fast_assign(
>>   		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>> -		__entry->minor = q->owner ? q->owner->vdev->minor : -1;
>> +		struct v4l2_fh *owner = (struct v4l2_fh *) q->owner;
>> +		__entry->minor = owner ? owner->vdev->minor : -1;
>>   		__entry->queued_count = q->queued_count;
>>   		__entry->owned_by_drv_count =
>>   			atomic_read(&q->owned_by_drv_count);
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer
  2015-08-31  2:01     ` Junghak Sung
@ 2015-08-31  7:56       ` Junghak Sung
  2015-08-31  8:24         ` Hans Verkuil
  0 siblings, 1 reply; 23+ messages in thread
From: Junghak Sung @ 2015-08-31  7:56 UTC (permalink / raw)
  To: Hans Verkuil, linux-media, mchehab, laurent.pinchart,
	sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon



On 08/31/2015 11:01 AM, Junghak Sung wrote:
> Hello Hans,
>
> Thank you for your review.
> I leave some comments in the body for reply.
>
> Regards,
> Junghak
>
>
>
> On 08/28/2015 10:31 PM, Hans Verkuil wrote:
>> Hi Junghak,
>>
>> Thanks for this patch, it looks much better. I do have a number of
>> comments, though...
>>
>> On 08/26/2015 01:59 PM, Junghak Sung wrote:
>>> Remove v4l2-specific stuff from struct vb2_buffer and add member
>>> variables
>>> related with buffer management.
>>>
>>> struct vb2_plane {
>>>          <snip>
>>>          /* plane information */
>>>          unsigned int            bytesused;
>>>          unsigned int            length;
>>>          union {
>>>                  unsigned int    offset;
>>>                  unsigned long   userptr;
>>>                  int             fd;
>>>          } m;
>>>          unsigned int            data_offset;
>>> }
>>>
>>> struct vb2_buffer {
>>>          <snip>
>>>          /* buffer information */
>>>          unsigned int            num_planes;
>>>          unsigned int            index;
>>>          unsigned int            type;
>>>          unsigned int            memory;
>>>
>>>          struct vb2_plane        planes[VIDEO_MAX_PLANES];
>>>          <snip>
>>> };
>>>
>>> And create struct vb2_v4l2_buffer as container buffer for v4l2 use.
>>>
>>> struct vb2_v4l2_buffer {
>>>          struct vb2_buffer       vb2_buf;
>>>
>>>          __u32                   flags;
>>>          __u32                   field;
>>>          struct timeval          timestamp;
>>>          struct v4l2_timecode    timecode;
>>>          __u32                   sequence;
>>> };
>>>
>>> This patch includes only changes inside of videobuf2. So, it is
>>> required to
>>> modify all device drivers which use videobuf2.
>>>
>>> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
>>> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
>>> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>>> Acked-by: Inki Dae <inki.dae@samsung.com>
>>> ---
>>>   drivers/media/v4l2-core/videobuf2-core.c |  324
>>> +++++++++++++++++-------------
>>>   include/media/videobuf2-core.h           |   50 ++---
>>>   include/media/videobuf2-v4l2.h           |   26 +++
>>>   3 files changed, 236 insertions(+), 164 deletions(-)
>>>
>>> diff --git a/drivers/media/v4l2-core/videobuf2-core.c
>>> b/drivers/media/v4l2-core/videobuf2-core.c
>>> index ab00ea0..9266d50 100644
>>> --- a/drivers/media/v4l2-core/videobuf2-core.c
>>> +++ b/drivers/media/v4l2-core/videobuf2-core.c
>>> @@ -35,10 +35,10 @@
>>>   static int debug;
>>>   module_param(debug, int, 0644);
>>>
>>> -#define dprintk(level, fmt, arg...)                          \
>>> -    do {                                      \
>>> -        if (debug >= level)                          \
>>> -            pr_info("vb2: %s: " fmt, __func__, ## arg); \
>>> +#define dprintk(level, fmt, arg...)                    \
>>> +    do {                                \
>>> +        if (debug >= level)                    \
>>> +            pr_info("vb2: %s: " fmt, __func__, ## arg);    \
>>
>> These are just whitespace changes, and that is something it see *a
>> lot* in this
>> patch. And usually for no clear reason.
>>
>> Please remove those whitespace changes, it makes a difficult patch
>> even harder
>> to read than it already is.
>>
>
> I just wanted to remove unnecessary white spaces or adjust alignment.
> OK, I will revert those whitespace changes for better review.
>
>>>       } while (0)
>>>
>>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>>
>> <snip>
>>
>>> @@ -656,12 +652,21 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>>    */
>>>   static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct
>>> v4l2_buffer *b)
>>>   {
>>> +    struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>>       struct vb2_queue *q = vb->vb2_queue;
>>> +    unsigned int plane;
>>>
>>>       /* Copy back data such as timestamp, flags, etc. */
>>> -    memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
>>> -    b->reserved2 = vb->v4l2_buf.reserved2;
>>> -    b->reserved = vb->v4l2_buf.reserved;
>>
>> Hmm, I'm not sure why these reserved fields were copied here. I think
>> it was
>> for compatibility reasons for some old drivers that abused the
>> reserved field.
>> However, in the new code these reserved fields should probably be
>> explicitly
>> initialized to 0.
>>
>>> +    b->index = vb->index;
>>> +    b->type = vb->type;
>>> +    b->memory = vb->memory;
>>> +    b->bytesused = 0;
>>> +
>>> +    b->flags = vbuf->flags;
>>> +    b->field = vbuf->field;
>>> +    b->timestamp = vbuf->timestamp;
>>> +    b->timecode = vbuf->timecode;
>>> +    b->sequence = vbuf->sequence;
>>>
>>>       if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>>>           /*
>>> @@ -669,21 +674,33 @@ static void __fill_v4l2_buffer(struct
>>> vb2_buffer *vb, struct v4l2_buffer *b)
>>>            * for it. The caller has already verified memory and size.
>>>            */
>>>           b->length = vb->num_planes;
>>> -        memcpy(b->m.planes, vb->v4l2_planes,
>>> -            b->length * sizeof(struct v4l2_plane));
>>
>> A similar problem occurs here: the memcpy would have copied the reserved
>> field in v4l2_plane as well, but that no longer happens, so you need to
>> do an explicit memset for the reserved field in the new code.
>>
>
> It means that I'd better add reserved fields to struct vb2_buffer and
> struct vb2_plane in order to keep the information in struct v4l2_buffer
> and struct v4l2_plane???
>

Oh, I've mistaken your point.
Now I got your point.
In __fill_v4l2_buffer(), just initialize explicitly the reserved
field like :
	memset(pdst->reserved, 0 sizeof(pdst->reserved));
Right?


>
>>> +        for (plane = 0; plane < vb->num_planes; ++plane) {
>>> +            struct v4l2_plane *pdst = &b->m.planes[plane];
>>> +            struct vb2_plane *psrc = &vb->planes[plane];
>>> +
>>> +            pdst->bytesused = psrc->bytesused;
>>> +            pdst->length = psrc->length;
>>> +            if (q->memory == V4L2_MEMORY_MMAP)
>>> +                pdst->m.mem_offset = psrc->m.offset;
>>> +            else if (q->memory == V4L2_MEMORY_USERPTR)
>>> +                pdst->m.userptr = psrc->m.userptr;
>>> +            else if (q->memory == V4L2_MEMORY_DMABUF)
>>> +                pdst->m.fd = psrc->m.fd;
>>> +            pdst->data_offset = psrc->data_offset;
>>> +        }
>>>       } else {
>>>           /*
>>>            * We use length and offset in v4l2_planes array even for
>>>            * single-planar buffers, but userspace does not.
>>>            */
>>> -        b->length = vb->v4l2_planes[0].length;
>>> -        b->bytesused = vb->v4l2_planes[0].bytesused;
>>> +        b->length = vb->planes[0].length;
>>> +        b->bytesused = vb->planes[0].bytesused;
>>>           if (q->memory == V4L2_MEMORY_MMAP)
>>> -            b->m.offset = vb->v4l2_planes[0].m.mem_offset;
>>> +            b->m.offset = vb->planes[0].m.offset;
>>>           else if (q->memory == V4L2_MEMORY_USERPTR)
>>> -            b->m.userptr = vb->v4l2_planes[0].m.userptr;
>>> +            b->m.userptr = vb->planes[0].m.userptr;
>>>           else if (q->memory == V4L2_MEMORY_DMABUF)
>>> -            b->m.fd = vb->v4l2_planes[0].m.fd;
>>> +            b->m.fd = vb->planes[0].m.fd;
>>>       }
>>>
>>>       /*
>>> @@ -692,7 +709,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer
>>> *vb, struct v4l2_buffer *b)
>>>       b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>>>       b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>>>       if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>>> -        V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>>> +            V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>>>           /*
>>>            * For non-COPY timestamps, drop timestamp source bits
>>>            * and obtain the timestamp source from the queue.
>>> @@ -767,7 +784,7 @@ EXPORT_SYMBOL(vb2_querybuf);
>>>   static int __verify_userptr_ops(struct vb2_queue *q)
>>>   {
>>>       if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
>>> -        !q->mem_ops->put_userptr)
>>> +            !q->mem_ops->put_userptr)
>>>           return -EINVAL;
>>>
>>>       return 0;
>>> @@ -780,7 +797,7 @@ static int __verify_userptr_ops(struct vb2_queue *q)
>>>   static int __verify_mmap_ops(struct vb2_queue *q)
>>>   {
>>>       if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
>>> -        !q->mem_ops->put || !q->mem_ops->mmap)
>>> +            !q->mem_ops->put || !q->mem_ops->mmap)
>>>           return -EINVAL;
>>>
>>>       return 0;
>>> @@ -793,8 +810,8 @@ static int __verify_mmap_ops(struct vb2_queue *q)
>>>   static int __verify_dmabuf_ops(struct vb2_queue *q)
>>>   {
>>>       if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
>>> -        !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
>>> -        !q->mem_ops->unmap_dmabuf)
>>> +        !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
>>> +        !q->mem_ops->unmap_dmabuf)
>>>           return -EINVAL;
>>>
>>>       return 0;
>>> @@ -808,7 +825,7 @@ static int __verify_memory_type(struct vb2_queue *q,
>>>           enum v4l2_memory memory, enum v4l2_buf_type type)
>>>   {
>>>       if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
>>> -        memory != V4L2_MEMORY_DMABUF) {
>>> +            memory != V4L2_MEMORY_DMABUF) {
>>>           dprintk(1, "unsupported memory type\n");
>>>           return -EINVAL;
>>>       }
>>> @@ -927,7 +944,7 @@ static int __reqbufs(struct vb2_queue *q, struct
>>> v4l2_requestbuffers *req)
>>>        * Driver also sets the size and allocator context for each plane.
>>>        */
>>>       ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
>>> -               q->plane_sizes, q->alloc_ctx);
>>> +            q->plane_sizes, q->alloc_ctx);
>>>       if (ret)
>>>           return ret;
>>>
>>> @@ -952,7 +969,7 @@ static int __reqbufs(struct vb2_queue *q, struct
>>> v4l2_requestbuffers *req)
>>>           num_buffers = allocated_buffers;
>>>
>>>           ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
>>> -                   &num_planes, q->plane_sizes, q->alloc_ctx);
>>> +                &num_planes, q->plane_sizes, q->alloc_ctx);
>>>
>>>           if (!ret && allocated_buffers < num_buffers)
>>>               ret = -ENOMEM;
>>> @@ -1040,7 +1057,7 @@ static int __create_bufs(struct vb2_queue *q,
>>> struct v4l2_create_buffers *create
>>>        * buffer and their sizes are acceptable
>>>        */
>>>       ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>>> -               &num_planes, q->plane_sizes, q->alloc_ctx);
>>> +            &num_planes, q->plane_sizes, q->alloc_ctx);
>>>       if (ret)
>>>           return ret;
>>>
>>> @@ -1063,7 +1080,7 @@ static int __create_bufs(struct vb2_queue *q,
>>> struct v4l2_create_buffers *create
>>>            * queue driver has set up
>>>            */
>>>           ret = call_qop(q, queue_setup, q, &create->format,
>>> &num_buffers,
>>> -                   &num_planes, q->plane_sizes, q->alloc_ctx);
>>> +                &num_planes, q->plane_sizes, q->alloc_ctx);
>>>
>>>           if (!ret && allocated_buffers < num_buffers)
>>>               ret = -ENOMEM;
>>> @@ -1183,8 +1200,8 @@ void vb2_buffer_done(struct vb2_buffer *vb,
>>> enum vb2_buffer_state state)
>>>           return;
>>>
>>>       if (WARN_ON(state != VB2_BUF_STATE_DONE &&
>>> -            state != VB2_BUF_STATE_ERROR &&
>>> -            state != VB2_BUF_STATE_QUEUED))
>>> +        state != VB2_BUF_STATE_ERROR &&
>>> +        state != VB2_BUF_STATE_QUEUED))
>>>           state = VB2_BUF_STATE_ERROR;
>>>
>>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>>
>> All the chunks above are all spurious whitespace changes. As mentioned
>> in the beginning,
>> please remove all those pointless whitespace changes!
>>
>> There are a lot more of these, but I won't comment on them anymore.
>>
>> Basically this patch looks good to me, so once I have the next version
>> without all the
>> whitespace confusion and with the reserved field issues solved I'll do
>> a final review.
>>
>> BTW, did you test this with 'v4l2-compliance -s' and with the vivid
>> driver? Just to
>> make sure you didn't break anything.
>>
>
> Actually, I've tested with v4l2-compliance for just one v4l2 drivers -
> au0828.
> I'll try to test with vivid driver at next round.
>

I tried to use vivid for test. But, I have failed to install the
module (vivid.ko).
I mainly referred to documentation/video4linux/vivid.txt. But, it
not enough to test.
Could you give me a guide?

Best Regards,
Junghak

>
>> Regards,
>>
>>     Hans
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer
  2015-08-31  7:56       ` Junghak Sung
@ 2015-08-31  8:24         ` Hans Verkuil
  0 siblings, 0 replies; 23+ messages in thread
From: Hans Verkuil @ 2015-08-31  8:24 UTC (permalink / raw)
  To: Junghak Sung, linux-media, mchehab, laurent.pinchart,
	sakari.ailus, pawel
  Cc: inki.dae, sw0312.kim, nenggun.kim, sangbae90.lee, rany.kwon

On 08/31/2015 09:56 AM, Junghak Sung wrote:
> 
> 
> On 08/31/2015 11:01 AM, Junghak Sung wrote:
>> Hello Hans,
>>
>> Thank you for your review.
>> I leave some comments in the body for reply.
>>
>> Regards,
>> Junghak
>>
>>
>>
>> On 08/28/2015 10:31 PM, Hans Verkuil wrote:
>>> Hi Junghak,
>>>
>>> Thanks for this patch, it looks much better. I do have a number of
>>> comments, though...
>>>
>>> On 08/26/2015 01:59 PM, Junghak Sung wrote:
>>>> Remove v4l2-specific stuff from struct vb2_buffer and add member
>>>> variables
>>>> related with buffer management.
>>>>
>>>> struct vb2_plane {
>>>>          <snip>
>>>>          /* plane information */
>>>>          unsigned int            bytesused;
>>>>          unsigned int            length;
>>>>          union {
>>>>                  unsigned int    offset;
>>>>                  unsigned long   userptr;
>>>>                  int             fd;
>>>>          } m;
>>>>          unsigned int            data_offset;
>>>> }
>>>>
>>>> struct vb2_buffer {
>>>>          <snip>
>>>>          /* buffer information */
>>>>          unsigned int            num_planes;
>>>>          unsigned int            index;
>>>>          unsigned int            type;
>>>>          unsigned int            memory;
>>>>
>>>>          struct vb2_plane        planes[VIDEO_MAX_PLANES];
>>>>          <snip>
>>>> };
>>>>
>>>> And create struct vb2_v4l2_buffer as container buffer for v4l2 use.
>>>>
>>>> struct vb2_v4l2_buffer {
>>>>          struct vb2_buffer       vb2_buf;
>>>>
>>>>          __u32                   flags;
>>>>          __u32                   field;
>>>>          struct timeval          timestamp;
>>>>          struct v4l2_timecode    timecode;
>>>>          __u32                   sequence;
>>>> };
>>>>
>>>> This patch includes only changes inside of videobuf2. So, it is
>>>> required to
>>>> modify all device drivers which use videobuf2.
>>>>
>>>> Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
>>>> Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
>>>> Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
>>>> Acked-by: Inki Dae <inki.dae@samsung.com>
>>>> ---
>>>>   drivers/media/v4l2-core/videobuf2-core.c |  324
>>>> +++++++++++++++++-------------
>>>>   include/media/videobuf2-core.h           |   50 ++---
>>>>   include/media/videobuf2-v4l2.h           |   26 +++
>>>>   3 files changed, 236 insertions(+), 164 deletions(-)
>>>>
>>>> diff --git a/drivers/media/v4l2-core/videobuf2-core.c
>>>> b/drivers/media/v4l2-core/videobuf2-core.c
>>>> index ab00ea0..9266d50 100644
>>>> --- a/drivers/media/v4l2-core/videobuf2-core.c
>>>> +++ b/drivers/media/v4l2-core/videobuf2-core.c
>>>> @@ -35,10 +35,10 @@
>>>>   static int debug;
>>>>   module_param(debug, int, 0644);
>>>>
>>>> -#define dprintk(level, fmt, arg...)                          \
>>>> -    do {                                      \
>>>> -        if (debug >= level)                          \
>>>> -            pr_info("vb2: %s: " fmt, __func__, ## arg); \
>>>> +#define dprintk(level, fmt, arg...)                    \
>>>> +    do {                                \
>>>> +        if (debug >= level)                    \
>>>> +            pr_info("vb2: %s: " fmt, __func__, ## arg);    \
>>>
>>> These are just whitespace changes, and that is something it see *a
>>> lot* in this
>>> patch. And usually for no clear reason.
>>>
>>> Please remove those whitespace changes, it makes a difficult patch
>>> even harder
>>> to read than it already is.
>>>
>>
>> I just wanted to remove unnecessary white spaces or adjust alignment.
>> OK, I will revert those whitespace changes for better review.
>>
>>>>       } while (0)
>>>>
>>>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>>>
>>> <snip>
>>>
>>>> @@ -656,12 +652,21 @@ static bool __buffers_in_use(struct vb2_queue *q)
>>>>    */
>>>>   static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct
>>>> v4l2_buffer *b)
>>>>   {
>>>> +    struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
>>>>       struct vb2_queue *q = vb->vb2_queue;
>>>> +    unsigned int plane;
>>>>
>>>>       /* Copy back data such as timestamp, flags, etc. */
>>>> -    memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
>>>> -    b->reserved2 = vb->v4l2_buf.reserved2;
>>>> -    b->reserved = vb->v4l2_buf.reserved;
>>>
>>> Hmm, I'm not sure why these reserved fields were copied here. I think
>>> it was
>>> for compatibility reasons for some old drivers that abused the
>>> reserved field.
>>> However, in the new code these reserved fields should probably be
>>> explicitly
>>> initialized to 0.
>>>
>>>> +    b->index = vb->index;
>>>> +    b->type = vb->type;
>>>> +    b->memory = vb->memory;
>>>> +    b->bytesused = 0;
>>>> +
>>>> +    b->flags = vbuf->flags;
>>>> +    b->field = vbuf->field;
>>>> +    b->timestamp = vbuf->timestamp;
>>>> +    b->timecode = vbuf->timecode;
>>>> +    b->sequence = vbuf->sequence;
>>>>
>>>>       if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
>>>>           /*
>>>> @@ -669,21 +674,33 @@ static void __fill_v4l2_buffer(struct
>>>> vb2_buffer *vb, struct v4l2_buffer *b)
>>>>            * for it. The caller has already verified memory and size.
>>>>            */
>>>>           b->length = vb->num_planes;
>>>> -        memcpy(b->m.planes, vb->v4l2_planes,
>>>> -            b->length * sizeof(struct v4l2_plane));
>>>
>>> A similar problem occurs here: the memcpy would have copied the reserved
>>> field in v4l2_plane as well, but that no longer happens, so you need to
>>> do an explicit memset for the reserved field in the new code.
>>>
>>
>> It means that I'd better add reserved fields to struct vb2_buffer and
>> struct vb2_plane in order to keep the information in struct v4l2_buffer
>> and struct v4l2_plane???
>>
> 
> Oh, I've mistaken your point.
> Now I got your point.
> In __fill_v4l2_buffer(), just initialize explicitly the reserved
> field like :
> 	memset(pdst->reserved, 0 sizeof(pdst->reserved));
> Right?

Right.

> 
> 
>>
>>>> +        for (plane = 0; plane < vb->num_planes; ++plane) {
>>>> +            struct v4l2_plane *pdst = &b->m.planes[plane];
>>>> +            struct vb2_plane *psrc = &vb->planes[plane];
>>>> +
>>>> +            pdst->bytesused = psrc->bytesused;
>>>> +            pdst->length = psrc->length;
>>>> +            if (q->memory == V4L2_MEMORY_MMAP)
>>>> +                pdst->m.mem_offset = psrc->m.offset;
>>>> +            else if (q->memory == V4L2_MEMORY_USERPTR)
>>>> +                pdst->m.userptr = psrc->m.userptr;
>>>> +            else if (q->memory == V4L2_MEMORY_DMABUF)
>>>> +                pdst->m.fd = psrc->m.fd;
>>>> +            pdst->data_offset = psrc->data_offset;
>>>> +        }
>>>>       } else {
>>>>           /*
>>>>            * We use length and offset in v4l2_planes array even for
>>>>            * single-planar buffers, but userspace does not.
>>>>            */
>>>> -        b->length = vb->v4l2_planes[0].length;
>>>> -        b->bytesused = vb->v4l2_planes[0].bytesused;
>>>> +        b->length = vb->planes[0].length;
>>>> +        b->bytesused = vb->planes[0].bytesused;
>>>>           if (q->memory == V4L2_MEMORY_MMAP)
>>>> -            b->m.offset = vb->v4l2_planes[0].m.mem_offset;
>>>> +            b->m.offset = vb->planes[0].m.offset;
>>>>           else if (q->memory == V4L2_MEMORY_USERPTR)
>>>> -            b->m.userptr = vb->v4l2_planes[0].m.userptr;
>>>> +            b->m.userptr = vb->planes[0].m.userptr;
>>>>           else if (q->memory == V4L2_MEMORY_DMABUF)
>>>> -            b->m.fd = vb->v4l2_planes[0].m.fd;
>>>> +            b->m.fd = vb->planes[0].m.fd;
>>>>       }
>>>>
>>>>       /*
>>>> @@ -692,7 +709,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer
>>>> *vb, struct v4l2_buffer *b)
>>>>       b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
>>>>       b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
>>>>       if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) !=
>>>> -        V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>>>> +            V4L2_BUF_FLAG_TIMESTAMP_COPY) {
>>>>           /*
>>>>            * For non-COPY timestamps, drop timestamp source bits
>>>>            * and obtain the timestamp source from the queue.
>>>> @@ -767,7 +784,7 @@ EXPORT_SYMBOL(vb2_querybuf);
>>>>   static int __verify_userptr_ops(struct vb2_queue *q)
>>>>   {
>>>>       if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
>>>> -        !q->mem_ops->put_userptr)
>>>> +            !q->mem_ops->put_userptr)
>>>>           return -EINVAL;
>>>>
>>>>       return 0;
>>>> @@ -780,7 +797,7 @@ static int __verify_userptr_ops(struct vb2_queue *q)
>>>>   static int __verify_mmap_ops(struct vb2_queue *q)
>>>>   {
>>>>       if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
>>>> -        !q->mem_ops->put || !q->mem_ops->mmap)
>>>> +            !q->mem_ops->put || !q->mem_ops->mmap)
>>>>           return -EINVAL;
>>>>
>>>>       return 0;
>>>> @@ -793,8 +810,8 @@ static int __verify_mmap_ops(struct vb2_queue *q)
>>>>   static int __verify_dmabuf_ops(struct vb2_queue *q)
>>>>   {
>>>>       if (!(q->io_modes & VB2_DMABUF) || !q->mem_ops->attach_dmabuf ||
>>>> -        !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
>>>> -        !q->mem_ops->unmap_dmabuf)
>>>> +        !q->mem_ops->detach_dmabuf  || !q->mem_ops->map_dmabuf ||
>>>> +        !q->mem_ops->unmap_dmabuf)
>>>>           return -EINVAL;
>>>>
>>>>       return 0;
>>>> @@ -808,7 +825,7 @@ static int __verify_memory_type(struct vb2_queue *q,
>>>>           enum v4l2_memory memory, enum v4l2_buf_type type)
>>>>   {
>>>>       if (memory != V4L2_MEMORY_MMAP && memory != V4L2_MEMORY_USERPTR &&
>>>> -        memory != V4L2_MEMORY_DMABUF) {
>>>> +            memory != V4L2_MEMORY_DMABUF) {
>>>>           dprintk(1, "unsupported memory type\n");
>>>>           return -EINVAL;
>>>>       }
>>>> @@ -927,7 +944,7 @@ static int __reqbufs(struct vb2_queue *q, struct
>>>> v4l2_requestbuffers *req)
>>>>        * Driver also sets the size and allocator context for each plane.
>>>>        */
>>>>       ret = call_qop(q, queue_setup, q, NULL, &num_buffers, &num_planes,
>>>> -               q->plane_sizes, q->alloc_ctx);
>>>> +            q->plane_sizes, q->alloc_ctx);
>>>>       if (ret)
>>>>           return ret;
>>>>
>>>> @@ -952,7 +969,7 @@ static int __reqbufs(struct vb2_queue *q, struct
>>>> v4l2_requestbuffers *req)
>>>>           num_buffers = allocated_buffers;
>>>>
>>>>           ret = call_qop(q, queue_setup, q, NULL, &num_buffers,
>>>> -                   &num_planes, q->plane_sizes, q->alloc_ctx);
>>>> +                &num_planes, q->plane_sizes, q->alloc_ctx);
>>>>
>>>>           if (!ret && allocated_buffers < num_buffers)
>>>>               ret = -ENOMEM;
>>>> @@ -1040,7 +1057,7 @@ static int __create_bufs(struct vb2_queue *q,
>>>> struct v4l2_create_buffers *create
>>>>        * buffer and their sizes are acceptable
>>>>        */
>>>>       ret = call_qop(q, queue_setup, q, &create->format, &num_buffers,
>>>> -               &num_planes, q->plane_sizes, q->alloc_ctx);
>>>> +            &num_planes, q->plane_sizes, q->alloc_ctx);
>>>>       if (ret)
>>>>           return ret;
>>>>
>>>> @@ -1063,7 +1080,7 @@ static int __create_bufs(struct vb2_queue *q,
>>>> struct v4l2_create_buffers *create
>>>>            * queue driver has set up
>>>>            */
>>>>           ret = call_qop(q, queue_setup, q, &create->format,
>>>> &num_buffers,
>>>> -                   &num_planes, q->plane_sizes, q->alloc_ctx);
>>>> +                &num_planes, q->plane_sizes, q->alloc_ctx);
>>>>
>>>>           if (!ret && allocated_buffers < num_buffers)
>>>>               ret = -ENOMEM;
>>>> @@ -1183,8 +1200,8 @@ void vb2_buffer_done(struct vb2_buffer *vb,
>>>> enum vb2_buffer_state state)
>>>>           return;
>>>>
>>>>       if (WARN_ON(state != VB2_BUF_STATE_DONE &&
>>>> -            state != VB2_BUF_STATE_ERROR &&
>>>> -            state != VB2_BUF_STATE_QUEUED))
>>>> +        state != VB2_BUF_STATE_ERROR &&
>>>> +        state != VB2_BUF_STATE_QUEUED))
>>>>           state = VB2_BUF_STATE_ERROR;
>>>>
>>>>   #ifdef CONFIG_VIDEO_ADV_DEBUG
>>>
>>> All the chunks above are all spurious whitespace changes. As mentioned
>>> in the beginning,
>>> please remove all those pointless whitespace changes!
>>>
>>> There are a lot more of these, but I won't comment on them anymore.
>>>
>>> Basically this patch looks good to me, so once I have the next version
>>> without all the
>>> whitespace confusion and with the reserved field issues solved I'll do
>>> a final review.
>>>
>>> BTW, did you test this with 'v4l2-compliance -s' and with the vivid
>>> driver? Just to
>>> make sure you didn't break anything.
>>>
>>
>> Actually, I've tested with v4l2-compliance for just one v4l2 drivers -
>> au0828.
>> I'll try to test with vivid driver at next round.
>>
> 
> I tried to use vivid for test. But, I have failed to install the
> module (vivid.ko).
> I mainly referred to documentation/video4linux/vivid.txt. But, it
> not enough to test.
> Could you give me a guide?

modprobe vivid no_error_inj=1
v4l2-compliance -d /dev/video0 -s
v4l2-compliance -d /dev/video1 -s

I always forget to pass the module option...

The vivid module has controls for error injection which are all disable with that
module option. Otherwise all the error injection controls would be used by
v4l2-compliance and of course you'd get zillions of errors :-)

Note that you will get two identical failures when testing /dev/video1:

fail: v4l2-test-controls.cpp(243): no controls in class 00f00000

This is a vivid driver bug and you can ignore those two fails.

You also want to test with the vim2m test driver:

modprobe vim2m
v4l2-compliance -d /dev/video2 -s

Regards,

	Hans

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2015-08-31  8:25 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-26 11:59 [RFC PATCH v3 0/5] Refactoring Videobuf2 for common use Junghak Sung
2015-08-26 11:59 ` [RFC PATCH v3 1/5] media: videobuf2: Replace videobuf2-core with videobuf2-v4l2 Junghak Sung
2015-08-27  8:51   ` Mauro Carvalho Chehab
2015-08-26 11:59 ` [RFC PATCH v3 2/5] media: videobuf2: Restructure vb2_buffer Junghak Sung
2015-08-27 10:28   ` Mauro Carvalho Chehab
2015-08-28  1:26     ` Junghak Sung
2015-08-28  9:09       ` Mauro Carvalho Chehab
2015-08-28 13:31   ` Hans Verkuil
2015-08-31  2:01     ` Junghak Sung
2015-08-31  7:56       ` Junghak Sung
2015-08-31  8:24         ` Hans Verkuil
2015-08-26 11:59 ` [RFC PATCH v3 3/5] media: videobuf2: Modify all device drivers Junghak Sung
2015-08-27 10:33   ` Mauro Carvalho Chehab
2015-08-28  2:19     ` Junghak Sung
2015-08-28  9:14       ` Mauro Carvalho Chehab
2015-08-26 11:59 ` [RFC PATCH v3 4/5] media: videobuf2: Change queue_setup argument Junghak Sung
2015-08-27 10:45   ` Mauro Carvalho Chehab
2015-08-26 11:59 ` [RFC PATCH v3 5/5] media: videobuf2: Divide videobuf2-core into 2 parts Junghak Sung
2015-08-27 11:43   ` Mauro Carvalho Chehab
2015-08-28  6:50     ` Junghak Sung
2015-08-28  9:05       ` Mauro Carvalho Chehab
2015-08-28 13:50   ` Hans Verkuil
2015-08-31  2:08     ` Junghak Sung

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).