cron job: media_tree daily build: WARNINGS

2018-08-04 Thread Hans Verkuil
This message is generated daily by a cron job that builds media_tree for
the kernels and architectures in the list below.

Results of the daily build of media_tree:

date:   Sun Aug  5 05:00:10 CEST 2018
media-tree git hash:12f336c88090fb8004736fd4329184326a49673b
media_build git hash:   a0cd9105aaeb5af5af36117af923a3d1de4b76d7
v4l-utils git hash: 70b13df426d30ca58c79cf8a366e73463bb22cbb
edid-decode git hash:   ab18befbcacd6cd4dff63faa82e32700369d6f25
gcc version:i686-linux-gcc (GCC) 8.1.0
sparse version: 0.5.2
smatch version: 0.5.1
host hardware:  x86_64
host os:4.16.0-1-amd64

linux-git-arm-at91: OK
linux-git-arm-davinci: OK
linux-git-arm-multi: OK
linux-git-arm-pxa: OK
linux-git-arm-stm32: OK
linux-git-arm64: OK
linux-git-i686: WARNINGS
linux-git-mips: OK
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: WARNINGS
Check COMPILE_TEST: OK
linux-2.6.36.4-i686: OK
linux-2.6.36.4-x86_64: OK
linux-2.6.37.6-i686: OK
linux-2.6.37.6-x86_64: OK
linux-2.6.38.8-i686: OK
linux-2.6.38.8-x86_64: OK
linux-2.6.39.4-i686: OK
linux-2.6.39.4-x86_64: OK
linux-3.0.101-i686: OK
linux-3.0.101-x86_64: OK
linux-3.1.10-i686: OK
linux-3.1.10-x86_64: OK
linux-3.2.102-i686: OK
linux-3.2.102-x86_64: OK
linux-3.3.8-i686: OK
linux-3.3.8-x86_64: OK
linux-3.4.113-i686: OK
linux-3.4.113-x86_64: OK
linux-3.5.7-i686: OK
linux-3.5.7-x86_64: OK
linux-3.6.11-i686: OK
linux-3.6.11-x86_64: OK
linux-3.7.10-i686: OK
linux-3.7.10-x86_64: OK
linux-3.8.13-i686: OK
linux-3.8.13-x86_64: OK
linux-3.9.11-i686: OK
linux-3.9.11-x86_64: OK
linux-3.10.108-i686: OK
linux-3.10.108-x86_64: OK
linux-3.11.10-i686: OK
linux-3.11.10-x86_64: OK
linux-3.12.74-i686: OK
linux-3.12.74-x86_64: OK
linux-3.13.11-i686: OK
linux-3.13.11-x86_64: OK
linux-3.14.79-i686: OK
linux-3.14.79-x86_64: OK
linux-3.15.10-i686: OK
linux-3.15.10-x86_64: OK
linux-3.16.57-i686: OK
linux-3.16.57-x86_64: OK
linux-3.17.8-i686: OK
linux-3.17.8-x86_64: OK
linux-3.18.115-i686: OK
linux-3.18.115-x86_64: OK
linux-3.19.8-i686: OK
linux-3.19.8-x86_64: OK
linux-4.0.9-i686: OK
linux-4.0.9-x86_64: OK
linux-4.1.52-i686: OK
linux-4.1.52-x86_64: OK
linux-4.2.8-i686: OK
linux-4.2.8-x86_64: OK
linux-4.3.6-i686: OK
linux-4.3.6-x86_64: OK
linux-4.4.140-i686: OK
linux-4.4.140-x86_64: OK
linux-4.5.7-i686: OK
linux-4.5.7-x86_64: OK
linux-4.6.7-i686: OK
linux-4.6.7-x86_64: OK
linux-4.7.10-i686: OK
linux-4.7.10-x86_64: OK
linux-4.8.17-i686: OK
linux-4.8.17-x86_64: OK
linux-4.9.112-i686: OK
linux-4.9.112-x86_64: OK
linux-4.10.17-i686: OK
linux-4.10.17-x86_64: OK
linux-4.11.12-i686: OK
linux-4.11.12-x86_64: OK
linux-4.12.14-i686: OK
linux-4.12.14-x86_64: OK
linux-4.13.16-i686: OK
linux-4.13.16-x86_64: OK
linux-4.14.55-i686: OK
linux-4.14.55-x86_64: OK
linux-4.15.18-i686: OK
linux-4.15.18-x86_64: OK
linux-4.16.18-i686: OK
linux-4.16.18-x86_64: OK
linux-4.17.6-i686: OK
linux-4.17.6-x86_64: OK
linux-4.18-rc4-i686: OK
linux-4.18-rc4-x86_64: OK
apps: OK
spec-git: OK
sparse: WARNINGS

Detailed results are available here:

http://www.xs4all.nl/~hverkuil/logs/Sunday.log

Full logs are available here:

http://www.xs4all.nl/~hverkuil/logs/Sunday.tar.bz2

The Media Infrastructure API from this daily build is here:

http://www.xs4all.nl/~hverkuil/spec/index.html


[ragnatech:media-tree 273/382] drivers/media/i2c/mt9v111.c:801:10: error: implicit declaration of function 'v4l2_subdev_get_try_format'; did you mean 'v4l2_subdev_notify_event'?

2018-08-04 Thread kbuild test robot
tree:   git://git.ragnatech.se/linux media-tree
head:   12f336c88090fb8004736fd4329184326a49673b
commit: aab7ed1c392703604fbdc5bd5005dfb61a0b32f9 [273/382] media: i2c: Add 
driver for Aptina MT9V111
config: x86_64-randconfig-x010-201831 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
git checkout aab7ed1c392703604fbdc5bd5005dfb61a0b32f9
# save the attached .config to linux build tree
make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   drivers/media/i2c/mt9v111.c: In function '__mt9v111_get_pad_format':
>> drivers/media/i2c/mt9v111.c:801:10: error: implicit declaration of function 
>> 'v4l2_subdev_get_try_format'; did you mean 'v4l2_subdev_notify_event'? 
>> [-Werror=implicit-function-declaration]
  return v4l2_subdev_get_try_format(>sd, cfg, pad);
 ^~
 v4l2_subdev_notify_event
>> drivers/media/i2c/mt9v111.c:801:10: warning: return makes pointer from 
>> integer without a cast [-Wint-conversion]
  return v4l2_subdev_get_try_format(>sd, cfg, pad);
 ^~
   drivers/media/i2c/mt9v111.c: In function 'mt9v111_set_format':
   drivers/media/i2c/mt9v111.c:887:15: warning: 'idx' may be used uninitialized 
in this function [-Wmaybe-uninitialized]
 unsigned int idx;
  ^~~
   cc1: some warnings being treated as errors

vim +801 drivers/media/i2c/mt9v111.c

   791  
   792  static struct v4l2_mbus_framefmt *__mt9v111_get_pad_format(
   793  struct mt9v111_dev *mt9v111,
   794  struct v4l2_subdev_pad_config 
*cfg,
   795  unsigned int pad,
   796  enum v4l2_subdev_format_whence 
which)
   797  {
   798  switch (which) {
   799  case V4L2_SUBDEV_FORMAT_TRY:
   800  #if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
 > 801  return v4l2_subdev_get_try_format(>sd, cfg, 
 > pad);
   802  #else
   803  return >try_fmt;
   804  #endif
   805  case V4L2_SUBDEV_FORMAT_ACTIVE:
   806  return >fmt;
   807  default:
   808  return NULL;
   809  }
   810  }
   811  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH v2 1/2] uvcvideo: rename UVC_QUIRK_INFO to UVC_INFO_QUIRK

2018-08-04 Thread Nicolas Dufresne
Le vendredi 03 août 2018 à 13:36 +0200, Guennadi Liakhovetski a écrit :
> This macro defines "information about quirks," not "quirks for
> information."

Does not sound better to me. It's "Quirk's information", vs
"information about quirks". I prefer the first one. In term of C
namespace the orignal is also better. So the name space is UVC_QUIRK,
and the detail is INFO.

If we where to apply your logic, you'd rename driver_info, into
info_driver, because it's information about the driver.

> 
> Signed-off-by: Guennadi Liakhovetski  >
> ---
>  drivers/media/usb/uvc/uvc_driver.c | 18 +-
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/media/usb/uvc/uvc_driver.c
> b/drivers/media/usb/uvc/uvc_driver.c
> index d46dc43..699984b 100644
> --- a/drivers/media/usb/uvc/uvc_driver.c
> +++ b/drivers/media/usb/uvc/uvc_driver.c
> @@ -2344,7 +2344,7 @@ static int uvc_clock_param_set(const char *val,
> const struct kernel_param *kp)
>   .quirks = UVC_QUIRK_FORCE_Y8,
>  };
>  
> -#define UVC_QUIRK_INFO(q) (kernel_ulong_t)&(struct
> uvc_device_info){.quirks = q}
> +#define UVC_INFO_QUIRK(q) (kernel_ulong_t)&(struct
> uvc_device_info){.quirks = q}
>  
>  /*
>   * The Logitech cameras listed below have their interface class set
> to
> @@ -2453,7 +2453,7 @@ static int uvc_clock_param_set(const char *val,
> const struct kernel_param *kp)
> .bInterfaceClass  = USB_CLASS_VIDEO,
> .bInterfaceSubClass   = 1,
> .bInterfaceProtocol   = 0,
> -   .driver_info  =
> UVC_QUIRK_INFO(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) },
> +   .driver_info  =
> UVC_INFO_QUIRK(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) },
>   /* Chicony CNF7129 (Asus EEE 100HE) */
>   { .match_flags  = USB_DEVICE_ID_MATCH_DEVICE
>   | USB_DEVICE_ID_MATCH_INT_INFO,
> @@ -2462,7 +2462,7 @@ static int uvc_clock_param_set(const char *val,
> const struct kernel_param *kp)
> .bInterfaceClass  = USB_CLASS_VIDEO,
> .bInterfaceSubClass   = 1,
> .bInterfaceProtocol   = 0,
> -   .driver_info  =
> UVC_QUIRK_INFO(UVC_QUIRK_RESTRICT_FRAME_RATE) },
> +   .driver_info  =
> UVC_INFO_QUIRK(UVC_QUIRK_RESTRICT_FRAME_RATE) },
>   /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
>   { .match_flags  = USB_DEVICE_ID_MATCH_DEVICE
>   | USB_DEVICE_ID_MATCH_INT_INFO,
> @@ -2525,7 +2525,7 @@ static int uvc_clock_param_set(const char *val,
> const struct kernel_param *kp)
> .bInterfaceClass  = USB_CLASS_VIDEO,
> .bInterfaceSubClass   = 1,
> .bInterfaceProtocol   = 0,
> -   .driver_info  =
> UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX
> +   .driver_info  =
> UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
>   | UVC_QUIRK_BUILTIN_ISIGHT) },
>   /* Apple Built-In iSight via iBridge */
>   { .match_flags  = USB_DEVICE_ID_MATCH_DEVICE
> @@ -2607,7 +2607,7 @@ static int uvc_clock_param_set(const char *val,
> const struct kernel_param *kp)
> .bInterfaceClass  = USB_CLASS_VIDEO,
> .bInterfaceSubClass   = 1,
> .bInterfaceProtocol   = 0,
> -   .driver_info  =
> UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX
> +   .driver_info  =
> UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
>   | UVC_QUIRK_PROBE_DEF) },
>   /* IMC Networks (Medion Akoya) */
>   { .match_flags  = USB_DEVICE_ID_MATCH_DEVICE
> @@ -2707,7 +2707,7 @@ static int uvc_clock_param_set(const char *val,
> const struct kernel_param *kp)
> .bInterfaceClass  = USB_CLASS_VIDEO,
> .bInterfaceSubClass   = 1,
> .bInterfaceProtocol   = 0,
> -   .driver_info  =
> UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX
> +   .driver_info  =
> UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
>   | UVC_QUIRK_PROBE_EXTRAFIELDS)
> },
>   /* Aveo Technology USB 2.0 Camera (Tasco USB Microscope) */
>   { .match_flags  = USB_DEVICE_ID_MATCH_DEVICE
> @@ -2725,7 +2725,7 @@ static int uvc_clock_param_set(const char *val,
> const struct kernel_param *kp)
> .bInterfaceClass  = USB_CLASS_VIDEO,
> .bInterfaceSubClass   = 1,
> .bInterfaceProtocol   = 0,
> -   .driver_info  =
> UVC_QUIRK_INFO(UVC_QUIRK_PROBE_EXTRAFIELDS) },
> +   .driver_info  =
> UVC_INFO_QUIRK(UVC_QUIRK_PROBE_EXTRAFIELDS) },
>   /* Manta MM-353 Plako */
>   { .match_flags  = USB_DEVICE_ID_MATCH_DEVICE
>   | USB_DEVICE_ID_MATCH_INT_INFO,
> @@ -2771,7 +2771,7 @@ static int uvc_clock_param_set(const char *val,
> const struct kernel_param *kp)
> .bInterfaceClass  = USB_CLASS_VIDEO,
> .bInterfaceSubClass   = 1,
> .bInterfaceProtocol   = 0,
> -   .driver_info  =
> UVC_QUIRK_INFO(UVC_QUIRK_STATUS_INTERVAL) },
> +  

[RFC] Request API and V4L2 capabilities

2018-08-04 Thread Hans Verkuil
Hi all,

While the Request API patch series addresses all the core API issues, there
are some high-level considerations as well:

1) How can the application tell that the Request API is supported and for
   which buffer types (capture/output) and pixel formats?

2) How can the application tell if the Request API is required as opposed to 
being
   optional?

3) Some controls may be required in each request, how to let userspace know 
this?
   Is it even necessary to inform userspace?

4) (For bonus points): How to let the application know which streaming I/O modes
   are available? That's never been possible before, but it would be very nice
   indeed if that's made explicit.

Since the Request API associates data with frame buffers it makes sense to 
expose
this as a new capability field in struct v4l2_requestbuffers and struct 
v4l2_create_buffers.

The first struct has 2 reserved fields, the second has 8, so it's not a problem 
to
take one for a capability field. Both structs also have a buffer type, so we 
know
if this is requested for a capture or output buffer type. The pixel format is 
known
in the driver, so HAS/REQUIRES_REQUESTS can be set based on that. I doubt we'll 
have
drivers where the request caps would actually depend on the pixel format, but it
theoretically possible. For both ioctls you can call them with count=0 at the 
start
of the application. REQBUFS has of course the side-effect of deleting all 
buffers,
but at the start of your application you don't have any yet. CREATE_BUFS has no
side-effects.

I propose adding these capabilities:

#define V4L2_BUF_CAP_HAS_REQUESTS   0x0001
#define V4L2_BUF_CAP_REQUIRES_REQUESTS  0x0002
#define V4L2_BUF_CAP_HAS_MMAP   0x0100
#define V4L2_BUF_CAP_HAS_USERPTR0x0200
#define V4L2_BUF_CAP_HAS_DMABUF 0x0400

If REQUIRES_REQUESTS is set, then HAS_REQUESTS is also set.

At this time I think that REQUIRES_REQUESTS would only need to be set for the
output queue of stateless codecs.

If capabilities is 0, then it's from an old kernel and all you know is that
requests are certainly not supported, and that MMAP is supported. Whether 
USERPTR
or DMABUF are supported isn't known in that case (just try it :-) ).

Strictly speaking we do not need these HAS_MMAP/USERPTR/DMABUF caps, but it is 
very
easy to add if we create a new capability field anyway, and it has always 
annoyed
the hell out of me that we didn't have a good way to let userspace know what
streaming I/O modes we support. And with vb2 it's easy to implement.

Regarding point 3: I think this should be documented next to the pixel format. 
I.e.
the MPEG-2 Slice format used by the stateless cedrus codec requires the request 
API
and that two MPEG-2 controls (slice params and quantization matrices) must be 
present
in each request.

I am not sure a control flag (e.g. V4L2_CTRL_FLAG_REQUIRED_IN_REQ) is needed 
here.
It's really implied by the fact that you use a stateless codec. It doesn't help
generic applications like v4l2-ctl or qv4l2 either since in order to support
stateless codecs they will have to know about the details of these controls 
anyway.

So I am inclined to say that it is not necessary to expose this information in
the API, but it has to be documented together with the pixel format 
documentation.

Comments? Ideas?

Regards,

Hans


[PATCHv17 00/34] Request API

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Hi all,

This is version 17 of the Request API series.

The (minor) changes compared to v16 are:

- Incorporated Tomasz' documentation comments.

- Dropped patch 28/34: "v4l2-mem2mem: Simplify exiting the function in
  v4l2_m2m_try_schedule". This is really independent of the Request API
  and is part of a v4l2-mem2mem patch series from Ezequiel Garcia:

  https://www.mail-archive.com/linux-media@vger.kernel.org/msg133969.html

- Added this patch as it is needed by the cedrus driver:
  https://patchwork.linuxtv.org/patch/50771/

- Rebased to the latest master.

The goal is to get this merged together with a staging cedrus driver for
4.20.

This patch series is also available here:

https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=reqv17

The patched v4l2-compliance (and rebased to the latest v4l-utils
as well) is available here:

https://git.linuxtv.org/hverkuil/v4l-utils.git/log/?h=request

Regards,

Hans

Alexandre Courbot (2):
  Documentation: v4l: document request API
  videodev2.h: add request_fd field to v4l2_ext_controls

Hans Verkuil (31):
  uapi/linux/media.h: add request API
  media-request: implement media requests
  media-request: add media_request_get_by_fd
  media-request: add media_request_object_find
  v4l2-device.h: add v4l2_device_supports_requests() helper
  v4l2-dev: lock req_queue_mutex
  v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev
  v4l2-ctrls: prepare internal structs for request API
  v4l2-ctrls: alloc memory for p_req
  v4l2-ctrls: use ref in helper instead of ctrl
  v4l2-ctrls: add core request support
  v4l2-ctrls: support g/s_ext_ctrls for requests
  v4l2-ctrls: add v4l2_ctrl_request_hdl_find/put/ctrl_find functions
  vb2: store userspace data in vb2_v4l2_buffer
  davinci_vpfe: remove bogus vb2->state check
  vb2: drop VB2_BUF_STATE_PREPARED, use bool prepared/synced instead
  videodev2.h: Add request_fd field to v4l2_buffer
  vb2: add init_buffer buffer op
  videobuf2-core: embed media_request_object
  videobuf2-core: integrate with media requests
  videobuf2-v4l2: integrate with media requests
  videobuf2-core: add request helper functions
  videobuf2-v4l2: add vb2_request_queue/validate helpers
  videobuf2-core: add uses_requests/qbuf flags
  videobuf2-v4l2: refuse qbuf if queue uses requests or vv.
  v4l2-mem2mem: add vb2_m2m_request_queue
  vim2m: use workqueue
  vim2m: support requests
  vivid: add mc
  vivid: add request support
  RFC: media-requests: add debugfs node

Sakari Ailus (1):
  media: doc: Add media-request.h header to documentation build

 Documentation/media/kapi/mc-core.rst  |   2 +
 .../media/uapi/mediactl/media-controller.rst  |   1 +
 .../media/uapi/mediactl/media-funcs.rst   |   6 +
 .../uapi/mediactl/media-ioc-request-alloc.rst |  78 +++
 .../uapi/mediactl/media-request-ioc-queue.rst |  82 +++
 .../mediactl/media-request-ioc-reinit.rst |  51 ++
 .../media/uapi/mediactl/request-api.rst   | 247 
 .../uapi/mediactl/request-func-close.rst  |  49 ++
 .../uapi/mediactl/request-func-ioctl.rst  |  68 +++
 .../media/uapi/mediactl/request-func-poll.rst |  77 +++
 Documentation/media/uapi/v4l/buffer.rst   |  21 +-
 .../media/uapi/v4l/vidioc-g-ext-ctrls.rst |  94 ++--
 Documentation/media/uapi/v4l/vidioc-qbuf.rst  |  32 +-
 .../media/videodev2.h.rst.exceptions  |   1 +
 drivers/media/Makefile|   3 +-
 .../media/common/videobuf2/videobuf2-core.c   | 262 +++--
 .../media/common/videobuf2/videobuf2-v4l2.c   | 501 -
 drivers/media/dvb-core/dvb_vb2.c  |   5 +-
 drivers/media/dvb-frontends/rtl2832_sdr.c |   5 +-
 drivers/media/media-device.c  |  55 ++
 drivers/media/media-devnode.c |  17 +
 drivers/media/media-request.c | 493 
 drivers/media/pci/bt8xx/bttv-driver.c |   2 +-
 drivers/media/pci/cx23885/cx23885-417.c   |   2 +-
 drivers/media/pci/cx88/cx88-blackbird.c   |   2 +-
 drivers/media/pci/cx88/cx88-video.c   |   2 +-
 drivers/media/pci/saa7134/saa7134-empress.c   |   4 +-
 drivers/media/pci/saa7134/saa7134-video.c |   2 +-
 .../media/platform/exynos4-is/fimc-capture.c  |   2 +-
 drivers/media/platform/omap3isp/ispvideo.c|   4 +-
 drivers/media/platform/rcar-vin/rcar-core.c   |   2 +-
 drivers/media/platform/rcar_drif.c|   2 +-
 .../media/platform/s3c-camif/camif-capture.c  |   4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c  |   4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c  |   4 +-
 .../media/platform/soc_camera/soc_camera.c|   7 +-
 drivers/media/platform/vim2m.c|  51 +-
 drivers/media/platform/vivid/vivid-core.c |  69 +++
 drivers/media/platform/vivid/vivid-core.h |   8 +
 drivers/media/platform/vivid/vivid-ctrls.c|  46 +-
 .../media/platform/vivid/vivid-kthread-cap.c  |  12 +
 .../media/platform/vivid/vivid-kthread-out.c  |  12 +
 

[PATCHv17 07/34] v4l2-device.h: add v4l2_device_supports_requests() helper

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Add a simple helper function that tests if the driver supports
the request API.

Signed-off-by: Hans Verkuil 
---
 include/media/v4l2-device.h | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h
index b330e4a08a6b..ac7677a183ff 100644
--- a/include/media/v4l2-device.h
+++ b/include/media/v4l2-device.h
@@ -211,6 +211,17 @@ static inline void v4l2_subdev_notify(struct v4l2_subdev 
*sd,
sd->v4l2_dev->notify(sd, notification, arg);
 }
 
+/**
+ * v4l2_device_supports_requests - Test if requests are supported.
+ *
+ * @v4l2_dev: pointer to struct v4l2_device
+ */
+static inline bool v4l2_device_supports_requests(struct v4l2_device *v4l2_dev)
+{
+   return v4l2_dev->mdev && v4l2_dev->mdev->ops &&
+  v4l2_dev->mdev->ops->req_queue;
+}
+
 /* Helper macros to iterate over all subdevs. */
 
 /**
-- 
2.18.0



[PATCHv17 06/34] media-request: add media_request_object_find

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Add media_request_object_find to find a request object inside a
request based on ops and priv values.

Objects of the same type (vb2 buffer, control handler) will have
the same ops value. And objects that refer to the same 'parent'
object (e.g. the v4l2_ctrl_handler that has the current driver
state) will have the same priv value.

The caller has to call media_request_object_put() for the returned
object since this function increments the refcount.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
---
 drivers/media/media-request.c | 25 +
 include/media/media-request.h | 28 
 2 files changed, 53 insertions(+)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index 4b523f3a03a3..a5b70a4e613b 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -344,6 +344,31 @@ static void media_request_object_release(struct kref *kref)
obj->ops->release(obj);
 }
 
+struct media_request_object *
+media_request_object_find(struct media_request *req,
+ const struct media_request_object_ops *ops,
+ void *priv)
+{
+   struct media_request_object *obj;
+   struct media_request_object *found = NULL;
+   unsigned long flags;
+
+   if (WARN_ON(!ops || !priv))
+   return NULL;
+
+   spin_lock_irqsave(>lock, flags);
+   list_for_each_entry(obj, >objects, list) {
+   if (obj->ops == ops && obj->priv == priv) {
+   media_request_object_get(obj);
+   found = obj;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(>lock, flags);
+   return found;
+}
+EXPORT_SYMBOL_GPL(media_request_object_find);
+
 void media_request_object_put(struct media_request_object *obj)
 {
kref_put(>kref, media_request_object_release);
diff --git a/include/media/media-request.h b/include/media/media-request.h
index 66ec9d09fcd8..fd08d7a431a1 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -253,6 +253,26 @@ static inline void media_request_object_get(struct 
media_request_object *obj)
  */
 void media_request_object_put(struct media_request_object *obj);
 
+/**
+ * media_request_object_find - Find an object in a request
+ *
+ * @req: The media request
+ * @ops: Find an object with this ops value
+ * @priv: Find an object with this priv value
+ *
+ * Both @ops and @priv must be non-NULL.
+ *
+ * Returns the object pointer or NULL if not found. The caller must
+ * call media_request_object_put() once it finished using the object.
+ *
+ * Since this function needs to walk the list of objects it takes
+ * the @req->lock spin lock to make this safe.
+ */
+struct media_request_object *
+media_request_object_find(struct media_request *req,
+ const struct media_request_object_ops *ops,
+ void *priv);
+
 /**
  * media_request_object_init - Initialise a media request object
  *
@@ -324,6 +344,14 @@ static inline void media_request_object_put(struct 
media_request_object *obj)
 {
 }
 
+static inline struct media_request_object *
+media_request_object_find(struct media_request *req,
+ const struct media_request_object_ops *ops,
+ void *priv)
+{
+   return NULL;
+}
+
 static inline void media_request_object_init(struct media_request_object *obj)
 {
obj->ops = NULL;
-- 
2.18.0



[PATCHv17 11/34] v4l2-ctrls: prepare internal structs for request API

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Embed and initialize a media_request_object in struct v4l2_ctrl_handler.

Add a p_req field to struct v4l2_ctrl_ref that will store the
request value.

Signed-off-by: Hans Verkuil 
Signed-off-by: Alexandre Courbot 
---
 drivers/media/v4l2-core/v4l2-ctrls.c |  1 +
 include/media/v4l2-ctrls.h   | 10 ++
 2 files changed, 11 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index 404291f00715..b33a8bee82b0 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1901,6 +1901,7 @@ int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler 
*hdl,
  sizeof(hdl->buckets[0]),
  GFP_KERNEL | __GFP_ZERO);
hdl->error = hdl->buckets ? 0 : -ENOMEM;
+   media_request_object_init(>req_obj);
return hdl->error;
 }
 EXPORT_SYMBOL(v4l2_ctrl_handler_init_class);
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 192e31c21faf..3f4e062d4e3d 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* forward references */
 struct file;
@@ -249,6 +250,11 @@ struct v4l2_ctrl {
  * ``prepare_ext_ctrls`` function at ``v4l2-ctrl.c``.
  * @from_other_dev: If true, then @ctrl was defined in another
  * device than the  v4l2_ctrl_handler.
+ * @p_req: If the control handler containing this control reference
+ * is bound to a media request, then this points to the
+ * value of the control that should be applied when the request
+ * is executed, or to the value of the control at the time
+ * that the request was completed.
  *
  * Each control handler has a list of these refs. The list_head is used to
  * keep a sorted-by-control-ID list of all controls, while the next pointer
@@ -260,6 +266,7 @@ struct v4l2_ctrl_ref {
struct v4l2_ctrl *ctrl;
struct v4l2_ctrl_helper *helper;
bool from_other_dev;
+   union v4l2_ctrl_ptr p_req;
 };
 
 /**
@@ -283,6 +290,8 @@ struct v4l2_ctrl_ref {
  * @notify_priv: Passed as argument to the v4l2_ctrl notify callback.
  * @nr_of_buckets: Total number of buckets in the array.
  * @error: The error code of the first failed control addition.
+ * @req_obj:   The  media_request_object, used to link into a
+ *  media_request. This request object has a refcount.
  */
 struct v4l2_ctrl_handler {
struct mutex _lock;
@@ -295,6 +304,7 @@ struct v4l2_ctrl_handler {
void *notify_priv;
u16 nr_of_buckets;
int error;
+   struct media_request_object req_obj;
 };
 
 /**
-- 
2.18.0



[PATCHv17 18/34] davinci_vpfe: remove bogus vb2->state check

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

There is no need to check the vb2 state in the buf_prepare
callback: it can never be wrong.

Since VB2_BUF_STATE_PREPARED will be removed in the next patch
we'll remove this unnecessary check (and use of that state) first.

Signed-off-by: Hans Verkuil 
---
 drivers/staging/media/davinci_vpfe/vpfe_video.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c 
b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index 1269a983455e..4e3ec7fdc90d 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -1135,10 +1135,6 @@ static int vpfe_buffer_prepare(struct vb2_buffer *vb)
 
v4l2_dbg(1, debug, _dev->v4l2_dev, "vpfe_buffer_prepare\n");
 
-   if (vb->state != VB2_BUF_STATE_ACTIVE &&
-   vb->state != VB2_BUF_STATE_PREPARED)
-   return 0;
-
/* Initialize buffer */
vb2_set_plane_payload(vb, 0, video->fmt.fmt.pix.sizeimage);
if (vb2_plane_vaddr(vb, 0) &&
-- 
2.18.0



[PATCHv17 12/34] v4l2-ctrls: alloc memory for p_req

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

To store request data the handler_new_ref() allocates memory
for it if needed.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index b33a8bee82b0..171ab389afdd 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -2018,13 +2018,18 @@ EXPORT_SYMBOL(v4l2_ctrl_find);
 /* Allocate a new v4l2_ctrl_ref and hook it into the handler. */
 static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
   struct v4l2_ctrl *ctrl,
-  bool from_other_dev)
+  struct v4l2_ctrl_ref **ctrl_ref,
+  bool from_other_dev, bool allocate_req)
 {
struct v4l2_ctrl_ref *ref;
struct v4l2_ctrl_ref *new_ref;
u32 id = ctrl->id;
u32 class_ctrl = V4L2_CTRL_ID2WHICH(id) | 1;
int bucket = id % hdl->nr_of_buckets;   /* which bucket to use */
+   unsigned int sz_extra = 0;
+
+   if (ctrl_ref)
+   *ctrl_ref = NULL;
 
/*
 * Automatically add the control class if it is not yet present and
@@ -2038,11 +2043,16 @@ static int handler_new_ref(struct v4l2_ctrl_handler 
*hdl,
if (hdl->error)
return hdl->error;
 
-   new_ref = kzalloc(sizeof(*new_ref), GFP_KERNEL);
+   if (allocate_req)
+   sz_extra = ctrl->elems * ctrl->elem_size;
+   new_ref = kzalloc(sizeof(*new_ref) + sz_extra, GFP_KERNEL);
if (!new_ref)
return handler_set_err(hdl, -ENOMEM);
new_ref->ctrl = ctrl;
new_ref->from_other_dev = from_other_dev;
+   if (sz_extra)
+   new_ref->p_req.p = _ref[1];
+
if (ctrl->handler == hdl) {
/* By default each control starts in a cluster of its own.
   new_ref->ctrl is basically a cluster array with one
@@ -2082,6 +2092,8 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
/* Insert the control node in the hash */
new_ref->next = hdl->buckets[bucket];
hdl->buckets[bucket] = new_ref;
+   if (ctrl_ref)
+   *ctrl_ref = new_ref;
 
 unlock:
mutex_unlock(hdl->lock);
@@ -2223,7 +2235,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct 
v4l2_ctrl_handler *hdl,
ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
}
 
-   if (handler_new_ref(hdl, ctrl, false)) {
+   if (handler_new_ref(hdl, ctrl, NULL, false, false)) {
kvfree(ctrl);
return NULL;
}
@@ -2416,7 +2428,7 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
/* Filter any unwanted controls */
if (filter && !filter(ctrl))
continue;
-   ret = handler_new_ref(hdl, ctrl, from_other_dev);
+   ret = handler_new_ref(hdl, ctrl, NULL, from_other_dev, false);
if (ret)
break;
}
-- 
2.18.0



[PATCHv17 10/34] v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Add a 'bool from_other_dev' argument: set to true if the two
handlers refer to different devices (e.g. it is true when
inheriting controls from a subdev into a main v4l2 bridge
driver).

This will be used later when implementing support for the
request API since we need to skip such controls.

Signed-off-by: Hans Verkuil 
Signed-off-by: Alexandre Courbot 
---
 drivers/media/dvb-frontends/rtl2832_sdr.c |  5 +-
 drivers/media/pci/bt8xx/bttv-driver.c |  2 +-
 drivers/media/pci/cx23885/cx23885-417.c   |  2 +-
 drivers/media/pci/cx88/cx88-blackbird.c   |  2 +-
 drivers/media/pci/cx88/cx88-video.c   |  2 +-
 drivers/media/pci/saa7134/saa7134-empress.c   |  4 +-
 drivers/media/pci/saa7134/saa7134-video.c |  2 +-
 .../media/platform/exynos4-is/fimc-capture.c  |  2 +-
 drivers/media/platform/rcar-vin/rcar-core.c   |  2 +-
 drivers/media/platform/rcar_drif.c|  2 +-
 .../media/platform/soc_camera/soc_camera.c|  3 +-
 drivers/media/platform/vivid/vivid-ctrls.c| 46 +--
 drivers/media/usb/cx231xx/cx231xx-417.c   |  2 +-
 drivers/media/usb/cx231xx/cx231xx-video.c |  4 +-
 drivers/media/usb/msi2500/msi2500.c   |  2 +-
 drivers/media/usb/tm6000/tm6000-video.c   |  2 +-
 drivers/media/v4l2-core/v4l2-ctrls.c  | 11 +++--
 drivers/media/v4l2-core/v4l2-device.c |  3 +-
 drivers/staging/media/imx/imx-media-dev.c |  2 +-
 drivers/staging/media/imx/imx-media-fim.c |  2 +-
 include/media/v4l2-ctrls.h|  8 +++-
 21 files changed, 61 insertions(+), 49 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c 
b/drivers/media/dvb-frontends/rtl2832_sdr.c
index d448d9d4879c..7d0c89e269ab 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -1394,7 +1394,8 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
case RTL2832_SDR_TUNER_E4000:
v4l2_ctrl_handler_init(>hdl, 9);
if (subdev)
-   v4l2_ctrl_add_handler(>hdl, subdev->ctrl_handler, 
NULL);
+   v4l2_ctrl_add_handler(>hdl, subdev->ctrl_handler,
+ NULL, true);
break;
case RTL2832_SDR_TUNER_R820T:
case RTL2832_SDR_TUNER_R828D:
@@ -1423,7 +1424,7 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
v4l2_ctrl_handler_init(>hdl, 2);
if (subdev)
v4l2_ctrl_add_handler(>hdl, subdev->ctrl_handler,
- NULL);
+ NULL, true);
break;
default:
v4l2_ctrl_handler_init(>hdl, 0);
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c 
b/drivers/media/pci/bt8xx/bttv-driver.c
index cf05e11da01b..e86154092558 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -4211,7 +4211,7 @@ static int bttv_probe(struct pci_dev *dev, const struct 
pci_device_id *pci_id)
/* register video4linux + input */
if (!bttv_tvcards[btv->c.type].no_video) {
v4l2_ctrl_add_handler(>radio_ctrl_handler, hdl,
-   v4l2_ctrl_radio_filter);
+   v4l2_ctrl_radio_filter, false);
if (btv->radio_ctrl_handler.error) {
result = btv->radio_ctrl_handler.error;
goto fail2;
diff --git a/drivers/media/pci/cx23885/cx23885-417.c 
b/drivers/media/pci/cx23885/cx23885-417.c
index a71f3c7569ce..762823871c78 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1527,7 +1527,7 @@ int cx23885_417_register(struct cx23885_dev *dev)
dev->cxhdl.priv = dev;
dev->cxhdl.func = cx23885_api_func;
cx2341x_handler_set_50hz(>cxhdl, tsport->height == 576);
-   v4l2_ctrl_add_handler(>ctrl_handler, >cxhdl.hdl, NULL);
+   v4l2_ctrl_add_handler(>ctrl_handler, >cxhdl.hdl, NULL, false);
 
/* Allocate and initialize V4L video device */
dev->v4l_device = cx23885_video_dev_alloc(tsport,
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c 
b/drivers/media/pci/cx88/cx88-blackbird.c
index 7a4876cf9f08..722dd101c9b0 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -1183,7 +1183,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver 
*drv)
err = cx2341x_handler_init(>cxhdl, 36);
if (err)
goto fail_core;
-   v4l2_ctrl_add_handler(>cxhdl.hdl, >video_hdl, NULL);
+   v4l2_ctrl_add_handler(>cxhdl.hdl, >video_hdl, NULL, false);
 
/* blackbird stuff */
pr_info("cx23416 based mpeg encoder (blackbird reference design)\n");
diff --git a/drivers/media/pci/cx88/cx88-video.c 
b/drivers/media/pci/cx88/cx88-video.c
index 

[PATCHv17 22/34] videobuf2-core: embed media_request_object

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Make vb2_buffer a request object.

Signed-off-by: Hans Verkuil 
---
 include/media/videobuf2-core.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index cbda3968d018..df92dcdeabb3 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define VB2_MAX_FRAME  (32)
 #define VB2_MAX_PLANES (8)
@@ -236,6 +237,8 @@ struct vb2_queue;
  * @num_planes:number of planes in the buffer
  * on an internal driver queue.
  * @timestamp: frame timestamp in ns.
+ * @req_obj:   used to bind this buffer to a request. This
+ * request object has a refcount.
  */
 struct vb2_buffer {
struct vb2_queue*vb2_queue;
@@ -244,6 +247,7 @@ struct vb2_buffer {
unsigned intmemory;
unsigned intnum_planes;
u64 timestamp;
+   struct media_request_object req_obj;
 
/* private: internal use only
 *
-- 
2.18.0



[PATCHv17 03/34] media-request: implement media requests

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Add initial media request support:

1) Add MEDIA_IOC_REQUEST_ALLOC ioctl support to media-device.c
2) Add struct media_request to store request objects.
3) Add struct media_request_object to represent a request object.
4) Add MEDIA_REQUEST_IOC_QUEUE/REINIT ioctl support.

Basic lifecycle: the application allocates a request, adds
objects to it, queues the request, polls until it is completed
and can then read the final values of the objects at the time
of completion. When it closes the file descriptor the request
memory will be freed (actually, when the last user of that request
releases the request).

Drivers will bind an object to a request (the 'adds objects to it'
phase), when MEDIA_REQUEST_IOC_QUEUE is called the request is
validated (req_validate op), then queued (the req_queue op).

When done with an object it can either be unbound from the request
(e.g. when the driver has finished with a vb2 buffer) or marked as
completed (e.g. for controls associated with a buffer). When all
objects in the request are completed (or unbound), then the request
fd will signal an exception (poll).

Signed-off-by: Hans Verkuil 
Co-developed-by: Sakari Ailus 
Signed-off-by: Sakari Ailus 
Co-developed-by: Laurent Pinchart 
Co-developed-by: Alexandre Courbot 
---
 drivers/media/Makefile|   3 +-
 drivers/media/media-device.c  |  14 ++
 drivers/media/media-request.c | 423 ++
 include/media/media-device.h  |  21 ++
 include/media/media-request.h | 327 ++
 5 files changed, 787 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/media-request.c
 create mode 100644 include/media/media-request.h

diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 594b462ddf0e..985d35ec6b29 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -3,7 +3,8 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-media-objs := media-device.o media-devnode.o media-entity.o
+media-objs := media-device.o media-devnode.o media-entity.o \
+  media-request.o
 
 #
 # I2C drivers should come before other drivers, otherwise they'll fail
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index fcdf3d5dc4b6..4b9a8de05562 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_MEDIA_CONTROLLER
 
@@ -377,6 +378,15 @@ static long media_device_get_topology(struct media_device 
*mdev, void *arg)
return ret;
 }
 
+static long media_device_request_alloc(struct media_device *mdev,
+  struct media_request_alloc *alloc)
+{
+   if (!mdev->ops || !mdev->ops->req_validate || !mdev->ops->req_queue)
+   return -ENOTTY;
+
+   return media_request_alloc(mdev, alloc);
+}
+
 static long copy_arg_from_user(void *karg, void __user *uarg, unsigned int cmd)
 {
/* All media IOCTLs are _IOWR() */
@@ -425,6 +435,7 @@ static const struct media_ioctl_info ioctl_info[] = {
MEDIA_IOC(ENUM_LINKS, media_device_enum_links, 
MEDIA_IOC_FL_GRAPH_MUTEX),
MEDIA_IOC(SETUP_LINK, media_device_setup_link, 
MEDIA_IOC_FL_GRAPH_MUTEX),
MEDIA_IOC(G_TOPOLOGY, media_device_get_topology, 
MEDIA_IOC_FL_GRAPH_MUTEX),
+   MEDIA_IOC(REQUEST_ALLOC, media_device_request_alloc, 0),
 };
 
 static long media_device_ioctl(struct file *filp, unsigned int cmd,
@@ -697,6 +708,8 @@ void media_device_init(struct media_device *mdev)
INIT_LIST_HEAD(>pads);
INIT_LIST_HEAD(>links);
INIT_LIST_HEAD(>entity_notify);
+
+   mutex_init(>req_queue_mutex);
mutex_init(>graph_mutex);
ida_init(>entity_internal_idx);
 
@@ -710,6 +723,7 @@ void media_device_cleanup(struct media_device *mdev)
mdev->entity_internal_idx_max = 0;
media_graph_walk_cleanup(>pm_count_walk);
mutex_destroy(>graph_mutex);
+   mutex_destroy(>req_queue_mutex);
 }
 EXPORT_SYMBOL_GPL(media_device_cleanup);
 
diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
new file mode 100644
index ..253068f51a1f
--- /dev/null
+++ b/drivers/media/media-request.c
@@ -0,0 +1,423 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Media device request objects
+ *
+ * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights 
reserved.
+ * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 Google, Inc.
+ *
+ * Author: Hans Verkuil 
+ * Author: Sakari Ailus 
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+static const char * const request_state[] = {
+   [MEDIA_REQUEST_STATE_IDLE]   = "idle",
+   [MEDIA_REQUEST_STATE_VALIDATING] = "validating",
+   [MEDIA_REQUEST_STATE_QUEUED] = "queued",
+   [MEDIA_REQUEST_STATE_COMPLETE]   = "complete",
+   [MEDIA_REQUEST_STATE_CLEANING]   = "cleaning",
+   [MEDIA_REQUEST_STATE_UPDATING]   = "updating",

[PATCHv17 13/34] v4l2-ctrls: use ref in helper instead of ctrl

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

The next patch needs the reference to a control instead of the
control itself, so change struct v4l2_ctrl_helper accordingly.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index 171ab389afdd..570b6f8ae46a 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -37,8 +37,8 @@
 struct v4l2_ctrl_helper {
/* Pointer to the control reference of the master control */
struct v4l2_ctrl_ref *mref;
-   /* The control corresponding to the v4l2_ext_control ID field. */
-   struct v4l2_ctrl *ctrl;
+   /* The control ref corresponding to the v4l2_ext_control ID field. */
+   struct v4l2_ctrl_ref *ref;
/* v4l2_ext_control index of the next control belonging to the
   same cluster, or 0 if there isn't any. */
u32 next;
@@ -2908,6 +2908,7 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler 
*hdl,
ref = find_ref_lock(hdl, id);
if (ref == NULL)
return -EINVAL;
+   h->ref = ref;
ctrl = ref->ctrl;
if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED)
return -EINVAL;
@@ -2930,7 +2931,6 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler 
*hdl,
}
/* Store the ref to the master control of the cluster */
h->mref = ref;
-   h->ctrl = ctrl;
/* Initially set next to 0, meaning that there is no other
   control in this helper array belonging to the same
   cluster */
@@ -3015,7 +3015,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
cs->error_idx = cs->count;
 
for (i = 0; !ret && i < cs->count; i++)
-   if (helpers[i].ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
+   if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
ret = -EACCES;
 
for (i = 0; !ret && i < cs->count; i++) {
@@ -3050,7 +3050,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
 
do {
ret = ctrl_to_user(cs->controls + idx,
-  helpers[idx].ctrl);
+  helpers[idx].ref->ctrl);
idx = helpers[idx].next;
} while (!ret && idx);
}
@@ -3202,7 +3202,7 @@ static int validate_ctrls(struct v4l2_ext_controls *cs,
 
cs->error_idx = cs->count;
for (i = 0; i < cs->count; i++) {
-   struct v4l2_ctrl *ctrl = helpers[i].ctrl;
+   struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl;
union v4l2_ctrl_ptr p_new;
 
cs->error_idx = i;
@@ -3314,7 +3314,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
do {
/* Check if the auto control is part of the
   list, and remember the new value. */
-   if (helpers[tmp_idx].ctrl == master)
+   if (helpers[tmp_idx].ref->ctrl == master)
new_auto_val = 
cs->controls[tmp_idx].value;
tmp_idx = helpers[tmp_idx].next;
} while (tmp_idx);
@@ -3327,7 +3327,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
/* Copy the new caller-supplied control values.
   user_to_new() sets 'is_new' to 1. */
do {
-   struct v4l2_ctrl *ctrl = helpers[idx].ctrl;
+   struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl;
 
ret = user_to_new(cs->controls + idx, ctrl);
if (!ret && ctrl->is_ptr)
@@ -3343,7 +3343,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
idx = i;
do {
ret = new_to_user(cs->controls + idx,
-   helpers[idx].ctrl);
+   helpers[idx].ref->ctrl);
idx = helpers[idx].next;
} while (!ret && idx);
}
-- 
2.18.0



[PATCHv17 15/34] v4l2-ctrls: support g/s_ext_ctrls for requests

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

The v4l2_g/s_ext_ctrls functions now support control handlers that
represent requests.

The v4l2_ctrls_find_req_obj() function is responsible for finding the
request from the fd.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/omap3isp/ispvideo.c |   2 +-
 drivers/media/v4l2-core/v4l2-ctrls.c   | 138 +++--
 drivers/media/v4l2-core/v4l2-ioctl.c   |  12 +-
 drivers/media/v4l2-core/v4l2-subdev.c  |   9 +-
 include/media/v4l2-ctrls.h |   7 +-
 5 files changed, 149 insertions(+), 19 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispvideo.c 
b/drivers/media/platform/omap3isp/ispvideo.c
index 9d228eac24ea..674e7fd3ad99 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -1028,7 +1028,7 @@ static int isp_video_check_external_subdevs(struct 
isp_video *video,
ctrls.count = 1;
ctrls.controls = 
 
-   ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, );
+   ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, NULL, );
if (ret < 0) {
dev_warn(isp->dev, "no pixel rate control in subdev %s\n",
 pipe->external->name);
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index b8ff6d6b14cd..86a6ae54ccaa 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -3140,7 +3140,8 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 
which)
 }
 
 /* Get extended controls. Allocates the helpers array if needed. */
-int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls 
*cs)
+int __v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl,
+  struct v4l2_ext_controls *cs)
 {
struct v4l2_ctrl_helper helper[4];
struct v4l2_ctrl_helper *helpers = helper;
@@ -3220,6 +3221,83 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
kvfree(helpers);
return ret;
 }
+
+static struct media_request_object *
+v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
+   struct media_request *req, bool set)
+{
+   struct media_request_object *obj;
+   struct v4l2_ctrl_handler *new_hdl;
+   int ret;
+
+   if (IS_ERR(req))
+   return ERR_CAST(req);
+
+   if (set && WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING))
+   return ERR_PTR(-EBUSY);
+
+   obj = media_request_object_find(req, _ops, hdl);
+   if (obj)
+   return obj;
+   if (!set)
+   return ERR_PTR(-ENOENT);
+
+   new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL);
+   if (!new_hdl)
+   return ERR_PTR(-ENOMEM);
+
+   obj = _hdl->req_obj;
+   ret = v4l2_ctrl_handler_init(new_hdl, (hdl->nr_of_buckets - 1) * 8);
+   if (!ret)
+   ret = v4l2_ctrl_request_bind(req, new_hdl, hdl);
+   if (ret) {
+   kfree(new_hdl);
+
+   return ERR_PTR(ret);
+   }
+
+   media_request_object_get(obj);
+   return obj;
+}
+
+int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev,
+struct v4l2_ext_controls *cs)
+{
+   struct media_request_object *obj = NULL;
+   int ret;
+
+   if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) {
+   struct media_request *req;
+
+   if (!mdev || cs->request_fd < 0)
+   return -EINVAL;
+
+   req = media_request_get_by_fd(mdev, cs->request_fd);
+   if (IS_ERR(req))
+   return PTR_ERR(req);
+
+   if (req->state != MEDIA_REQUEST_STATE_IDLE &&
+   req->state != MEDIA_REQUEST_STATE_COMPLETE) {
+   media_request_put(req);
+   return -EBUSY;
+   }
+
+   obj = v4l2_ctrls_find_req_obj(hdl, req, false);
+   /* Reference to the request held through obj */
+   media_request_put(req);
+   if (IS_ERR(obj))
+   return PTR_ERR(obj);
+
+   hdl = container_of(obj, struct v4l2_ctrl_handler,
+  req_obj);
+   }
+
+   ret = __v4l2_g_ext_ctrls(hdl, cs);
+
+   if (obj)
+   media_request_object_put(obj);
+   return ret;
+}
 EXPORT_SYMBOL(v4l2_g_ext_ctrls);
 
 /* Helper function to get a single control */
@@ -3408,9 +3486,9 @@ static void update_from_auto_cluster(struct v4l2_ctrl 
*master)
 }
 
 /* Try or try-and-set controls */
-static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
-struct v4l2_ext_controls *cs,
-bool set)
+static int __try_set_ext_ctrls(struct v4l2_fh *fh,
+  struct v4l2_ctrl_handler *hdl,
+  struct v4l2_ext_controls *cs, bool 

[PATCHv17 34/34] RFC: media-requests: add debugfs node

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Keep track of the number of requests and request objects of a media
device. Helps to verify that all request-related memory is freed.

Signed-off-by: Hans Verkuil 
---
 drivers/media/media-device.c  | 41 +++
 drivers/media/media-devnode.c | 17 +++
 drivers/media/media-request.c |  5 +
 include/media/media-device.h  | 11 ++
 include/media/media-devnode.h |  4 
 include/media/media-request.h |  2 ++
 6 files changed, 80 insertions(+)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 4b9a8de05562..28a891b53886 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -691,6 +691,23 @@ void media_device_unregister_entity(struct media_entity 
*entity)
 }
 EXPORT_SYMBOL_GPL(media_device_unregister_entity);
 
+#ifdef CONFIG_DEBUG_FS
+/*
+ * Log the state of media requests.
+ * Very useful for debugging.
+ */
+static int media_device_requests(struct seq_file *file, void *priv)
+{
+   struct media_device *dev = dev_get_drvdata(file->private);
+
+   seq_printf(file, "number of requests: %d\n",
+  atomic_read(>num_requests));
+   seq_printf(file, "number of request objects: %d\n",
+  atomic_read(>num_request_objects));
+   return 0;
+}
+#endif
+
 /**
  * media_device_init() - initialize a media device
  * @mdev:  The media device
@@ -713,6 +730,9 @@ void media_device_init(struct media_device *mdev)
mutex_init(>graph_mutex);
ida_init(>entity_internal_idx);
 
+   atomic_set(>num_requests, 0);
+   atomic_set(>num_request_objects, 0);
+
dev_dbg(mdev->dev, "Media device initialized\n");
 }
 EXPORT_SYMBOL_GPL(media_device_init);
@@ -764,6 +784,26 @@ int __must_check __media_device_register(struct 
media_device *mdev,
 
dev_dbg(mdev->dev, "Media device registered\n");
 
+#ifdef CONFIG_DEBUG_FS
+   if (!media_top_dir)
+   return 0;
+
+   mdev->media_dir = debugfs_create_dir(dev_name(>dev),
+media_top_dir);
+   if (IS_ERR_OR_NULL(mdev->media_dir)) {
+   dev_warn(mdev->dev, "Failed to create debugfs dir\n");
+   return 0;
+   }
+   mdev->requests_file = debugfs_create_devm_seqfile(>dev,
+   "requests", mdev->media_dir, media_device_requests);
+   if (IS_ERR_OR_NULL(mdev->requests_file)) {
+   dev_warn(mdev->dev, "Failed to create requests file\n");
+   debugfs_remove_recursive(mdev->media_dir);
+   mdev->media_dir = NULL;
+   return 0;
+   }
+#endif
+
return 0;
 }
 EXPORT_SYMBOL_GPL(__media_device_register);
@@ -841,6 +881,7 @@ void media_device_unregister(struct media_device *mdev)
 
dev_dbg(mdev->dev, "Media device unregistered\n");
 
+   debugfs_remove_recursive(mdev->media_dir);
device_remove_file(>devnode->dev, _attr_model);
media_devnode_unregister(mdev->devnode);
/* devnode free is handled in media_devnode_*() */
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 6b87a721dc49..4358ed22f208 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -53,6 +53,12 @@ static dev_t media_dev_t;
 static DEFINE_MUTEX(media_devnode_lock);
 static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
 
+/*
+ * debugfs
+ */
+struct dentry *media_top_dir;
+
+
 /* Called when the last user of the media device exits. */
 static void media_devnode_release(struct device *cd)
 {
@@ -259,6 +265,8 @@ int __must_check media_devnode_register(struct media_device 
*mdev,
goto cdev_add_error;
}
 
+   dev_set_drvdata(>dev, mdev);
+
/* Part 4: Activate this minor. The char device can now be used. */
set_bit(MEDIA_FLAG_REGISTERED, >flags);
 
@@ -310,6 +318,14 @@ static int __init media_devnode_init(void)
return ret;
}
 
+#ifdef CONFIG_DEBUG_FS
+   media_top_dir = debugfs_create_dir("media", NULL);
+   if (IS_ERR_OR_NULL(media_top_dir)) {
+   pr_warn("Failed to create debugfs media dir\n");
+   media_top_dir = NULL;
+   }
+#endif
+
ret = bus_register(_bus_type);
if (ret < 0) {
unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
@@ -322,6 +338,7 @@ static int __init media_devnode_init(void)
 
 static void __exit media_devnode_exit(void)
 {
+   debugfs_remove_recursive(media_top_dir);
bus_unregister(_bus_type);
unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
 }
diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index a5b70a4e613b..8ba97a9c4bf1 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -72,6 +72,7 @@ static void media_request_release(struct kref *kref)
mdev->ops->req_free(req);
else
kfree(req);
+  

[PATCHv17 23/34] videobuf2-core: integrate with media requests

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Buffers can now be prepared or queued for a request.

A buffer is unbound from the request at vb2_buffer_done time or
when the queue is cancelled.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-core.c   | 133 +-
 .../media/common/videobuf2/videobuf2-v4l2.c   |   4 +-
 drivers/media/dvb-core/dvb_vb2.c  |   2 +-
 include/media/videobuf2-core.h|  18 ++-
 4 files changed, 147 insertions(+), 10 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 230f83d6d094..1efb9c8b359d 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -499,8 +499,9 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned 
int buffers)
pr_info(" buf_init: %u buf_cleanup: %u buf_prepare: 
%u buf_finish: %u\n",
vb->cnt_buf_init, vb->cnt_buf_cleanup,
vb->cnt_buf_prepare, vb->cnt_buf_finish);
-   pr_info(" buf_queue: %u buf_done: %u\n",
-   vb->cnt_buf_queue, vb->cnt_buf_done);
+   pr_info(" buf_queue: %u buf_done: %u 
buf_request_complete: %u\n",
+   vb->cnt_buf_queue, vb->cnt_buf_done,
+   vb->cnt_buf_request_complete);
pr_info(" alloc: %u put: %u prepare: %u finish: %u 
mmap: %u\n",
vb->cnt_mem_alloc, vb->cnt_mem_put,
vb->cnt_mem_prepare, vb->cnt_mem_finish,
@@ -936,6 +937,14 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum 
vb2_buffer_state state)
vb->state = state;
}
atomic_dec(>owned_by_drv_count);
+
+   if (vb->req_obj.req) {
+   /* This is not supported at the moment */
+   WARN_ON(state == VB2_BUF_STATE_REQUEUEING);
+   media_request_object_unbind(>req_obj);
+   media_request_object_put(>req_obj);
+   }
+
spin_unlock_irqrestore(>done_lock, flags);
 
trace_vb2_buf_done(q, vb);
@@ -1290,6 +1299,60 @@ static int __buf_prepare(struct vb2_buffer *vb)
return 0;
 }
 
+static int vb2_req_prepare(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+   int ret;
+
+   if (WARN_ON(vb->state != VB2_BUF_STATE_IN_REQUEST))
+   return -EINVAL;
+
+   mutex_lock(vb->vb2_queue->lock);
+   ret = __buf_prepare(vb);
+   mutex_unlock(vb->vb2_queue->lock);
+   return ret;
+}
+
+static void __vb2_dqbuf(struct vb2_buffer *vb);
+
+static void vb2_req_unprepare(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   mutex_lock(vb->vb2_queue->lock);
+   __vb2_dqbuf(vb);
+   vb->state = VB2_BUF_STATE_IN_REQUEST;
+   mutex_unlock(vb->vb2_queue->lock);
+   WARN_ON(!vb->req_obj.req);
+}
+
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
+ struct media_request *req);
+
+static void vb2_req_queue(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   mutex_lock(vb->vb2_queue->lock);
+   vb2_core_qbuf(vb->vb2_queue, vb->index, NULL, NULL);
+   mutex_unlock(vb->vb2_queue->lock);
+}
+
+static void vb2_req_release(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   if (vb->state == VB2_BUF_STATE_IN_REQUEST)
+   vb->state = VB2_BUF_STATE_DEQUEUED;
+}
+
+static const struct media_request_object_ops vb2_core_req_ops = {
+   .prepare = vb2_req_prepare,
+   .unprepare = vb2_req_unprepare,
+   .queue = vb2_req_queue,
+   .release = vb2_req_release,
+};
+
 int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 {
struct vb2_buffer *vb;
@@ -1315,7 +1378,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
 
dprintk(2, "prepare of buffer %d succeeded\n", vb->index);
 
-   return ret;
+   return 0;
 }
 EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
@@ -1382,7 +1445,8 @@ static int vb2_start_streaming(struct vb2_queue *q)
return ret;
 }
 
-int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
+ struct media_request *req)
 {
struct vb2_buffer *vb;
int ret;
@@ -1394,8 +1458,39 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int 
index, void *pb)
 
vb = q->bufs[index];
 
+   if (req) {
+   int ret;
+
+   if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+   dprintk(1, "buffer %d not in 

[PATCHv17 05/34] media-request: add media_request_get_by_fd

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Add media_request_get_by_fd() to find a request based on the file
descriptor.

The caller has to call media_request_put() for the returned
request since this function increments the refcount.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
---
 drivers/media/media-request.c | 40 +++
 include/media/media-request.h | 24 +
 2 files changed, 64 insertions(+)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index 253068f51a1f..4b523f3a03a3 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -231,6 +231,46 @@ static const struct file_operations request_fops = {
.release = media_request_close,
 };
 
+struct media_request *
+media_request_get_by_fd(struct media_device *mdev, int request_fd)
+{
+   struct file *filp;
+   struct media_request *req;
+
+   if (!mdev || !mdev->ops ||
+   !mdev->ops->req_validate || !mdev->ops->req_queue)
+   return ERR_PTR(-EPERM);
+
+   filp = fget(request_fd);
+   if (!filp)
+   return ERR_PTR(-ENOENT);
+
+   if (filp->f_op != _fops)
+   goto err_fput;
+   req = filp->private_data;
+   if (req->mdev != mdev)
+   goto err_fput;
+
+   /*
+* Note: as long as someone has an open filehandle of the request,
+* the request can never be released. The fget() above ensures that
+* even if userspace closes the request filehandle, the release()
+* fop won't be called, so the media_request_get() always succeeds
+* and there is no race condition where the request was released
+* before media_request_get() is called.
+*/
+   media_request_get(req);
+   fput(filp);
+
+   return req;
+
+err_fput:
+   fput(filp);
+
+   return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL_GPL(media_request_get_by_fd);
+
 int media_request_alloc(struct media_device *mdev,
struct media_request_alloc *alloc)
 {
diff --git a/include/media/media-request.h b/include/media/media-request.h
index fe5a04fb970c..66ec9d09fcd8 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -143,6 +143,24 @@ static inline void media_request_get(struct media_request 
*req)
  */
 void media_request_put(struct media_request *req);
 
+/**
+ * media_request_get_by_fd - Get a media request by fd
+ *
+ * @mdev: Media device this request belongs to
+ * @request_fd: The file descriptor of the request
+ *
+ * Get the request represented by @request_fd that is owned
+ * by the media device.
+ *
+ * Return a -EPERM error pointer if requests are not supported
+ * by this driver. Return -ENOENT if the request was not found.
+ * Return the pointer to the request if found: the caller will
+ * have to call @media_request_put when it finished using the
+ * request.
+ */
+struct media_request *
+media_request_get_by_fd(struct media_device *mdev, int request_fd);
+
 /**
  * media_request_alloc - Allocate the media request
  *
@@ -164,6 +182,12 @@ static inline void media_request_put(struct media_request 
*req)
 {
 }
 
+static inline struct media_request *
+media_request_get_by_fd(struct media_device *mdev, int request_fd)
+{
+   return ERR_PTR(-EPERM);
+}
+
 #endif
 
 /**
-- 
2.18.0



[PATCHv17 29/34] v4l2-mem2mem: add vb2_m2m_request_queue

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

For mem2mem devices we have to make sure that v4l2_m2m_try_schedule()
is called whenever a request is queued.

We do that by creating a vb2_m2m_request_queue() helper that should
be used instead of the 'normal' vb2_request_queue() helper. The m2m
helper function will call v4l2_m2m_try_schedule() as needed.

In addition we also avoid calling v4l2_m2m_try_schedule() when preparing
or queueing a buffer for a request since that is no longer needed.
Instead this helper function will do that when the request is actually
queued.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-mem2mem.c | 59 ++
 include/media/v4l2-mem2mem.h   |  4 ++
 2 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c 
b/drivers/media/v4l2-core/v4l2-mem2mem.c
index b09494174eb4..56a16cfef6f8 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -369,7 +369,7 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx 
*m2m_ctx)
spin_unlock_irqrestore(_dev->job_spinlock, flags);
if (m2m_dev->m2m_ops->job_abort)
m2m_dev->m2m_ops->job_abort(m2m_ctx->priv);
-   dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx);
+   dprintk("m2m_ctx %p running, will wait to complete\n", m2m_ctx);
wait_event(m2m_ctx->finished,
!(m2m_ctx->job_flags & TRANS_RUNNING));
} else if (m2m_ctx->job_flags & TRANS_QUEUED) {
@@ -460,8 +460,14 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx 
*m2m_ctx,
int ret;
 
vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+   if (!V4L2_TYPE_IS_OUTPUT(vq->type) &&
+   (buf->flags & V4L2_BUF_FLAG_REQUEST_FD)) {
+   dprintk("%s: requests cannot be used with capture buffers\n",
+   __func__);
+   return -EPERM;
+   }
ret = vb2_qbuf(vq, vdev->v4l2_dev->mdev, buf);
-   if (!ret)
+   if (!ret && !(buf->flags & V4L2_BUF_FLAG_IN_REQUEST))
v4l2_m2m_try_schedule(m2m_ctx);
 
return ret;
@@ -483,14 +489,9 @@ int v4l2_m2m_prepare_buf(struct file *file, struct 
v4l2_m2m_ctx *m2m_ctx,
 {
struct video_device *vdev = video_devdata(file);
struct vb2_queue *vq;
-   int ret;
 
vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
-   ret = vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
-   if (!ret)
-   v4l2_m2m_try_schedule(m2m_ctx);
-
-   return ret;
+   return vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
 
@@ -934,6 +935,48 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue);
 
+void vb2_m2m_request_queue(struct media_request *req)
+{
+   struct media_request_object *obj, *obj_safe;
+   struct v4l2_m2m_ctx *m2m_ctx = NULL;
+
+   /* Queue all non-buffer objects */
+   list_for_each_entry_safe(obj, obj_safe, >objects, list)
+   if (obj->ops->queue && !vb2_request_object_is_buffer(obj))
+   obj->ops->queue(obj);
+
+   /* Queue all buffer objects */
+   list_for_each_entry_safe(obj, obj_safe, >objects, list) {
+   struct v4l2_m2m_ctx *m2m_ctx_obj;
+   struct vb2_buffer *vb;
+
+   if (!obj->ops->queue || !vb2_request_object_is_buffer(obj))
+   continue;
+
+   /* Sanity checks */
+   vb = container_of(obj, struct vb2_buffer, req_obj);
+   WARN_ON(!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type));
+   m2m_ctx_obj = container_of(vb->vb2_queue,
+  struct v4l2_m2m_ctx,
+  out_q_ctx.q);
+   WARN_ON(m2m_ctx && m2m_ctx_obj != m2m_ctx);
+   m2m_ctx = m2m_ctx_obj;
+
+   /*
+* The buffer we queue here can in theory be immediately
+* unbound, hence the use of list_for_each_entry_safe()
+* above and why we call the queue op last.
+*/
+   obj->ops->queue(obj);
+   }
+
+   WARN_ON(!m2m_ctx);
+
+   if (m2m_ctx)
+   v4l2_m2m_try_schedule(m2m_ctx);
+}
+EXPORT_SYMBOL_GPL(vb2_m2m_request_queue);
+
 /* Videobuf2 ioctl helpers */
 
 int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
diff --git a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h
index d655720e16a1..58c1ecf3d648 100644
--- a/include/media/v4l2-mem2mem.h
+++ b/include/media/v4l2-mem2mem.h
@@ -622,6 +622,10 @@ v4l2_m2m_dst_buf_remove_by_idx(struct v4l2_m2m_ctx 
*m2m_ctx, unsigned int idx)
return v4l2_m2m_buf_remove_by_idx(_ctx->cap_q_ctx, idx);
 }
 
+/* v4l2 request helper */
+
+void vb2_m2m_request_queue(struct media_request *req);
+
 /* v4l2 ioctl helpers */
 
 int 

[PATCHv17 28/34] videobuf2-v4l2: refuse qbuf if queue uses requests or vv.

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Check if the vb2 queue uses requests, and if so refuse to
add buffers that are not part of a request. Also check for
the reverse: a vb2 queue did not use requests, and an attempt
was made to queue a buffer to a request.

We might relax this in the future, but for now just return
-EPERM in that case.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-v4l2.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 88d8f60c742b..1b2351986230 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -378,8 +378,16 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, 
struct media_device *md
return ret;
}
 
-   if (!(b->flags & V4L2_BUF_FLAG_REQUEST_FD))
+   if (!(b->flags & V4L2_BUF_FLAG_REQUEST_FD)) {
+   if (q->uses_requests) {
+   dprintk(1, "%s: queue uses requests\n", opname);
+   return -EPERM;
+   }
return 0;
+   } else if (q->uses_qbuf) {
+   dprintk(1, "%s: queue does not use requests\n", opname);
+   return -EPERM;
+   }
 
/*
 * For proper locking when queueing a request you need to be able
-- 
2.18.0



[PATCHv17 17/34] vb2: store userspace data in vb2_v4l2_buffer

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

The userspace-provided plane data needs to be stored in
vb2_v4l2_buffer. Currently this information is applied by
__fill_vb2_buffer() which is called by the core prepare_buf
and qbuf functions, but when using requests these functions
aren't called yet since the buffer won't be prepared until
the media request is actually queued.

In the meantime this information has to be stored somewhere
and vb2_v4l2_buffer is a good place for it.

The __fill_vb2_buffer callback now just copies the relevant
information from vb2_v4l2_buffer into the planes array.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-core.c   |  43 +--
 .../media/common/videobuf2/videobuf2-v4l2.c   | 327 ++
 drivers/media/dvb-core/dvb_vb2.c  |   3 +-
 include/media/videobuf2-core.h|   3 +-
 include/media/videobuf2-v4l2.h|   2 +
 5 files changed, 209 insertions(+), 169 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 5653e8eebe2b..7401a17c80ca 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -967,20 +967,19 @@ EXPORT_SYMBOL_GPL(vb2_discard_done);
 /*
  * __prepare_mmap() - prepare an MMAP buffer
  */
-static int __prepare_mmap(struct vb2_buffer *vb, const void *pb)
+static int __prepare_mmap(struct vb2_buffer *vb)
 {
int ret = 0;
 
-   if (pb)
-   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
-vb, pb, vb->planes);
+   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+vb, vb->planes);
return ret ? ret : call_vb_qop(vb, buf_prepare, vb);
 }
 
 /*
  * __prepare_userptr() - prepare a USERPTR buffer
  */
-static int __prepare_userptr(struct vb2_buffer *vb, const void *pb)
+static int __prepare_userptr(struct vb2_buffer *vb)
 {
struct vb2_plane planes[VB2_MAX_PLANES];
struct vb2_queue *q = vb->vb2_queue;
@@ -991,12 +990,10 @@ static int __prepare_userptr(struct vb2_buffer *vb, const 
void *pb)
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
/* Copy relevant information provided by the userspace */
-   if (pb) {
-   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
-vb, pb, planes);
-   if (ret)
-   return ret;
-   }
+   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+vb, planes);
+   if (ret)
+   return ret;
 
for (plane = 0; plane < vb->num_planes; ++plane) {
/* Skip the plane if already verified */
@@ -1096,7 +1093,7 @@ static int __prepare_userptr(struct vb2_buffer *vb, const 
void *pb)
 /*
  * __prepare_dmabuf() - prepare a DMABUF buffer
  */
-static int __prepare_dmabuf(struct vb2_buffer *vb, const void *pb)
+static int __prepare_dmabuf(struct vb2_buffer *vb)
 {
struct vb2_plane planes[VB2_MAX_PLANES];
struct vb2_queue *q = vb->vb2_queue;
@@ -1107,12 +1104,10 @@ static int __prepare_dmabuf(struct vb2_buffer *vb, 
const void *pb)
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
/* Copy relevant information provided by the userspace */
-   if (pb) {
-   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
-vb, pb, planes);
-   if (ret)
-   return ret;
-   }
+   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+vb, planes);
+   if (ret)
+   return ret;
 
for (plane = 0; plane < vb->num_planes; ++plane) {
struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
@@ -1241,7 +1236,7 @@ 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 void *pb)
+static int __buf_prepare(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
unsigned int plane;
@@ -1256,13 +1251,13 @@ static int __buf_prepare(struct vb2_buffer *vb, const 
void *pb)
 
switch (q->memory) {
case VB2_MEMORY_MMAP:
-   ret = __prepare_mmap(vb, pb);
+   ret = __prepare_mmap(vb);
break;
case VB2_MEMORY_USERPTR:
-   ret = __prepare_userptr(vb, pb);
+   ret = __prepare_userptr(vb);
break;
case VB2_MEMORY_DMABUF:
-   ret = __prepare_dmabuf(vb, pb);
+   ret = __prepare_dmabuf(vb);
break;
default:
WARN(1, "Invalid queue type\n");
@@ -1296,7 +1291,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
return -EINVAL;
}
 
-   ret = __buf_prepare(vb, pb);
+   ret = __buf_prepare(vb);
if (ret)
return 

[PATCHv17 14/34] v4l2-ctrls: add core request support

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Integrate the request support. This adds the v4l2_ctrl_request_complete
and v4l2_ctrl_request_setup functions to complete a request and (as a
helper function) to apply a request to the hardware.

It takes care of queuing requests and correctly chaining control values
in the request queue.

Note that when a request is marked completed it will copy control values
to the internal request state. This can be optimized in the future since
this is sub-optimal when dealing with large compound and/or array controls.

For the initial 'stateless codec' use-case the current implementation is
sufficient.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 326 ++-
 include/media/v4l2-ctrls.h   |  51 +
 2 files changed, 371 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index 570b6f8ae46a..b8ff6d6b14cd 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1668,6 +1668,13 @@ static int new_to_user(struct v4l2_ext_control *c,
return ptr_to_user(c, ctrl, ctrl->p_new);
 }
 
+/* Helper function: copy the request value back to the caller */
+static int req_to_user(struct v4l2_ext_control *c,
+  struct v4l2_ctrl_ref *ref)
+{
+   return ptr_to_user(c, ref->ctrl, ref->p_req);
+}
+
 /* Helper function: copy the initial control value back to the caller */
 static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
 {
@@ -1787,6 +1794,26 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
 }
 
+/* Copy the new value to the request value */
+static void new_to_req(struct v4l2_ctrl_ref *ref)
+{
+   if (!ref)
+   return;
+   ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req);
+   ref->req = ref;
+}
+
+/* Copy the request value to the new value */
+static void req_to_new(struct v4l2_ctrl_ref *ref)
+{
+   if (!ref)
+   return;
+   if (ref->req)
+   ptr_to_ptr(ref->ctrl, ref->req->p_req, ref->ctrl->p_new);
+   else
+   ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);
+}
+
 /* Return non-zero if one or more of the controls in the cluster has a new
value that differs from the current value. */
 static int cluster_changed(struct v4l2_ctrl *master)
@@ -1896,6 +1923,9 @@ int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler 
*hdl,
lockdep_set_class_and_name(hdl->lock, key, name);
INIT_LIST_HEAD(>ctrls);
INIT_LIST_HEAD(>ctrl_refs);
+   INIT_LIST_HEAD(>requests);
+   INIT_LIST_HEAD(>requests_queued);
+   hdl->request_is_queued = false;
hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
hdl->buckets = kvmalloc_array(hdl->nr_of_buckets,
  sizeof(hdl->buckets[0]),
@@ -1916,6 +1946,14 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler 
*hdl)
if (hdl == NULL || hdl->buckets == NULL)
return;
 
+   if (!hdl->req_obj.req && !list_empty(>requests)) {
+   struct v4l2_ctrl_handler *req, *next_req;
+
+   list_for_each_entry_safe(req, next_req, >requests, 
requests) {
+   media_request_object_unbind(>req_obj);
+   media_request_object_put(>req_obj);
+   }
+   }
mutex_lock(hdl->lock);
/* Free all nodes */
list_for_each_entry_safe(ref, next_ref, >ctrl_refs, node) {
@@ -2837,6 +2875,123 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, 
struct v4l2_querymenu *qm)
 }
 EXPORT_SYMBOL(v4l2_querymenu);
 
+static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl,
+  const struct v4l2_ctrl_handler *from)
+{
+   struct v4l2_ctrl_ref *ref;
+   int err;
+
+   if (WARN_ON(!hdl || hdl == from))
+   return -EINVAL;
+
+   if (hdl->error)
+   return hdl->error;
+
+   WARN_ON(hdl->lock != >_lock);
+
+   mutex_lock(from->lock);
+   list_for_each_entry(ref, >ctrl_refs, node) {
+   struct v4l2_ctrl *ctrl = ref->ctrl;
+   struct v4l2_ctrl_ref *new_ref;
+
+   /* Skip refs inherited from other devices */
+   if (ref->from_other_dev)
+   continue;
+   /* And buttons */
+   if (ctrl->type == V4L2_CTRL_TYPE_BUTTON)
+   continue;
+   err = handler_new_ref(hdl, ctrl, _ref, false, true);
+   if (err)
+   break;
+   }
+   mutex_unlock(from->lock);
+   return err;
+}
+
+static void v4l2_ctrl_request_queue(struct media_request_object *obj)
+{
+   struct v4l2_ctrl_handler *hdl =
+   container_of(obj, struct v4l2_ctrl_handler, req_obj);
+   struct v4l2_ctrl_handler *main_hdl = obj->priv;
+   struct 

[PATCHv17 25/34] videobuf2-core: add request helper functions

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Add a new helper function to tell if a request object is a buffer.

Add a new helper function that returns true if a media_request
contains at least one buffer.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-core.c   | 24 +++
 include/media/videobuf2-core.h| 15 
 2 files changed, 39 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 3e6db7d30989..f8af7add35ab 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1362,6 +1362,30 @@ static const struct media_request_object_ops 
vb2_core_req_ops = {
.release = vb2_req_release,
 };
 
+bool vb2_request_object_is_buffer(struct media_request_object *obj)
+{
+   return obj->ops == _core_req_ops;
+}
+EXPORT_SYMBOL_GPL(vb2_request_object_is_buffer);
+
+bool vb2_request_has_buffers(struct media_request *req)
+{
+   struct media_request_object *obj;
+   unsigned long flags;
+   bool has_buffers = false;
+
+   spin_lock_irqsave(>lock, flags);
+   list_for_each_entry(obj, >objects, list) {
+   if (vb2_request_object_is_buffer(obj)) {
+   has_buffers = true;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(>lock, flags);
+   return has_buffers;
+}
+EXPORT_SYMBOL_GPL(vb2_request_has_buffers);
+
 int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 {
struct vb2_buffer *vb;
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 8a8d7732d182..cad712403d14 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -1168,4 +1168,19 @@ bool vb2_buffer_in_use(struct vb2_queue *q, struct 
vb2_buffer *vb);
  */
 int vb2_verify_memory_type(struct vb2_queue *q,
enum vb2_memory memory, unsigned int type);
+
+/**
+ * vb2_request_object_is_buffer() - return true if the object is a buffer
+ *
+ * @obj:   the request object.
+ */
+bool vb2_request_object_is_buffer(struct media_request_object *obj);
+
+/**
+ * vb2_request_has_buffers() - return true if the request contains buffers
+ *
+ * @req:   the request.
+ */
+bool vb2_request_has_buffers(struct media_request *req);
+
 #endif /* _MEDIA_VIDEOBUF2_CORE_H */
-- 
2.18.0



[PATCHv17 26/34] videobuf2-v4l2: add vb2_request_queue/validate helpers

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

The generic vb2_request_validate helper function checks if
there are buffers in the request and if so, prepares (validates)
all objects in the request.

The generic vb2_request_queue helper function queues all buffer
objects in the validated request.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-v4l2.c   | 44 +++
 include/media/videobuf2-v4l2.h|  4 ++
 2 files changed, 48 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 9c652afa62ab..88d8f60c742b 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -1100,6 +1100,50 @@ void vb2_ops_wait_finish(struct vb2_queue *vq)
 }
 EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
 
+int vb2_request_validate(struct media_request *req)
+{
+   struct media_request_object *obj;
+   int ret = 0;
+
+   if (!vb2_request_has_buffers(req))
+   return -ENOENT;
+
+   list_for_each_entry(obj, >objects, list) {
+   if (!obj->ops->prepare)
+   continue;
+
+   ret = obj->ops->prepare(obj);
+   if (ret)
+   break;
+   }
+
+   if (ret) {
+   list_for_each_entry_continue_reverse(obj, >objects, list)
+   if (obj->ops->unprepare)
+   obj->ops->unprepare(obj);
+   return ret;
+   }
+   return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_request_validate);
+
+void vb2_request_queue(struct media_request *req)
+{
+   struct media_request_object *obj, *obj_safe;
+
+   /* Queue all non-buffer objects */
+   list_for_each_entry_safe(obj, obj_safe, >objects, list)
+   if (obj->ops->queue && !vb2_request_object_is_buffer(obj))
+   obj->ops->queue(obj);
+
+   /* Queue all buffer objects */
+   list_for_each_entry_safe(obj, obj_safe, >objects, list) {
+   if (obj->ops->queue && vb2_request_object_is_buffer(obj))
+   obj->ops->queue(obj);
+   }
+}
+EXPORT_SYMBOL_GPL(vb2_request_queue);
+
 MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
 MODULE_AUTHOR("Pawel Osciak , Marek Szyprowski");
 MODULE_LICENSE("GPL");
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 91a2b3e1a642..727855463838 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -303,4 +303,8 @@ void vb2_ops_wait_prepare(struct vb2_queue *vq);
  */
 void vb2_ops_wait_finish(struct vb2_queue *vq);
 
+struct media_request;
+int vb2_request_validate(struct media_request *req);
+void vb2_request_queue(struct media_request *req);
+
 #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
-- 
2.18.0



[PATCHv17 24/34] videobuf2-v4l2: integrate with media requests

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

This implements the V4L2 part of the request support. The main
change is that vb2_qbuf and vb2_prepare_buf now have a new
media_device pointer. This required changes to several drivers
that did not use the vb2_ioctl_qbuf/prepare_buf helper functions.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-core.c   |  13 +-
 .../media/common/videobuf2/videobuf2-v4l2.c   | 112 --
 drivers/media/platform/omap3isp/ispvideo.c|   2 +-
 .../media/platform/s3c-camif/camif-capture.c  |   4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c  |   4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c  |   4 +-
 .../media/platform/soc_camera/soc_camera.c|   4 +-
 drivers/media/usb/uvc/uvc_queue.c |   5 +-
 drivers/media/usb/uvc/uvc_v4l2.c  |   3 +-
 drivers/media/usb/uvc/uvcvideo.h  |   1 +
 drivers/media/v4l2-core/v4l2-mem2mem.c|   6 +-
 .../staging/media/davinci_vpfe/vpfe_video.c   |   3 +-
 drivers/staging/media/omap4iss/iss_video.c|   3 +-
 drivers/usb/gadget/function/uvc_queue.c   |   2 +-
 include/media/videobuf2-v4l2.h|  14 ++-
 15 files changed, 148 insertions(+), 32 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 1efb9c8b359d..3e6db7d30989 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1338,6 +1338,14 @@ static void vb2_req_queue(struct media_request_object 
*obj)
mutex_unlock(vb->vb2_queue->lock);
 }
 
+static void vb2_req_unbind(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   if (vb->state == VB2_BUF_STATE_IN_REQUEST)
+   call_void_bufop(vb->vb2_queue, init_buffer, vb);
+}
+
 static void vb2_req_release(struct media_request_object *obj)
 {
struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
@@ -1350,6 +1358,7 @@ static const struct media_request_object_ops 
vb2_core_req_ops = {
.prepare = vb2_req_prepare,
.unprepare = vb2_req_unprepare,
.queue = vb2_req_queue,
+   .unbind = vb2_req_unbind,
.release = vb2_req_release,
 };
 
@@ -1481,8 +1490,10 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int 
index, void *pb,
 
vb->state = VB2_BUF_STATE_IN_REQUEST;
/* Fill buffer information for the userspace */
-   if (pb)
+   if (pb) {
+   call_void_bufop(q, copy_timestamp, vb, pb);
call_void_bufop(q, fill_user_buffer, vb, pb);
+   }
 
dprintk(2, "qbuf of buffer %d succeeded\n", vb->index);
return 0;
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index ea9db4b3f59a..9c652afa62ab 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -25,6 +25,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -40,10 +41,12 @@ module_param(debug, int, 0644);
pr_info("vb2-v4l2: %s: " fmt, __func__, ## arg); \
} while (0)
 
-/* Flags that are set by the vb2 core */
+/* Flags that are set by us */
 #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_IN_REQUEST | \
+V4L2_BUF_FLAG_REQUEST_FD | \
 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 | \
@@ -118,6 +121,16 @@ static int __verify_length(struct vb2_buffer *vb, const 
struct v4l2_buffer *b)
return 0;
 }
 
+/*
+ * __init_v4l2_vb2_buffer() - initialize the v4l2_vb2_buffer struct
+ */
+static void __init_v4l2_vb2_buffer(struct vb2_buffer *vb)
+{
+   struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+   vbuf->request_fd = -1;
+}
+
 static void __copy_timestamp(struct vb2_buffer *vb, const void *pb)
 {
const struct v4l2_buffer *b = pb;
@@ -181,6 +194,7 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, 
struct v4l2_buffer *b
return -EINVAL;
}
vbuf->sequence = 0;
+   vbuf->request_fd = -1;
 
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
switch (b->memory) {
@@ -318,9 +332,12 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, 
struct v4l2_buffer *b
return 0;
 }
 
-static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
-   const char *opname)
+static int 

[PATCHv17 20/34] videodev2.h: Add request_fd field to v4l2_buffer

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

When queuing buffers allow for passing the request that should
be associated with this buffer.

If V4L2_BUF_FLAG_REQUEST_FD is set, then request_fd is used as
the file descriptor.

If a buffer is stored in a request, but not yet queued to the
driver, then V4L2_BUF_FLAG_IN_REQUEST is set.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-v4l2.c |  2 +-
 drivers/media/usb/cpia2/cpia2_v4l.c |  2 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c   |  9 ++---
 drivers/media/v4l2-core/v4l2-ioctl.c|  4 ++--
 include/uapi/linux/videodev2.h  | 10 +-
 5 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index a677e2c26247..64905d87465c 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -384,7 +384,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void 
*pb)
b->timecode = vbuf->timecode;
b->sequence = vbuf->sequence;
b->reserved2 = 0;
-   b->reserved = 0;
+   b->request_fd = 0;
 
if (q->is_multiplanar) {
/*
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c 
b/drivers/media/usb/cpia2/cpia2_v4l.c
index 99f106b13280..13aee9f67d05 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -949,7 +949,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct 
v4l2_buffer *buf)
buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
buf->length = cam->frame_size;
buf->reserved2 = 0;
-   buf->reserved = 0;
+   buf->request_fd = 0;
memset(>timecode, 0, sizeof(buf->timecode));
 
DBG("DQBUF #%d status:%d seq:%d length:%d\n", buf->index,
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index dcce86c1fe40..633465d21d04 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -482,7 +482,7 @@ struct v4l2_buffer32 {
} m;
__u32   length;
__u32   reserved2;
-   __u32   reserved;
+   __s32   request_fd;
 };
 
 static int get_v4l2_plane32(struct v4l2_plane __user *p64,
@@ -581,6 +581,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer __user *p64,
 {
u32 type;
u32 length;
+   s32 request_fd;
enum v4l2_memory memory;
struct v4l2_plane32 __user *uplane32;
struct v4l2_plane __user *uplane;
@@ -595,7 +596,9 @@ static int get_v4l2_buffer32(struct v4l2_buffer __user *p64,
get_user(memory, >memory) ||
put_user(memory, >memory) ||
get_user(length, >length) ||
-   put_user(length, >length))
+   put_user(length, >length) ||
+   get_user(request_fd, >request_fd) ||
+   put_user(request_fd, >request_fd))
return -EFAULT;
 
if (V4L2_TYPE_IS_OUTPUT(type))
@@ -699,7 +702,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer __user *p64,
copy_in_user(>timecode, >timecode, sizeof(p64->timecode)) 
||
assign_in_user(>sequence, >sequence) ||
assign_in_user(>reserved2, >reserved2) ||
-   assign_in_user(>reserved, >reserved) ||
+   assign_in_user(>request_fd, >request_fd) ||
get_user(length, >length) ||
put_user(length, >length))
return -EFAULT;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 20b5145a5254..2a84ca9e328a 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -474,13 +474,13 @@ static void v4l_print_buffer(const void *arg, bool 
write_only)
const struct v4l2_plane *plane;
int i;
 
-   pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, flags=0x%08x, 
field=%s, sequence=%d, memory=%s",
+   pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, request_fd=%d, 
flags=0x%08x, field=%s, sequence=%d, memory=%s",
p->timestamp.tv_sec / 3600,
(int)(p->timestamp.tv_sec / 60) % 60,
(int)(p->timestamp.tv_sec % 60),
(long)p->timestamp.tv_usec,
p->index,
-   prt_names(p->type, v4l2_type_names),
+   prt_names(p->type, v4l2_type_names), p->request_fd,
p->flags, prt_names(p->field, v4l2_field_names),
p->sequence, prt_names(p->memory, v4l2_memory_names));
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 1df0fa983db6..91126b7312f8 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -917,6 +917,7 @@ struct v4l2_plane {
  * 

[PATCHv17 19/34] vb2: drop VB2_BUF_STATE_PREPARED, use bool prepared/synced instead

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

The PREPARED state becomes a problem with the request API: a buffer
could be PREPARED but dequeued, or PREPARED and in state IN_REQUEST.

PREPARED is really not a state as such, but more a property of the
buffer. So make new 'prepared' and 'synced' bools instead to remember
whether the buffer is prepared and/or synced or not.

V4L2_BUF_FLAG_PREPARED is only set if the buffer is both synced and
prepared and in the DEQUEUED state.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-core.c   | 38 +--
 .../media/common/videobuf2/videobuf2-v4l2.c   | 16 +---
 include/media/videobuf2-core.h|  6 ++-
 3 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 7401a17c80ca..eead693ba619 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -682,7 +682,7 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory 
memory,
}
 
/*
-* Call queue_cancel to clean up any buffers in the PREPARED or
+* Call queue_cancel to clean up any buffers in the
 * QUEUED state which is possible if buffers were prepared or
 * queued without ever calling STREAMON.
 */
@@ -921,6 +921,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum 
vb2_buffer_state state)
/* sync buffers */
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish, vb->planes[plane].mem_priv);
+   vb->synced = false;
}
 
spin_lock_irqsave(>done_lock, flags);
@@ -1239,6 +1240,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
 static int __buf_prepare(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
+   enum vb2_buffer_state orig_state = vb->state;
unsigned int plane;
int ret;
 
@@ -1247,6 +1249,10 @@ static int __buf_prepare(struct vb2_buffer *vb)
return -EIO;
}
 
+   if (vb->prepared)
+   return 0;
+   WARN_ON(vb->synced);
+
vb->state = VB2_BUF_STATE_PREPARING;
 
switch (q->memory) {
@@ -1262,11 +1268,12 @@ static int __buf_prepare(struct vb2_buffer *vb)
default:
WARN(1, "Invalid queue type\n");
ret = -EINVAL;
+   break;
}
 
if (ret) {
dprintk(1, "buffer preparation failed: %d\n", ret);
-   vb->state = VB2_BUF_STATE_DEQUEUED;
+   vb->state = orig_state;
return ret;
}
 
@@ -1274,7 +1281,9 @@ static int __buf_prepare(struct vb2_buffer *vb)
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, prepare, vb->planes[plane].mem_priv);
 
-   vb->state = VB2_BUF_STATE_PREPARED;
+   vb->synced = true;
+   vb->prepared = true;
+   vb->state = orig_state;
 
return 0;
 }
@@ -1290,6 +1299,10 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
vb->state);
return -EINVAL;
}
+   if (vb->prepared) {
+   dprintk(1, "buffer already prepared\n");
+   return -EINVAL;
+   }
 
ret = __buf_prepare(vb);
if (ret)
@@ -1381,11 +1394,11 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int 
index, void *pb)
 
switch (vb->state) {
case VB2_BUF_STATE_DEQUEUED:
-   ret = __buf_prepare(vb);
-   if (ret)
-   return ret;
-   break;
-   case VB2_BUF_STATE_PREPARED:
+   if (!vb->prepared) {
+   ret = __buf_prepare(vb);
+   if (ret)
+   return ret;
+   }
break;
case VB2_BUF_STATE_PREPARING:
dprintk(1, "buffer still being prepared\n");
@@ -1611,6 +1624,7 @@ int vb2_core_dqbuf(struct vb2_queue *q, unsigned int 
*pindex, void *pb,
}
 
call_void_vb_qop(vb, buf_finish, vb);
+   vb->prepared = false;
 
if (pindex)
*pindex = vb->index;
@@ -1699,18 +1713,18 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
for (i = 0; i < q->num_buffers; ++i) {
struct vb2_buffer *vb = q->bufs[i];
 
-   if (vb->state == VB2_BUF_STATE_PREPARED ||
-   vb->state == VB2_BUF_STATE_QUEUED) {
+   if (vb->synced) {
unsigned int plane;
 
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish,
vb->planes[plane].mem_priv);
+   vb->synced = false;
}
 
-  

[PATCHv17 21/34] vb2: add init_buffer buffer op

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

We need to initialize the request_fd field in struct vb2_v4l2_buffer
to -1 instead of the default of 0. So we need to add a new op that
is called when struct vb2_v4l2_buffer is allocated.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 2 ++
 include/media/videobuf2-core.h  | 4 
 2 files changed, 6 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index eead693ba619..230f83d6d094 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -356,6 +356,8 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
vb->planes[plane].length = plane_sizes[plane];
vb->planes[plane].min_length = plane_sizes[plane];
}
+   call_void_bufop(q, init_buffer, vb);
+
q->bufs[vb->index] = vb;
 
/* Allocate video buffer memory for the MMAP type */
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 5e760d5f280a..cbda3968d018 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -408,6 +408,9 @@ struct vb2_ops {
  * @verify_planes_array: Verify that a given user space structure contains
  * enough planes for the buffer. This is called
  * for each dequeued buffer.
+ * @init_buffer:   given a _buffer initialize the extra data after
+ * struct vb2_buffer.
+ * For V4L2 this is a  vb2_v4l2_buffer.
  * @fill_user_buffer:  given a _buffer fill in the userspace structure.
  * For V4L2 this is a  v4l2_buffer.
  * @fill_vb2_buffer:   given a userspace structure, fill in the _buffer.
@@ -418,6 +421,7 @@ struct vb2_ops {
  */
 struct vb2_buf_ops {
int (*verify_planes_array)(struct vb2_buffer *vb, const void *pb);
+   void (*init_buffer)(struct vb2_buffer *vb);
void (*fill_user_buffer)(struct vb2_buffer *vb, void *pb);
int (*fill_vb2_buffer)(struct vb2_buffer *vb, struct vb2_plane *planes);
void (*copy_timestamp)(struct vb2_buffer *vb, const void *pb);
-- 
2.18.0



[PATCHv17 01/34] Documentation: v4l: document request API

2018-08-04 Thread Hans Verkuil
From: Alexandre Courbot 

Document the request API for V4L2 devices, and amend the documentation
of system calls influenced by it.

Signed-off-by: Alexandre Courbot 
Signed-off-by: Hans Verkuil 
---
 .../media/uapi/mediactl/media-controller.rst  |   1 +
 .../media/uapi/mediactl/media-funcs.rst   |   6 +
 .../uapi/mediactl/media-ioc-request-alloc.rst |  78 ++
 .../uapi/mediactl/media-request-ioc-queue.rst |  82 ++
 .../mediactl/media-request-ioc-reinit.rst |  51 
 .../media/uapi/mediactl/request-api.rst   | 247 ++
 .../uapi/mediactl/request-func-close.rst  |  49 
 .../uapi/mediactl/request-func-ioctl.rst  |  68 +
 .../media/uapi/mediactl/request-func-poll.rst |  77 ++
 Documentation/media/uapi/v4l/buffer.rst   |  21 +-
 .../media/uapi/v4l/vidioc-g-ext-ctrls.rst |  94 ---
 Documentation/media/uapi/v4l/vidioc-qbuf.rst  |  32 ++-
 .../media/videodev2.h.rst.exceptions  |   1 +
 13 files changed, 771 insertions(+), 36 deletions(-)
 create mode 100644 
Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
 create mode 100644 
Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
 create mode 100644 
Documentation/media/uapi/mediactl/media-request-ioc-reinit.rst
 create mode 100644 Documentation/media/uapi/mediactl/request-api.rst
 create mode 100644 Documentation/media/uapi/mediactl/request-func-close.rst
 create mode 100644 Documentation/media/uapi/mediactl/request-func-ioctl.rst
 create mode 100644 Documentation/media/uapi/mediactl/request-func-poll.rst

diff --git a/Documentation/media/uapi/mediactl/media-controller.rst 
b/Documentation/media/uapi/mediactl/media-controller.rst
index 0eea4f9a07d5..66aff38cd499 100644
--- a/Documentation/media/uapi/mediactl/media-controller.rst
+++ b/Documentation/media/uapi/mediactl/media-controller.rst
@@ -21,6 +21,7 @@ Part IV - Media Controller API
 media-controller-intro
 media-controller-model
 media-types
+request-api
 media-funcs
 media-header
 
diff --git a/Documentation/media/uapi/mediactl/media-funcs.rst 
b/Documentation/media/uapi/mediactl/media-funcs.rst
index 076856501cdb..260f9dcadcde 100644
--- a/Documentation/media/uapi/mediactl/media-funcs.rst
+++ b/Documentation/media/uapi/mediactl/media-funcs.rst
@@ -16,3 +16,9 @@ Function Reference
 media-ioc-enum-entities
 media-ioc-enum-links
 media-ioc-setup-link
+media-ioc-request-alloc
+request-func-close
+request-func-ioctl
+request-func-poll
+media-request-ioc-queue
+media-request-ioc-reinit
diff --git a/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst 
b/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
new file mode 100644
index ..11dcc14ca0bd
--- /dev/null
+++ b/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
@@ -0,0 +1,78 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. _media_ioc_request_alloc:
+
+*
+ioctl MEDIA_IOC_REQUEST_ALLOC
+*
+
+Name
+
+
+MEDIA_IOC_REQUEST_ALLOC - Allocate a request
+
+
+Synopsis
+
+
+.. c:function:: int ioctl( int fd, MEDIA_IOC_REQUEST_ALLOC, struct 
media_request_alloc *argp )
+:name: MEDIA_IOC_REQUEST_ALLOC
+
+
+Arguments
+=
+
+``fd``
+File descriptor returned by :ref:`open() `.
+
+``argp``
+Pointer to struct :c:type:`media_request_alloc`.
+
+
+Description
+===
+
+If the media device supports :ref:`requests `, then
+this ioctl can be used to allocate a request. If it is not supported, then
+``errno`` is set to ``ENOTTY``. A request is accessed through a file descriptor
+that is returned in struct :c:type:`media_request_alloc`.
+
+If the request was successfully allocated, then the request file descriptor
+can be passed to the :ref:`VIDIOC_QBUF `,
+:ref:`VIDIOC_G_EXT_CTRLS `,
+:ref:`VIDIOC_S_EXT_CTRLS ` and
+:ref:`VIDIOC_TRY_EXT_CTRLS ` ioctls.
+
+In addition, the request can be queued by calling
+:ref:`MEDIA_REQUEST_IOC_QUEUE` and re-initialized by calling
+:ref:`MEDIA_REQUEST_IOC_REINIT`.
+
+Finally, the file descriptor can be :ref:`polled ` to wait
+for the request to complete.
+
+The request will remain allocated until all the file descriptors associated
+with it are closed by :ref:`close() ` and the driver no
+longer uses the request internally.
+
+.. c:type:: media_request_alloc
+
+.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
+
+.. flat-table:: struct media_request_alloc
+:header-rows:  0
+:stub-columns: 0
+:widths:   1 1 2
+
+*  -  __s32
+   -  ``fd``
+   -  The file descriptor of the request.
+
+Return Value
+
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes ` chapter.
+
+ENOTTY
+The driver has no support for requests.
diff --git a/Documentation/media/uapi/mediactl/media-request-ioc-queue.rst 

[PATCHv17 08/34] v4l2-dev: lock req_queue_mutex

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

We need to serialize streamon/off with queueing new requests.
These ioctls may trigger the cancellation of a streaming
operation, and that should not be mixed with queuing a new
request at the same time.

Finally close() needs this lock since that too can trigger the
cancellation of a streaming operation.

We take the req_queue_mutex here before any other locks since
it is a very high-level lock.

Signed-off-by: Hans Verkuil 
Signed-off-by: Sakari Ailus 
---
 drivers/media/v4l2-core/v4l2-dev.c   | 13 +
 drivers/media/v4l2-core/v4l2-ioctl.c | 22 +-
 2 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-dev.c 
b/drivers/media/v4l2-core/v4l2-dev.c
index 69e775930fc4..53018e4a4c78 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -444,8 +444,21 @@ static int v4l2_release(struct inode *inode, struct file 
*filp)
struct video_device *vdev = video_devdata(filp);
int ret = 0;
 
+   /*
+* We need to serialize the release() with queueing new requests.
+* The release() may trigger the cancellation of a streaming
+* operation, and that should not be mixed with queueing a new
+* request at the same time.
+*/
+   if (v4l2_device_supports_requests(vdev->v4l2_dev))
+   mutex_lock(>v4l2_dev->mdev->req_queue_mutex);
+
if (vdev->fops->release)
ret = vdev->fops->release(filp);
+
+   if (v4l2_device_supports_requests(vdev->v4l2_dev))
+   mutex_unlock(>v4l2_dev->mdev->req_queue_mutex);
+
if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
dprintk("%s: release\n",
video_device_node_name(vdev));
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 54afc9c7ee6e..ea475d833dd6 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2780,6 +2780,7 @@ static long __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
 {
struct video_device *vfd = video_devdata(file);
+   struct mutex *req_queue_lock = NULL;
struct mutex *lock; /* ioctl serialization mutex */
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
bool write_only = false;
@@ -2799,10 +2800,27 @@ static long __video_do_ioctl(struct file *file,
if (test_bit(V4L2_FL_USES_V4L2_FH, >flags))
vfh = file->private_data;
 
+   /*
+* We need to serialize streamon/off with queueing new requests.
+* These ioctls may trigger the cancellation of a streaming
+* operation, and that should not be mixed with queueing a new
+* request at the same time.
+*/
+   if (v4l2_device_supports_requests(vfd->v4l2_dev) &&
+   (cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF)) {
+   req_queue_lock = >v4l2_dev->mdev->req_queue_mutex;
+
+   if (mutex_lock_interruptible(req_queue_lock))
+   return -ERESTARTSYS;
+   }
+
lock = v4l2_ioctl_get_lock(vfd, vfh, cmd, arg);
 
-   if (lock && mutex_lock_interruptible(lock))
+   if (lock && mutex_lock_interruptible(lock)) {
+   if (req_queue_lock)
+   mutex_unlock(req_queue_lock);
return -ERESTARTSYS;
+   }
 
if (!video_is_registered(vfd)) {
ret = -ENODEV;
@@ -2861,6 +2879,8 @@ static long __video_do_ioctl(struct file *file,
 unlock:
if (lock)
mutex_unlock(lock);
+   if (req_queue_lock)
+   mutex_unlock(req_queue_lock);
return ret;
 }
 
-- 
2.18.0



[PATCHv17 02/34] uapi/linux/media.h: add request API

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Define the public request API.

This adds the new MEDIA_IOC_REQUEST_ALLOC ioctl to allocate a request
and two ioctls that operate on a request in order to queue the
contents of the request to the driver and to re-initialize the
request.

Signed-off-by: Hans Verkuil 
Acked-by: Sakari Ailus 
Reviewed-by: Laurent Pinchart 
---
 include/uapi/linux/media.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index 36f76e777ef9..cf77f00a0f2d 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -364,11 +364,23 @@ struct media_v2_topology {
 
 /* ioctls */
 
+struct __attribute__ ((packed)) media_request_alloc {
+   __s32 fd;
+};
+
 #define MEDIA_IOC_DEVICE_INFO  _IOWR('|', 0x00, struct media_device_info)
 #define MEDIA_IOC_ENUM_ENTITIES_IOWR('|', 0x01, struct 
media_entity_desc)
 #define MEDIA_IOC_ENUM_LINKS   _IOWR('|', 0x02, struct media_links_enum)
 #define MEDIA_IOC_SETUP_LINK   _IOWR('|', 0x03, struct media_link_desc)
 #define MEDIA_IOC_G_TOPOLOGY   _IOWR('|', 0x04, struct media_v2_topology)
+#define MEDIA_IOC_REQUEST_ALLOC_IOWR('|', 0x05, struct 
media_request_alloc)
+
+/*
+ * These ioctls are called on the request file descriptor as returned
+ * by MEDIA_IOC_REQUEST_ALLOC.
+ */
+#define MEDIA_REQUEST_IOC_QUEUE_IO('|',  0x80)
+#define MEDIA_REQUEST_IOC_REINIT   _IO('|',  0x81)
 
 #ifndef __KERNEL__
 
-- 
2.18.0



[PATCHv17 09/34] videodev2.h: add request_fd field to v4l2_ext_controls

2018-08-04 Thread Hans Verkuil
From: Alexandre Courbot 

If 'which' is V4L2_CTRL_WHICH_REQUEST_VAL, then the 'request_fd' field
can be used to specify a request for the G/S/TRY_EXT_CTRLS ioctls.

Signed-off-by: Alexandre Courbot 
Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 5 -
 drivers/media/v4l2-core/v4l2-ioctl.c  | 6 +++---
 include/uapi/linux/videodev2.h| 4 +++-
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 6481212fda77..dcce86c1fe40 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -834,7 +834,8 @@ struct v4l2_ext_controls32 {
__u32 which;
__u32 count;
__u32 error_idx;
-   __u32 reserved[2];
+   __s32 request_fd;
+   __u32 reserved[1];
compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
 };
 
@@ -909,6 +910,7 @@ static int get_v4l2_ext_controls32(struct file *file,
get_user(count, >count) ||
put_user(count, >count) ||
assign_in_user(>error_idx, >error_idx) ||
+   assign_in_user(>request_fd, >request_fd) ||
copy_in_user(p64->reserved, p32->reserved, sizeof(p64->reserved)))
return -EFAULT;
 
@@ -974,6 +976,7 @@ static int put_v4l2_ext_controls32(struct file *file,
get_user(count, >count) ||
put_user(count, >count) ||
assign_in_user(>error_idx, >error_idx) ||
+   assign_in_user(>request_fd, >request_fd) ||
copy_in_user(p32->reserved, p64->reserved, sizeof(p32->reserved)) ||
get_user(kcontrols, >controls))
return -EFAULT;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index ea475d833dd6..03241d6b7ef8 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -590,8 +590,8 @@ static void v4l_print_ext_controls(const void *arg, bool 
write_only)
const struct v4l2_ext_controls *p = arg;
int i;
 
-   pr_cont("which=0x%x, count=%d, error_idx=%d",
-   p->which, p->count, p->error_idx);
+   pr_cont("which=0x%x, count=%d, error_idx=%d, request_fd=%d",
+   p->which, p->count, p->error_idx, p->request_fd);
for (i = 0; i < p->count; i++) {
if (!p->controls[i].size)
pr_cont(", id/val=0x%x/0x%x",
@@ -907,7 +907,7 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int 
allow_priv)
__u32 i;
 
/* zero the reserved fields */
-   c->reserved[0] = c->reserved[1] = 0;
+   c->reserved[0] = 0;
for (i = 0; i < c->count; i++)
c->controls[i].reserved2[0] = 0;
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 5d1a3685bea9..1df0fa983db6 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1599,7 +1599,8 @@ struct v4l2_ext_controls {
};
__u32 count;
__u32 error_idx;
-   __u32 reserved[2];
+   __s32 request_fd;
+   __u32 reserved[1];
struct v4l2_ext_control *controls;
 };
 
@@ -1612,6 +1613,7 @@ struct v4l2_ext_controls {
 #define V4L2_CTRL_MAX_DIMS   (4)
 #define V4L2_CTRL_WHICH_CUR_VAL   0
 #define V4L2_CTRL_WHICH_DEF_VAL   0x0f00
+#define V4L2_CTRL_WHICH_REQUEST_VAL 0x0f01
 
 enum v4l2_ctrl_type {
V4L2_CTRL_TYPE_INTEGER   = 1,
-- 
2.18.0



[PATCHv17 31/34] vim2m: support requests

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Add support for requests to vim2m.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vim2m.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 6f87ef025ff1..3b8df2c9d24a 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -379,8 +379,18 @@ static void device_run(void *priv)
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
 
+   /* Apply request controls if needed */
+   if (src_buf->vb2_buf.req_obj.req)
+   v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req,
+   >hdl);
+
device_process(ctx, src_buf, dst_buf);
 
+   /* Complete request controls if needed */
+   if (src_buf->vb2_buf.req_obj.req)
+   v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req,
+   >hdl);
+
/* Run delayed work, which simulates a hardware irq  */
schedule_delayed_work(>work_run, msecs_to_jiffies(ctx->transtime));
 }
@@ -808,12 +818,21 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
if (vbuf == NULL)
return;
+   v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
+  >hdl);
spin_lock_irqsave(>dev->irqlock, flags);
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
spin_unlock_irqrestore(>dev->irqlock, flags);
}
 }
 
+static void vim2m_buf_request_complete(struct vb2_buffer *vb)
+{
+   struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+   v4l2_ctrl_request_complete(vb->req_obj.req, >hdl);
+}
+
 static const struct vb2_ops vim2m_qops = {
.queue_setup = vim2m_queue_setup,
.buf_prepare = vim2m_buf_prepare,
@@ -822,6 +841,7 @@ static const struct vb2_ops vim2m_qops = {
.stop_streaming  = vim2m_stop_streaming,
.wait_prepare= vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
+   .buf_request_complete = vim2m_buf_request_complete,
 };
 
 static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue 
*dst_vq)
@@ -988,6 +1008,11 @@ static const struct v4l2_m2m_ops m2m_ops = {
.job_abort  = job_abort,
 };
 
+static const struct media_device_ops m2m_media_ops = {
+   .req_validate = vb2_request_validate,
+   .req_queue = vb2_m2m_request_queue,
+};
+
 static int vim2m_probe(struct platform_device *pdev)
 {
struct vim2m_dev *dev;
@@ -1036,6 +1061,7 @@ static int vim2m_probe(struct platform_device *pdev)
dev->mdev.dev = >dev;
strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
media_device_init(>mdev);
+   dev->mdev.ops = _media_ops;
dev->v4l2_dev.mdev = >mdev;
 
ret = v4l2_m2m_register_media_controller(dev->m2m_dev,
-- 
2.18.0



[PATCHv17 04/34] media: doc: Add media-request.h header to documentation build

2018-08-04 Thread Hans Verkuil
From: Sakari Ailus 

media-request.h has been recently added; add it to the documentation build
as well.

Signed-off-by: Sakari Ailus 
Signed-off-by: Hans Verkuil 
---
 Documentation/media/kapi/mc-core.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/media/kapi/mc-core.rst 
b/Documentation/media/kapi/mc-core.rst
index 0c05503eaf1f..69362b3135c2 100644
--- a/Documentation/media/kapi/mc-core.rst
+++ b/Documentation/media/kapi/mc-core.rst
@@ -262,3 +262,5 @@ in the end provide a way to use driver-specific callbacks.
 .. kernel-doc:: include/media/media-devnode.h
 
 .. kernel-doc:: include/media/media-entity.h
+
+.. kernel-doc:: include/media/media-request.h
-- 
2.18.0



[PATCHv17 27/34] videobuf2-core: add uses_requests/qbuf flags

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Set the first time a buffer from a request is queued to vb2
(uses_requests) or directly queued (uses_qbuf).
Cleared when the queue is canceled.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 13 +
 include/media/videobuf2-core.h  |  8 
 2 files changed, 21 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index f8af7add35ab..5d7946ec80d8 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1491,9 +1491,17 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int 
index, void *pb,
 
vb = q->bufs[index];
 
+   if ((req && q->uses_qbuf) ||
+   (!req && vb->state != VB2_BUF_STATE_IN_REQUEST &&
+q->uses_requests)) {
+   dprintk(1, "queue in wrong mode (qbuf vs requests)\n");
+   return -EPERM;
+   }
+
if (req) {
int ret;
 
+   q->uses_requests = 1;
if (vb->state != VB2_BUF_STATE_DEQUEUED) {
dprintk(1, "buffer %d not in dequeued state\n",
vb->index);
@@ -1523,6 +1531,9 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int 
index, void *pb,
return 0;
}
 
+   if (vb->state != VB2_BUF_STATE_IN_REQUEST)
+   q->uses_qbuf = 1;
+
switch (vb->state) {
case VB2_BUF_STATE_DEQUEUED:
case VB2_BUF_STATE_IN_REQUEST:
@@ -1825,6 +1836,8 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
q->start_streaming_called = 0;
q->queued_count = 0;
q->error = 0;
+   q->uses_requests = 0;
+   q->uses_qbuf = 0;
 
/*
 * Remove all buffers from videobuf's list...
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index cad712403d14..daffdf259fce 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -468,6 +468,12 @@ struct vb2_buf_ops {
  * @quirk_poll_must_check_waiting_for_buffers: Return %EPOLLERR at poll when 
QBUF
  *  has not been called. This is a vb1 idiom that has been adopted
  *  also by vb2.
+ * @uses_qbuf: qbuf was used directly for this queue. Set to 1 the first
+ * time this is called. Set to 0 when the queue is canceled.
+ * If this is 1, then you cannot queue buffers from a request.
+ * @uses_requests: requests are used for this queue. Set to 1 the first time
+ * a request is queued. Set to 0 when the queue is canceled.
+ * If this is 1, then you cannot queue buffers directly.
  * @lock:  pointer to a mutex that protects the  vb2_queue. The
  * driver can set this to a mutex to let the v4l2 core serialize
  * the queuing ioctls. If the driver wants to handle locking
@@ -535,6 +541,8 @@ struct vb2_queue {
unsignedfileio_write_immediately:1;
unsignedallow_zero_bytesused:1;
unsigned   quirk_poll_must_check_waiting_for_buffers:1;
+   unsigneduses_qbuf:1;
+   unsigneduses_requests:1;
 
struct mutex*lock;
void*owner;
-- 
2.18.0



[PATCHv17 16/34] v4l2-ctrls: add v4l2_ctrl_request_hdl_find/put/ctrl_find functions

2018-08-04 Thread Hans Verkuil
If a driver needs to find/inspect the controls set in a request then
it can use these functions.

E.g. to check if a required control is set in a request use this in the
req_validate() implementation:

int res = -EINVAL;

hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
if (hdl) {
if (v4l2_ctrl_request_hdl_ctrl_find(hdl, ctrl_id))
res = 0;
v4l2_ctrl_request_hdl_put(hdl);
}
return res;

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 25 
 include/media/v4l2-ctrls.h   | 44 +++-
 2 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index 86a6ae54ccaa..2a30be824491 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -2976,6 +2976,31 @@ static const struct media_request_object_ops req_ops = {
.release = v4l2_ctrl_request_release,
 };
 
+struct v4l2_ctrl_handler *v4l2_ctrl_request_hdl_find(struct media_request *req,
+   struct v4l2_ctrl_handler *parent)
+{
+   struct media_request_object *obj;
+
+   if (WARN_ON(req->state != MEDIA_REQUEST_STATE_VALIDATING &&
+   req->state != MEDIA_REQUEST_STATE_QUEUED))
+   return NULL;
+
+   obj = media_request_object_find(req, _ops, parent);
+   if (obj)
+   return container_of(obj, struct v4l2_ctrl_handler, req_obj);
+   return NULL;
+}
+EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_find);
+
+struct v4l2_ctrl *
+v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id)
+{
+   struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
+
+   return (ref && ref->req == ref) ? ref->ctrl : NULL;
+}
+EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find);
+
 static int v4l2_ctrl_request_bind(struct media_request *req,
   struct v4l2_ctrl_handler *hdl,
   struct v4l2_ctrl_handler *from)
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 98b1e70a4a46..aeb7f3c24ef7 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -,7 +,49 @@ void v4l2_ctrl_request_setup(struct media_request *req,
  * request object.
  */
 void v4l2_ctrl_request_complete(struct media_request *req,
-   struct v4l2_ctrl_handler *hdl);
+   struct v4l2_ctrl_handler *parent);
+
+/**
+ * v4l2_ctrl_request_hdl_find - Find the control handler in the request
+ *
+ * @req: The request
+ * @parent: The parent control handler ('priv' in media_request_object_find())
+ *
+ * This function finds the control handler in the request. It may return
+ * NULL if not found. When done, you must call v4l2_ctrl_request_put_hdl()
+ * with the returned handler pointer.
+ *
+ * If the request is not in state VALIDATING or QUEUED, then this function
+ * will always return NULL.
+ */
+struct v4l2_ctrl_handler *v4l2_ctrl_request_hdl_find(struct media_request *req,
+   struct v4l2_ctrl_handler *parent);
+
+/**
+ * v4l2_ctrl_request_hdl_put - Put the control handler
+ *
+ * @hdl: Put this control handler
+ *
+ * This function released the control handler previously obtained from'
+ * v4l2_ctrl_request_hdl_find().
+ */
+static inline void v4l2_ctrl_request_hdl_put(struct v4l2_ctrl_handler *hdl)
+{
+   if (hdl)
+   media_request_object_put(>req_obj);
+}
+
+/**
+ * v4l2_ctrl_request_ctrl_find() - Find a control with the given ID.
+ *
+ * @hdl: The control handler from the request.
+ * @id: The ID of the control to find.
+ *
+ * This function returns a pointer to the control if this control is
+ * part of the request or NULL otherwise.
+ */
+struct v4l2_ctrl *
+v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id);
 
 /* Helpers for ioctl_ops */
 
-- 
2.18.0



[PATCHv17 33/34] vivid: add request support

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Add support for requests to vivid.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vivid/vivid-core.c|  8 
 drivers/media/platform/vivid/vivid-kthread-cap.c | 12 
 drivers/media/platform/vivid/vivid-kthread-out.c | 12 
 drivers/media/platform/vivid/vivid-sdr-cap.c | 16 
 drivers/media/platform/vivid/vivid-vbi-cap.c | 10 ++
 drivers/media/platform/vivid/vivid-vbi-out.c | 10 ++
 drivers/media/platform/vivid/vivid-vid-cap.c | 10 ++
 drivers/media/platform/vivid/vivid-vid-out.c | 10 ++
 8 files changed, 88 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-core.c 
b/drivers/media/platform/vivid/vivid-core.c
index 1c448529be04..3f6f5cbe1b60 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -627,6 +627,13 @@ static void vivid_dev_release(struct v4l2_device *v4l2_dev)
kfree(dev);
 }
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+static const struct media_device_ops vivid_media_ops = {
+   .req_validate = vb2_request_validate,
+   .req_queue = vb2_request_queue,
+};
+#endif
+
 static int vivid_create_instance(struct platform_device *pdev, int inst)
 {
static const struct v4l2_dv_timings def_dv_timings =
@@ -664,6 +671,7 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
strlcpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
dev->mdev.dev = >dev;
media_device_init(>mdev);
+   dev->mdev.ops = _media_ops;
 #endif
 
/* register v4l2_device */
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c 
b/drivers/media/platform/vivid/vivid-kthread-cap.c
index f06003bb8e42..eebfff2126be 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -703,6 +703,8 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev 
*dev, int dropped_bufs)
goto update_mv;
 
if (vid_cap_buf) {
+   v4l2_ctrl_request_setup(vid_cap_buf->vb.vb2_buf.req_obj.req,
+   >ctrl_hdl_vid_cap);
/* Fill buffer */
vivid_fillbuff(dev, vid_cap_buf);
dprintk(dev, 1, "filled buffer %d\n",
@@ -713,6 +715,8 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev 
*dev, int dropped_bufs)
dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc)
vivid_overlay(dev, vid_cap_buf);
 
+   v4l2_ctrl_request_complete(vid_cap_buf->vb.vb2_buf.req_obj.req,
+  >ctrl_hdl_vid_cap);
vb2_buffer_done(_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",
@@ -720,10 +724,14 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev 
*dev, int dropped_bufs)
}
 
if (vbi_cap_buf) {
+   v4l2_ctrl_request_setup(vbi_cap_buf->vb.vb2_buf.req_obj.req,
+   >ctrl_hdl_vbi_cap);
if (dev->stream_sliced_vbi_cap)
vivid_sliced_vbi_cap_process(dev, vbi_cap_buf);
else
vivid_raw_vbi_cap_process(dev, vbi_cap_buf);
+   v4l2_ctrl_request_complete(vbi_cap_buf->vb.vb2_buf.req_obj.req,
+  >ctrl_hdl_vbi_cap);
vb2_buffer_done(_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vbi_cap %d done\n",
@@ -891,6 +899,8 @@ 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(>list);
+   v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
+  >ctrl_hdl_vid_cap);
vb2_buffer_done(>vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(dev, 2, "vid_cap buffer %d done\n",
buf->vb.vb2_buf.index);
@@ -904,6 +914,8 @@ 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(>list);
+   v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
+  >ctrl_hdl_vbi_cap);
vb2_buffer_done(>vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(dev, 2, "vbi_cap buffer %d done\n",

[PATCHv17 30/34] vim2m: use workqueue

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

v4l2_ctrl uses mutexes, so we can't setup a ctrl_handler in
interrupt context. Switch to a workqueue instead and drop the timer.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vim2m.c | 25 ++---
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 462099a141e4..6f87ef025ff1 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -3,7 +3,8 @@
  *
  * This is a virtual device driver for testing mem-to-mem videobuf framework.
  * It simulates a device that uses memory buffers for both source and
- * destination, processes the data and issues an "irq" (simulated by a timer).
+ * destination, processes the data and issues an "irq" (simulated by a delayed
+ * workqueue).
  * The device is capable of multi-instance, multi-buffer-per-transaction
  * operation (via the mem2mem framework).
  *
@@ -19,7 +20,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 
@@ -148,7 +148,7 @@ struct vim2m_dev {
struct mutexdev_mutex;
spinlock_t  irqlock;
 
-   struct timer_list   timer;
+   struct delayed_work work_run;
 
struct v4l2_m2m_dev *m2m_dev;
 };
@@ -336,12 +336,6 @@ static int device_process(struct vim2m_ctx *ctx,
return 0;
 }
 
-static void schedule_irq(struct vim2m_dev *dev, int msec_timeout)
-{
-   dprintk(dev, "Scheduling a simulated irq\n");
-   mod_timer(>timer, jiffies + msecs_to_jiffies(msec_timeout));
-}
-
 /*
  * mem2mem callbacks
  */
@@ -387,13 +381,14 @@ static void device_run(void *priv)
 
device_process(ctx, src_buf, dst_buf);
 
-   /* Run a timer, which simulates a hardware irq  */
-   schedule_irq(dev, ctx->transtime);
+   /* Run delayed work, which simulates a hardware irq  */
+   schedule_delayed_work(>work_run, msecs_to_jiffies(ctx->transtime));
 }
 
-static void device_isr(struct timer_list *t)
+static void device_work(struct work_struct *w)
 {
-   struct vim2m_dev *vim2m_dev = from_timer(vim2m_dev, t, timer);
+   struct vim2m_dev *vim2m_dev =
+   container_of(w, struct vim2m_dev, work_run.work);
struct vim2m_ctx *curr_ctx;
struct vb2_v4l2_buffer *src_vb, *dst_vb;
unsigned long flags;
@@ -805,6 +800,7 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
struct vb2_v4l2_buffer *vbuf;
unsigned long flags;
 
+   flush_scheduled_work();
for (;;) {
if (V4L2_TYPE_IS_OUTPUT(q->type))
vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
@@ -1015,6 +1011,7 @@ static int vim2m_probe(struct platform_device *pdev)
vfd = >vfd;
vfd->lock = >dev_mutex;
vfd->v4l2_dev = >v4l2_dev;
+   INIT_DELAYED_WORK(>work_run, device_work);
 
ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
if (ret) {
@@ -1026,7 +1023,6 @@ static int vim2m_probe(struct platform_device *pdev)
v4l2_info(>v4l2_dev,
"Device registered as /dev/video%d\n", vfd->num);
 
-   timer_setup(>timer, device_isr, 0);
platform_set_drvdata(pdev, dev);
 
dev->m2m_dev = v4l2_m2m_init(_ops);
@@ -1083,7 +1079,6 @@ static int vim2m_remove(struct platform_device *pdev)
media_device_cleanup(>mdev);
 #endif
v4l2_m2m_release(dev->m2m_dev);
-   del_timer_sync(>timer);
video_unregister_device(>vfd);
v4l2_device_unregister(>v4l2_dev);
 
-- 
2.18.0



[PATCHv17 32/34] vivid: add mc

2018-08-04 Thread Hans Verkuil
From: Hans Verkuil 

Add support for the media_device to vivid. This is a prerequisite
for request support.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vivid/vivid-core.c | 61 +++
 drivers/media/platform/vivid/vivid-core.h |  8 +++
 2 files changed, 69 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-core.c 
b/drivers/media/platform/vivid/vivid-core.c
index 31db363602e5..1c448529be04 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -657,6 +657,15 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
 
dev->inst = inst;
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->v4l2_dev.mdev = >mdev;
+
+   /* Initialize media device */
+   strlcpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
+   dev->mdev.dev = >dev;
+   media_device_init(>mdev);
+#endif
+
/* register v4l2_device */
snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
"%s-%03d", VIVID_MODULE_NAME, inst);
@@ -1174,6 +1183,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->lock = >mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(>entity, 1, 
>vid_cap_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
 #ifdef CONFIG_VIDEO_VIVID_CEC
if (in_type_counter[HDMI]) {
struct cec_adapter *adap;
@@ -1226,6 +1242,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->lock = >mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE;
+   ret = media_entity_pads_init(>entity, 1, 
>vid_out_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
 #ifdef CONFIG_VIDEO_VIVID_CEC
for (i = 0; i < dev->num_outputs; i++) {
struct cec_adapter *adap;
@@ -1275,6 +1298,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->tvnorms = tvnorms_cap;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vbi_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(>entity, 1, 
>vbi_cap_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
ret = video_register_device(vfd, VFL_TYPE_VBI, 
vbi_cap_nr[inst]);
if (ret < 0)
goto unreg_dev;
@@ -1300,6 +1330,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->tvnorms = tvnorms_out;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vbi_out_pad.flags = MEDIA_PAD_FL_SOURCE;
+   ret = media_entity_pads_init(>entity, 1, 
>vbi_out_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
ret = video_register_device(vfd, VFL_TYPE_VBI, 
vbi_out_nr[inst]);
if (ret < 0)
goto unreg_dev;
@@ -1323,6 +1360,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->lock = >mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(>entity, 1, 
>sdr_cap_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
ret = video_register_device(vfd, VFL_TYPE_SDR, 
sdr_cap_nr[inst]);
if (ret < 0)
goto unreg_dev;
@@ -1369,12 +1413,25 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
  video_device_node_name(vfd));
}
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   /* Register the media device */
+   ret = media_device_register(>mdev);
+   if (ret) {
+   dev_err(dev->mdev.dev,
+   "media device register failed (err=%d)\n", ret);
+   goto unreg_dev;
+   }
+#endif
+
/* Now that everything is fine, let's add it to device list */
vivid_devs[inst] = dev;
 
return 0;
 
 unreg_dev:
+#ifdef CONFIG_MEDIA_CONTROLLER
+   media_device_unregister(>mdev);
+#endif
video_unregister_device(>radio_tx_dev);
video_unregister_device(>radio_rx_dev);
video_unregister_device(>sdr_cap_dev);
@@ -1445,6 +1502,10 @@ static int vivid_remove(struct platform_device *pdev)
if (!dev)
continue;
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   media_device_unregister(>mdev);
+#endif
+
 

Re: [PATCHv16 01/34] Documentation: v4l: document request API

2018-08-04 Thread Hans Verkuil
Hi Tomasz,

Thank you for your review. Unless stated otherwise I have incorporated your
suggestions.

On 08/03/2018 05:00 PM, Tomasz Figa wrote:
> Hi Hans,
> 
> On Fri, Jul 6, 2018 at 1:04 AM Hans Verkuil  wrote:
>>
>> From: Alexandre Courbot 
>>
>> Document the request API for V4L2 devices, and amend the documentation
>> of system calls influenced by it.
>>
>> Signed-off-by: Alexandre Courbot 
>> Signed-off-by: Hans Verkuil 
>> ---
>>  .../media/uapi/mediactl/media-controller.rst  |   1 +
>>  .../media/uapi/mediactl/media-funcs.rst   |   6 +
>>  .../uapi/mediactl/media-ioc-request-alloc.rst |  77 ++
>>  .../uapi/mediactl/media-request-ioc-queue.rst |  81 ++
>>  .../mediactl/media-request-ioc-reinit.rst |  51 
>>  .../media/uapi/mediactl/request-api.rst   | 247 ++
>>  .../uapi/mediactl/request-func-close.rst  |  49 
>>  .../uapi/mediactl/request-func-ioctl.rst  |  68 +
>>  .../media/uapi/mediactl/request-func-poll.rst |  74 ++
>>  Documentation/media/uapi/v4l/buffer.rst   |  21 +-
>>  .../media/uapi/v4l/vidioc-g-ext-ctrls.rst |  94 ---
>>  Documentation/media/uapi/v4l/vidioc-qbuf.rst  |  32 ++-
>>  .../media/videodev2.h.rst.exceptions  |   1 +
>>  13 files changed, 766 insertions(+), 36 deletions(-)
>>  create mode 100644 
>> Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
>>  create mode 100644 
>> Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
>>  create mode 100644 
>> Documentation/media/uapi/mediactl/media-request-ioc-reinit.rst
>>  create mode 100644 Documentation/media/uapi/mediactl/request-api.rst
>>  create mode 100644 Documentation/media/uapi/mediactl/request-func-close.rst
>>  create mode 100644 Documentation/media/uapi/mediactl/request-func-ioctl.rst
>>  create mode 100644 Documentation/media/uapi/mediactl/request-func-poll.rst
>>
> 
> Thanks a lot for working on this and sorry for being late to the
> party. Please see some comments inline. (Mostly wording nits, though.)
> 



>> diff --git a/Documentation/media/uapi/mediactl/request-api.rst 
>> b/Documentation/media/uapi/mediactl/request-api.rst
>> new file mode 100644
>> index ..3c49627acb72
>> --- /dev/null
>> +++ b/Documentation/media/uapi/mediactl/request-api.rst
>> @@ -0,0 +1,247 @@
>> +.. -*- coding: utf-8; mode: rst -*-
>> +
>> +.. _media-request-api:
>> +
>> +Request API
>> +===
>> +
>> +The Request API has been designed to allow V4L2 to deal with requirements of
>> +modern devices (stateless codecs, complex camera pipelines, ...) and APIs
>> +(Android Codec v2). One such requirement is the ability for devices 
>> belonging to
>> +the same pipeline to reconfigure and collaborate closely on a per-frame 
>> basis.
>> +Another is efficient support of stateless codecs, which need per-frame 
>> controls
>> +to be set synchronously in order to be used efficiently.
> 
> I think "synchronously" would match what we could do without Request
> API (wait for 1 frame to be dequeued, set control, queue next frame,
> etc.) and it would be inefficient. Perhaps "Another is efficient
> support of stateless codecs, which need controls to be set for exact
> frames beforehand to be used efficiently."?

I went with this:

"Another is support of stateless codecs, which require controls to be applied
to specific frames (aka 'per-frame controls') in order to be used efficiently."



>> +Once the request is fully prepared, it can be queued to the driver:
>> +
>> +.. code-block:: c
>> +
>> +   if (ioctl(req_fd, MEDIA_REQUEST_IOC_QUEUE))
>> +   return some_error;
> 
> This may suggest that it's okay to ignore the error code and just
> handle all the errors the same way. Perhaps "return some_error; /*
> check errno for exact error code */"?

I've just renamed 'some_error' to 'errno'. That makes much more sense.



>> diff --git a/Documentation/media/uapi/mediactl/request-func-close.rst 
>> b/Documentation/media/uapi/mediactl/request-func-close.rst
>> new file mode 100644
>> index ..1195f493bf05
>> --- /dev/null
>> +++ b/Documentation/media/uapi/mediactl/request-func-close.rst
>> @@ -0,0 +1,49 @@
>> +.. SPDX-License-Identifier: GPL-2.0
>> +.. -*- coding: utf-8; mode: rst -*-
>> +
>> +.. _request-func-close:
>> +
>> +***
>> +request close()
>> +***
>> +
>> +Name
>> +
>> +
>> +request-close - Close a request file descriptor
>> +
>> +
>> +Synopsis
>> +
>> +
>> +.. code-block:: c
>> +
>> +#include 
>> +
>> +
>> +.. c:function:: int close( int fd )
>> +:name: req-close
>> +
>> +Arguments
>> +=
>> +
>> +``fd``
>> +File descriptor returned by :ref:`MEDIA_IOC_REQUEST_ALLOC`.
>> +
> 
> I guess for now we're not considering exchanging those between
> processes, but even then, this could be a dup()ed descriptor too.

I've kept this as-is. We never mention dup() specifically for other
APIs either and I think it is overkill to do so.

> 
>> +
>> +Description
>> 

[PATCH] mediactl/*.rst: document argp

2018-08-04 Thread Hans Verkuil
The documentation of the Media Controller API ioctls is missing a description
of the argp ioctl argument. Add this.

Signed-off-by: Hans Verkuil 
---
diff --git a/Documentation/media/uapi/mediactl/media-ioc-device-info.rst 
b/Documentation/media/uapi/mediactl/media-ioc-device-info.rst
index 649cb3d9e058..c6f224e404b7 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-device-info.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-device-info.rst
@@ -26,6 +26,7 @@ Arguments
 File descriptor returned by :ref:`open() `.

 ``argp``
+Pointer to struct :c:type:`media_device_info`.


 Description
diff --git a/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst 
b/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst
index fc2e39c070c9..02738640e34e 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-enum-entities.rst
@@ -26,6 +26,7 @@ Arguments
 File descriptor returned by :ref:`open() `.

 ``argp``
+Pointer to struct :c:type:`media_entity_desc`.


 Description
diff --git a/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst 
b/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst
index f158c134e9b0..b89aaae373df 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-enum-links.rst
@@ -26,6 +26,7 @@ Arguments
 File descriptor returned by :ref:`open() `.

 ``argp``
+Pointer to struct :c:type:`media_links_enum`.


 Description
diff --git a/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst 
b/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst
index bac128c7eda9..4e1c59238371 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-g-topology.rst
@@ -26,6 +26,7 @@ Arguments
 File descriptor returned by :ref:`open() `.

 ``argp``
+Pointer to struct :c:type:`media_v2_topology`.


 Description
diff --git a/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst 
b/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst
index ae5194940100..e345e7dc9ad7 100644
--- a/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst
+++ b/Documentation/media/uapi/mediactl/media-ioc-setup-link.rst
@@ -26,6 +26,7 @@ Arguments
 File descriptor returned by :ref:`open() `.

 ``argp``
+Pointer to struct :c:type:`media_link_desc`.


 Description


Re: [PATCH 20/22] [media] tvp5150: Add input port connectors DT bindings

2018-08-04 Thread Marco Felsch
Hi Mauro,

On 18-08-03 14:30, Mauro Carvalho Chehab wrote:
> Em Fri, 3 Aug 2018 09:29:53 +0200
> Marco Felsch  escreveu:
> 
> > Hi Rob,
> > 
> > first of all, thanks for the review. After some discussion with the
> > media guys I have a question about the dt-bindings.
> > 
> > On 18-07-03 17:23, Rob Herring wrote:
> > > On Thu, Jun 28, 2018 at 06:20:52PM +0200, Marco Felsch wrote:  
> > > > The TVP5150/1 decoders support different video input sources to their
> > > > AIP1A/B pins.
> > > > 
> > > > Possible configurations are as follows:
> > > >   - Analog Composite signal connected to AIP1A.
> > > >   - Analog Composite signal connected to AIP1B.
> > > >   - Analog S-Video Y (luminance) and C (chrominance)
> > > > signals connected to AIP1A and AIP1B respectively.
> > > > 
> > > > This patch extends the device tree bindings documentation to describe
> > > > how the input connectors for these devices should be defined in a DT.
> > > > 
> > > > Signed-off-by: Marco Felsch 
> > > > ---
> > > >  .../devicetree/bindings/media/i2c/tvp5150.txt | 118 +-
> > > >  1 file changed, 113 insertions(+), 5 deletions(-)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt 
> > > > b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > > > index 8c0fc1a26bf0..feed8c911c5e 100644
> > > > --- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > > > +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > > > @@ -12,11 +12,23 @@ Optional Properties:
> > > >  - pdn-gpios: phandle for the GPIO connected to the PDN pin, if any.
> > > >  - reset-gpios: phandle for the GPIO connected to the RESETB pin, if 
> > > > any.
> > > >  
> > > > -The device node must contain one 'port' child node for its digital 
> > > > output
> > > > -video port, in accordance with the video interface bindings defined in
> > > > -Documentation/devicetree/bindings/media/video-interfaces.txt.
> > > > +The device node must contain one 'port' child node per device input 
> > > > and output
> > > > +port, in accordance with the video interface bindings defined in
> > > > +Documentation/devicetree/bindings/media/video-interfaces.txt. The port 
> > > > nodes
> > > > +are numbered as follows
> > > >  
> > > > -Required Endpoint Properties for parallel synchronization:
> > > > + Name  TypePort
> > > > +   --
> > > > + AIP1A sink0
> > > > + AIP1B sink1
> > > > + S-VIDEO   sink2
> > > > + Y-OUT src 3  
> > 
> > Do you think it's correct to have a seperate port for each binding?
> > Since the S-Video port is a combination of AIP1A and AIP1B. After a
> > discussion with Mauro [1] the TVP5150 should have only 3 pads. Since the
> > pads are directly mappped to the dt-ports this will correspond to three
> > ports (2 in, 1 out). Now the svideo connector will be mapped to a second
> > endpoint in each port:
> > 
> > port@0  
> > endpoint@0 ---> Comp0-Con
> > endpoint@1 -+-> Svideo-Con
> > port@1  |
> > endpoint@0 -|-> Comp1-Con
> > endpoint@1 -+
> > port@2
> > endpoint
> 
> For tvp5150, the model is like the above, so just one port at the
> S-video connector.

Okay, but this won't work. I tested it yesterday. Since the svideo port
is linked to two endpoints and the DTC will throw an error
"ERROR (duplicate_label)". Which make sens, but I covered it to late...

So we have two opportunities: 1) the one you described below or 2) we
map only port@0/port@1 to the svideo connector.

Anyway, should endpoint@1 always refer to the svideo connector or should
it be independent (in case of 1xcomp-con and 1xsvideo-con)?

> 
> Yet, for more complex devices that would allow switching the
> endpoints at the Svideo connector, the model would be:
> 
> port@0
>   endpoint@0 (AIP1A) ---> Comp0-Con
>   endpoint@1 (AIP1B) ---> Svideo-Con  port@0 (luminance)
> port@1
>   endpoint@0 (AIP1A) ---> Comp1-Con
>   endpoint@1 (AIP1B) ---> Svideo-Con  port@1 (chrominance)
> port@2
>   endpoint   (video bitstream output)
> 
> E. g. the S-Video connector will also have two ports, one for the
> chrominance signal and another one for the luminance one.
> 
> > I don't like that solution that much, since the mapping is now signal
> > based. We also don't map each line of a parallel port.
> > 
> > A quick grep shows that currently each device using a svideo connector
> > seperates them in a own port as I did.
> 
> No. I've no idea about how you did the grep, but this is not how other
> drivers handle it currently.

Sorry for that. My grep only covered the dt related connectors and not the
connectors within the mc framework.

> 
> Right now, on all hardware where connectors are mapped, there is just one
>