cron job: media_tree daily build: WARNINGS

2018-08-14 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:   Wed Aug 15 05:00:16 CEST 2018
media-tree git hash:da2048b7348a0be92f706ac019e022139e29495e
media_build git hash:   baf45935ffad914f33faf751ad9f4d0dd276c021
v4l-utils git hash: 4e160e6dfc8705fbc6867c880f445e69fcedcada
edid-decode git hash:   b2da1516df3cc2756bfe8d1fa06d7bf2562ba1f4
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: OK
linux-git-mips: OK
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: OK
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.18-i686: OK
linux-4.18-x86_64: OK
apps: WARNINGS
spec-git: OK
sparse: WARNINGS

Detailed results are available here:

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

Full logs are available here:

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

The Media Infrastructure API from this daily build is here:

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


RE: Using big platform driver as foundation to implement TV driver framework in Linux

2018-08-14 Thread 黃建興
Hi Mchehab,

We are very appreciating for your reply.

For GPL, We are agree to follow GPL license to open source code which is in 
Linux kernel.
For "but we don't accept any other OS-dependent code", we can follow this rule 
to remove relative OS-dependent code.
For " If otherwise all you want is to have a wrapper driver to run some 
proprietary driver, then shipping such solution would likely be a copyright 
violation and we can't help you.",
We can follow GPL, Our intention is not to be a copyright violation.

What we hope to do is to separate our board support package to two part. One is 
driver part, another is platform part.
We want to put driver part to kernel source folder driver/media, or driver/xxx 
and put platform part to arch/arm/mach-xxx.
Both of those code will follow GPL license, and we want to upstream both into 
main Linux code line.

Because our hardware is a consumerism orientation production, different 
hardware module is highly dependency to provide cost efficiency performance. It 
will cause our driver implement concept will have huge different with other 
company or personal computer.
For this reason, we want to collect non-standard part implement to "platform", 
in our view this is a very low level / highly hardware dependency from our 
production to product. We also hope most of platform part can be re-use to 
another OS, it can reduce cost for quality assurance or sync of bug fix to 
different OS.
We hope driver part can join and co-work with media community. Provide those 
driver part will reduce cost and time to upgrade to new version of kernel.

For example, the model we expect is:

User mode APP   ==interface(V4L2)==>   /driver/media/V4L2_Jpeg   == interface(a 
kind of media platform, hope have standard)==>   
/arch/arm/mach-MTK-TV-model2/platform_jpeg





-Original Message-
From: Mauro Carvalho Chehab [mailto:mchehab+sams...@kernel.org] 
Sent: Tuesday, August 14, 2018 5:39 PM
To: Jesse Huang (黃建興) 
Cc: mche...@kernel.org; linux-media@vger.kernel.org; Yishin Tung (童怡新) 
; Zink Hsin (辛鴻杰) ; MF Hsieh 
(謝明甫) ; Junyou Lin (林俊裕) 
Subject: Re: Using big platform driver as foundation to implement TV driver 
framework in Linux

Hi Jesse,

Em Mon, 13 Aug 2018 01:32:45 +
Jesse Huang (黃建興)  escreveu:

> Hi Mchehab,
> Hi Linux-Media,
> 
> MTK/MStar try to move TV SOC proprietary driver framework to Linux TV driver.
> 
> But, we also need to share/re-use driver code to non-OS which is a size 
> limitation low cost system.
> 
> Normally, each Linux driver need to control registers directly by it self. 
> For example:
> ===(sample code begin) 
> linux-3.18-exynos7270-sandbox.opensw0312.rebase-3d91408\drivers\media\
> pci\cx25821\cx25821-video.c static int vidioc_streamon(struct file 
> *file, void *priv, enum v4l2_buf_type i) {
> struct cx25821_channel *chan = video_drvdata(file);
> 
> if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> return -EINVAL;
> 
> if (chan->streaming_fh && chan->streaming_fh != priv)
> return -EBUSY;
> chan->streaming_fh = priv;
> 
> return videobuf_streamon(&chan->vidq); } 
> ===(sample code end)
> 
> 
> 
> But, in our concept, we hope to provide an entire proprietary a driver as a 
> “MTK TV platform driver”. Base on this driver to implement Linux standard TV 
> driver.
> If will look like this:
> ===(sample code begin) static int 
> vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) {
> return mtk_tv_platform->video->streamon();
> }
> 
> The mtk_tv_platform will be register when setup_arch() void __init 
> setup_arch(char **cmdline_p) { return 
> platform_device_register(&mtk_tv_platform);
> }
> ===(sample code end)
> 
> Would this kid of implement method can be accept for Linux upstream/submit 
> driver rule? What kind of framework design guide line/rule we should follow? 
> Would it possible to have some reference for us.
> 
> If this method is possible, we can share a lot of human resource to both 
> maintain for Linux and non-Linux project.

Not sure if I understand what you want to do.

The Linux Kernel is under a GPL version 2 license, meaning that anyone wanting 
to do Kernel development should license their work under those terms.

In other words, If you want to submit a driver to the Linux Kernel, the needed 
software to control the hardware should all be upstreamed using GPL version 2, 
including all register settings.

In the specific case of image enhancement algorithms, like 3A, we're currently 
working on a solution that would allow a third party software (ideally open 
source, but it could be a binary code) to run on userspace, receiving metadata 
from the hardware via a documented userspace, and using the standard V4L2 API 
to adjust the hardware, after doing some (usually proprietary) processing.

So, if you're willing to contribute under this terms, we can help you.

It could

Re: [PATCH v2 0/2] media: i2c: ov5640: Re-work MIPI startup sequence

2018-08-14 Thread Steve Longerbeam




On 08/14/2018 10:38 AM, jacopo mondi wrote:

Hi Steve,

On Tue, Aug 14, 2018 at 09:51:04AM -0700, Steve Longerbeam wrote:

Hi Jacopo,


On 08/14/2018 08:35 AM, jacopo mondi wrote:

Hi Steve,
sorry for resurecting this.



I'm sorry I'm not sur I'm following. Does this mean that with that bug
you are referring to up here fixed by my last patch you have capture
working?

No, capture still not working for me on SabreSD, even after fixing
the bug in 476dec0 "media: ov5640: Add horizontal and vertical totals",
by either using your patchset, or by running version 476dec0 of ov5640.c
with the call to ov5640_set_timings() moved to the correct places as
described below.


I've been reported a bug on exposure handling that makes the first
captured frames all black. Both me and Hugues have tried to fix the
issue (him with a more complete series, but that's another topic).
See [1] and [2]

It might be possible that you're getting blank frames with this series
applied? I never seen them as I'm skipping the first frames when
capturing, but I've now tested and without the exposure fixes (either
[1] or [2]) I actually have blank frames.

If that's the case for you too (which I hope so much) would you be
available to test again this series with exposure fixes on top?
On my platform that actually makes all frames correct.

Thanks
j

[1] [PATCH 0/2] media: ov5640: Fix set_timings and auto-exposure
[2] [PATCH v2 0/5] Fix OV5640 exposure & gain


It's not clear to me which patch sets you would like me to test.
Just [1] and [2], or [1], [2], and "media: i2c: ov5640: Re-work MIPI startup
sequence"?


I have tested on my board the following:
v4.18-rc2 + MIPI Fix + Timings + Hugues' exposure fix

Without Hugues' patches I get blank frames (the first ones at least)
Without MIPI startup reowkr and timings I get the LP-11 error on the
CSI-2 bus.

As Hugues' series has to be rebased on mine, I have prepared a branch
here for you if you feel like testing it:
git://jmondi.org/linux ov5640/timings_exposure


Hi Jacopo, that branch works on SabreSD!

Feel free to add

Tested-by: Steve Longerbeam 
on i.MX6q SabreSD with MIPI CSI-2 OV5640 module

to whichever ov5640 patches are appropriate.

Steve




Re: [PATCH 1/3] dt-bindings: media: Add i.MX Pixel Pipeline binding

2018-08-14 Thread Rob Herring
On Fri, 10 Aug 2018 17:18:20 +0200, Philipp Zabel wrote:
> Add DT binding documentation for the Pixel Pipeline (PXP) found on
> various NXP i.MX SoCs.
> 
> Signed-off-by: Philipp Zabel 
> ---
>  .../devicetree/bindings/media/fsl-pxp.txt | 26 +++
>  1 file changed, 26 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/media/fsl-pxp.txt
> 

Reviewed-by: Rob Herring 


Re: [PATCHv18 00/35] Request API

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 17:01:07 -0300
Mauro Carvalho Chehab  escreveu:

> > 
> > Besides all the review comments I also fixed a bug. See:
> > https://www.mail-archive.com/linux-media@vger.kernel.org/msg134311.html  
> 
> I'll look on it right now.

Sorry, I meant to say that I'm looking into this email:
https://www.mail-archive.com/linux-media@vger.kernel.org/msg134053.html

Thanks,
Mauro


Re: [PATCHv18 00/35] Request API

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:12 +0200
Hans Verkuil  escreveu:

> From: Hans Verkuil 
> 
> Hi all,
> 
> This is version 18 of the Request API series. The intention is that
> this will become a topic branch in preparation of merging this for
> 4.20 together with the cedrus staging driver.
> 
> I incorporated Mauro's review comments and a review comment from
> Ezequiel in v18.
> 
> The main change is that I reverted back to a simple int argument for the
> MEDIA_IOC_REQUEST_ALLOC ioctl. Mauro prefers it and I think he is right.
> It was what we had originally as well.
> 
> Besides all the review comments I also fixed a bug. See:
> https://www.mail-archive.com/linux-media@vger.kernel.org/msg134311.html

I'll look on it right now.

> 
> And sparse warned me about a poll prototype change, so the
> media_request_poll() was slightly changed (use of EPOLL* instead of POLL*
> and a __poll_t return type).
> 
> I also split up the old patch 17/34 into three patches: the first just
> moves a function up in the source, the second replaces 'if' statements
> with a switch, and the third is the actual patch that does the real
> work. There is now much less noise in that patch and it should be much easier
> to review.
> 
> Finally the RFC debugfs patch has been dropped from this series.
> 
> This patch series is also available here:
> 
> https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=reqv18
> 
> 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
> 
> To avoid having to do a full review again I made a diff between
> v17 and v18 that is much easier to understand. I added it below
> the line (note that the removal of the debugfs patch is not included
> in this diff, it's not useful).

Patchset looks ok. Just not sure about a timestamp change at the
VB2 code. Found one or two nitpicks too. Once addressed, I guess
it is ready for being merged on a topic branch.

If nobody would require major changes, IMO the best would be
to just reply to a v19 patch to the few ones that might require
a respin.

> 
> Regards,
> 
>   Hans
> 
> Alexandre Courbot (2):
>   Documentation: v4l: document request API
>   videodev2.h: add request_fd field to v4l2_ext_controls
> 
> Hans Verkuil (32):
>   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
>   videobuf2-v4l2: move __fill_v4l2_buffer() function
>   videobuf2-v4l2: replace if by switch in __fill_vb2_buffer()
>   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
> 
> 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 |  65 +++
>  .../uapi/mediactl/media-request-ioc-queue.rst |  82 +++
>  .../mediactl/media-request-ioc-reinit.rst |  51 ++
>  .../media/uapi/mediactl/request-api.rst   | 245 
>  .../uapi/mediactl/request-func-close.rst  |  48 ++
>  .../uapi/mediactl/request-func-ioctl.rst  |  67 +++
>  .../media/uapi/mediactl/request-func-poll.rst |  77 +++
>  Documentation/media/uapi/v4l/buffer.rst   |  21 +-
>  .../media/uapi/v4l/vidioc-g-ext-ctrls.rst |  53 +-
>  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   | 508 +++-
>  drivers/media/dvb-core/dvb_vb2.c  |   5

Re: [PATCHv18 31/35] v4l2-mem2mem: add vb2_m2m_request_queue

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:43 +0200
Hans Verkuil  escreveu:

> 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 

Reviewed-by: Mauro Carvalho Chehab 

> ---
>  drivers/media/v4l2-core/v4l2-mem2mem.c | 63 ++
>  include/media/v4l2-mem2mem.h   |  4 ++
>  2 files changed, 59 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c 
> b/drivers/media/v4l2-core/v4l2-mem2mem.c
> index 4de8fa163fd3..d7806db222d8 100644
> --- a/drivers/media/v4l2-core/v4l2-mem2mem.c
> +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
> @@ -387,7 +387,7 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx 
> *m2m_ctx)
>   spin_unlock_irqrestore(&m2m_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) {
> @@ -478,8 +478,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;
> @@ -501,14 +507,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);
>  
> @@ -952,6 +953,52 @@ 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 objects. Note that buffer objects are at the end of the
> +  * objects list, after all other object types. Once buffer objects
> +  * are queued, the driver might delete them immediately (if the driver
> +  * processes the buffer at once), so we have to use
> +  * list_for_each_entry_safe() to handle the case where the object we
> +  * queue is deleted.
> +  */
> + list_for_each_entry_safe(obj, obj_safe, &req->objects, list) {
> + struct v4l2_m2m_ctx *m2m_ctx_obj;
> + struct vb2_buffer *vb;
> +
> + if (!obj->ops->queue)
> + continue;
> +
> + if (vb2_request_object_is_buffer(obj)) {
> + /* 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 

Re: [PATCHv18 28/35] videobuf2-v4l2: add vb2_request_queue/validate helpers

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:40 +0200
Hans Verkuil  escreveu:

> 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.

Reviewed-by: Mauro Carvalho Chehab 
> 
> Signed-off-by: Hans Verkuil 
> ---
>  .../media/common/videobuf2/videobuf2-v4l2.c   | 51 +++
>  include/media/videobuf2-v4l2.h|  4 ++
>  2 files changed, 55 insertions(+)
> 
> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
> b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> index 9c652afa62ab..364b1fea3826 100644
> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> @@ -1100,6 +1100,57 @@ void vb2_ops_wait_finish(struct vb2_queue *vq)
>  }
>  EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
>  
> +/*
> + * Note that this function is called during validation time and
> + * thus the req_queue_mutex is held to ensure no request objects
> + * can be added or deleted while validating. So there is no need
> + * to protect the objects list.
> + */
> +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, &req->objects, list) {
> + if (!obj->ops->prepare)
> + continue;
> +
> + ret = obj->ops->prepare(obj);
> + if (ret)
> + break;
> + }
> +
> + if (ret) {
> + list_for_each_entry_continue_reverse(obj, &req->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 objects. Note that buffer objects are at the end of the
> +  * objects list, after all other object types. Once buffer objects
> +  * are queued, the driver might delete them immediately (if the driver
> +  * processes the buffer at once), so we have to use
> +  * list_for_each_entry_safe() to handle the case where the object we
> +  * queue is deleted.
> +  */
> + list_for_each_entry_safe(obj, obj_safe, &req->objects, list)
> + if (obj->ops->queue)
> + 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 */



Thanks,
Mauro


Re: [PATCHv18 24/35] videobuf2-core: embed media_request_object

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:36 +0200
Hans Verkuil  escreveu:

> From: Hans Verkuil 
> 
> Make vb2_buffer a request object.
> 
> Signed-off-by: Hans Verkuil 

I had already sent a reviewed-by to this. Anyway:

Reviewed-by: Mauro Carvalho Chehab 


> ---
>  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 2eb24961183e..413b8b2dc485 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
>*



Thanks,
Mauro


Re: [PATCHv18 21/35] vb2: drop VB2_BUF_STATE_PREPARED, use bool prepared/synced instead

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:33 +0200
Hans Verkuil  escreveu:

> 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 

Reviewed-by: Mauro Carvalho Chehab 
> ---
>  .../media/common/videobuf2/videobuf2-core.c   | 38 +--
>  .../media/common/videobuf2/videobuf2-v4l2.c   | 16 +---
>  include/media/videobuf2-core.h| 10 -
>  3 files changed, 44 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(&q->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; ++p

Re: [PATCHv18 19/35] vb2: store userspace data in vb2_v4l2_buffer

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:31 +0200
Hans Verkuil  escreveu:

> 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   | 60 +++
>  drivers/media/dvb-core/dvb_vb2.c  |  3 +-
>  include/media/videobuf2-core.h|  3 +-
>  include/media/videobuf2-v4l2.h|  2 +
>  5 files changed, 72 insertions(+), 39 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(s

Re: [PATCHv18 17/35] videobuf2-v4l2: move __fill_v4l2_buffer() function

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:29 +0200
Hans Verkuil  escreveu:

> From: Hans Verkuil 
> 
> Move the __fill_v4l2_buffer() to before the vb2_queue_or_prepare_buf()
> function to prepare for the next two patches.
> 
> No other changes.
> 
> Signed-off-by: Hans Verkuil 
Reviewed-by: Mauro Carvalho Chehab 

> ---
>  .../media/common/videobuf2/videobuf2-v4l2.c   | 264 +-
>  1 file changed, 132 insertions(+), 132 deletions(-)
> 
> diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
> b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> index 886a2d8d5c6c..408fd7ce9c09 100644
> --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
> +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
> @@ -154,138 +154,6 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer 
> *vb)
>   pr_warn("use the actual size instead.\n");
>  }
>  
> -static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer 
> *b,
> - const char *opname)
> -{
> - if (b->type != q->type) {
> - dprintk(1, "%s: invalid buffer type\n", opname);
> - return -EINVAL;
> - }
> -
> - if (b->index >= q->num_buffers) {
> - dprintk(1, "%s: buffer index out of range\n", opname);
> - return -EINVAL;
> - }
> -
> - if (q->bufs[b->index] == NULL) {
> - /* Should never happen */
> - dprintk(1, "%s: buffer is NULL\n", opname);
> - return -EINVAL;
> - }
> -
> - if (b->memory != q->memory) {
> - dprintk(1, "%s: invalid memory type\n", opname);
> - return -EINVAL;
> - }
> -
> - return __verify_planes_array(q->bufs[b->index], b);
> -}
> -
> -/*
> - * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
> - * returned to userspace
> - */
> -static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
> -{
> - struct v4l2_buffer *b = pb;
> - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
> - struct vb2_queue *q = vb->vb2_queue;
> - unsigned int plane;
> -
> - /* Copy back data such as timestamp, flags, etc. */
> - b->index = vb->index;
> - b->type = vb->type;
> - b->memory = vb->memory;
> - b->bytesused = 0;
> -
> - b->flags = vbuf->flags;
> - b->field = vbuf->field;
> - b->timestamp = ns_to_timeval(vb->timestamp);
> - b->timecode = vbuf->timecode;
> - b->sequence = vbuf->sequence;
> - b->reserved2 = 0;
> - b->reserved = 0;
> -
> - if (q->is_multiplanar) {
> - /*
> -  * Fill in plane-related data if userspace provided an array
> -  * for it. The caller has already verified memory and size.
> -  */
> - b->length = vb->num_planes;
> - for (plane = 0; plane < vb->num_planes; ++plane) {
> - struct v4l2_plane *pdst = &b->m.planes[plane];
> - struct vb2_plane *psrc = &vb->planes[plane];
> -
> - pdst->bytesused = psrc->bytesused;
> - pdst->length = psrc->length;
> - if (q->memory == VB2_MEMORY_MMAP)
> - pdst->m.mem_offset = psrc->m.offset;
> - else if (q->memory == VB2_MEMORY_USERPTR)
> - pdst->m.userptr = psrc->m.userptr;
> - else if (q->memory == VB2_MEMORY_DMABUF)
> - pdst->m.fd = psrc->m.fd;
> - pdst->data_offset = psrc->data_offset;
> - memset(pdst->reserved, 0, sizeof(pdst->reserved));
> - }
> - } else {
> - /*
> -  * We use length and offset in v4l2_planes array even for
> -  * single-planar buffers, but userspace does not.
> -  */
> - b->length = vb->planes[0].length;
> - b->bytesused = vb->planes[0].bytesused;
> - if (q->memory == VB2_MEMORY_MMAP)
> - b->m.offset = vb->planes[0].m.offset;
> - else if (q->memory == VB2_MEMORY_USERPTR)
> - b->m.userptr = vb->planes[0].m.userptr;
> - else if (q->memory == VB2_MEMORY_DMABUF)
> - b->m.fd = vb->planes[0].m.fd;
> - }
> -
> - /*
> -  * Clear any buffer state related flags.
> -  */
> - b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
> - b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
> - if (!q->copy_timestamp) {
> - /*
> -  * For non-COPY timestamps, drop timestamp source bits
> -  * and obtain the timestamp source from the queue.
> -  */
> - b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> - b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
> - }
> -
> - switch (vb->state) {
> - case VB2_BUF_STATE_QUEUED:
> - case VB2_BUF_STATE_ACTIVE:
> - b->flags |= V4L2_BUF_F

Re: [PATCHv18 16/35] v4l2-ctrls: add v4l2_ctrl_request_hdl_find/put/ctrl_find functions

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:28 +0200
Hans Verkuil  escreveu:

> 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 
Reviewed-by: Mauro Carvalho Chehab 
> ---
>  drivers/media/v4l2-core/v4l2-ctrls.c | 25 ++
>  include/media/v4l2-ctrls.h   | 49 +++-
>  2 files changed, 73 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
> b/drivers/media/v4l2-core/v4l2-ctrls.c
> index 6d34d7a6f235..a197b60183f5 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, &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 f4156544150b..53ca4df0c353 100644
> --- a/include/media/v4l2-ctrls.h
> +++ b/include/media/v4l2-ctrls.h
> @@ -,7 +,54 @@ 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.
> + *
> + * Note that in state VALIDATING the req_queue_mutex is held, so
> + * no objects can be added or deleted from the request.
> + *
> + * In state QUEUED it is the driver that will have to ensure this.
> + */
> +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(&hdl->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 */
>  



Thanks,
Mauro


Re: [PATCHv18 15/35] v4l2-ctrls: support g/s_ext_ctrls for requests

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:27 +0200
Hans Verkuil  escreveu:

> 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 
Reviewed-by: Mauro Carvalho Chehab 


> ---
>  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 = &ctrl;
>  
> - ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, &ctrls);
> + ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, NULL, &ctrls);
>   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 89e7bfee108f..6d34d7a6f235 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)
> +static int v4l2_g_ext_ctrls_common(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, &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 = &new_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_common(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, struc

Re: [PATCHv18 14/35] v4l2-ctrls: add core request support

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:26 +0200
Hans Verkuil  escreveu:

> 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 
Reviewed-by: Mauro Carvalho Chehab 
> ---
>  drivers/media/v4l2-core/v4l2-ctrls.c | 336 ++-
>  include/media/v4l2-ctrls.h   |  51 
>  2 files changed, 381 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
> b/drivers/media/v4l2-core/v4l2-ctrls.c
> index c20e74ba48ab..89e7bfee108f 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(&hdl->ctrls);
>   INIT_LIST_HEAD(&hdl->ctrl_refs);
> + INIT_LIST_HEAD(&hdl->requests);
> + INIT_LIST_HEAD(&hdl->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(&hdl->requests)) {
> + struct v4l2_ctrl_handler *req, *next_req;
> +
> + list_for_each_entry_safe(req, next_req, &hdl->requests, 
> requests) {
> + media_request_object_unbind(&req->req_obj);
> + media_request_object_put(&req->req_obj);
> + }
> + }
>   mutex_lock(hdl->lock);
>   /* Free all nodes */
>   list_for_each_entry_safe(ref, next_ref, &hdl->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 != &hdl->_lock);
> +
> + mutex_lock(from->lock);
> + list_for_each_entry(ref, &from->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, &new_ref, false, true);
> + if (err)
> + break;
> + }
> + mutex_unlock(from->lo

Re: [PATCHv18 08/35] v4l2-dev: lock req_queue_mutex

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:20 +0200
Hans Verkuil  escreveu:

> 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 

I didn't test this patch series with sparse yet. When merging
on a topic branch, I'll let you know if it applies cleanly.

Anyway:

Reviewed-by: Mauro Carvalho Chehab 

> ---
>  drivers/media/v4l2-core/v4l2-dev.c   | 18 --
>  drivers/media/v4l2-core/v4l2-ioctl.c | 22 +-
>  2 files changed, 37 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c 
> b/drivers/media/v4l2-core/v4l2-dev.c
> index 69e775930fc4..feb74942 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -444,8 +444,22 @@ static int v4l2_release(struct inode *inode, struct file 
> *filp)
>   struct video_device *vdev = video_devdata(filp);
>   int ret = 0;
>  
> - if (vdev->fops->release)
> - ret = vdev->fops->release(filp);
> + /*
> +  * 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 (vdev->fops->release) {
> + if (v4l2_device_supports_requests(vdev->v4l2_dev)) {
> + mutex_lock(&vdev->v4l2_dev->mdev->req_queue_mutex);
> + ret = vdev->fops->release(filp);
> + mutex_unlock(&vdev->v4l2_dev->mdev->req_queue_mutex);
> + } else {
> + ret = vdev->fops->release(filp);
> + }
> + }
> +
>   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, &vfd->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 = &vfd->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;
>  }
>  



Thanks,
Mauro


Re: [PATCHv18 03/35] media-request: implement media requests

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:15 +0200
Hans Verkuil  escreveu:

> 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 

Reviewed-by: Mauro Carvalho Chehab 

> ---
>  drivers/media/Makefile|   3 +-
>  drivers/media/media-device.c  |  24 +-
>  drivers/media/media-request.c | 464 ++
>  include/media/media-device.h  |  29 +++
>  include/media/media-request.h | 334 
>  5 files changed, 849 insertions(+), 5 deletions(-)
>  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..d78e991bce46 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,10 +378,19 @@ static long media_device_get_topology(struct 
> media_device *mdev, void *arg)
>   return ret;
>  }
>  
> +static long media_device_request_alloc(struct media_device *mdev,
> +int *alloc_fd)
> +{
> + if (!mdev->ops || !mdev->ops->req_validate || !mdev->ops->req_queue)
> + return -ENOTTY;
> +
> + return media_request_alloc(mdev, alloc_fd);
> +}
> +
>  static long copy_arg_from_user(void *karg, void __user *uarg, unsigned int 
> cmd)
>  {
> - /* All media IOCTLs are _IOWR() */
> - if (copy_from_user(karg, uarg, _IOC_SIZE(cmd)))
> + if ((_IOC_DIR(cmd) & _IOC_WRITE) &&
> + copy_from_user(karg, uarg, _IOC_SIZE(cmd)))
>   return -EFAULT;
>  
>   return 0;
> @@ -388,8 +398,8 @@ static long copy_arg_from_user(void *karg, void __user 
> *uarg, unsigned int cmd)
>  
>  static long copy_arg_to_user(void __user *uarg, void *karg, unsigned int cmd)
>  {
> - /* All media IOCTLs are _IOWR() */
> - if (copy_to_user(uarg, karg, _IOC_SIZE(cmd)))
> + if ((_IOC_DIR(cmd) & _IOC_READ) &&
> + copy_to_user(uarg, karg, _IOC_SIZE(cmd)))
>   return -EFAULT;
>  
>   return 0;

IMHO, the two above hunks should be there since version 0 :-)

I'm grateful that you remind to change it.

> @@ -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,9 +708,13 @@ void media_device_init(struct media_device *mdev)
>   INIT_LIST_HEAD(&mdev->pads);
>   INIT_LIST_HEAD(&mdev->links);
>   INIT_LIST_HEAD(&mdev->entity_notify);
> +
> + mutex_init(&mdev->req_queue_mutex);
>   mutex_init(&mdev->graph_mutex);
>   ida_init(&mdev->entity_internal_idx);
>  
> + atomic_set(&mdev->request_id, 0);
> +
>   dev_dbg(mdev->dev, "Media device initialized\n");
>  }
>  EXPORT_SYMBOL_GPL(media_device_init);
> @@ -710,6 +725,7 @@ void

Re: [PATCHv18 02/35] uapi/linux/media.h: add request API

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:14 +0200
Hans Verkuil  escreveu:

> 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 

Reviewed-by: Mauro Carvalho Chehab 

> ---
>  include/uapi/linux/media.h | 8 
>  1 file changed, 8 insertions(+)
> 
> diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
> index 36f76e777ef9..e5d0c5c611b5 100644
> --- a/include/uapi/linux/media.h
> +++ b/include/uapi/linux/media.h
> @@ -369,6 +369,14 @@ struct media_v2_topology {
>  #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  _IOR ('|', 0x05, int)
> +
> +/*
> + * 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__
>  



Thanks,
Mauro


Re: [PATCHv18 01/35] Documentation: v4l: document request API

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 16:20:13 +0200
Hans Verkuil  escreveu:

> From: Alexandre Courbot 
> 
> Document the request API for V4L2 devices, and amend the documentation
> of system calls influenced by it.

Looks ok to me. Just a minor nitpick (see below).

Mental note: we'll need to push the no-invariant-sections upstream before
merging this there. 

With that:

Reviewed-by: Mauro Carvalho Chehab 

> 
> 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 |  65 +
>  .../uapi/mediactl/media-request-ioc-queue.rst |  82 ++
>  .../mediactl/media-request-ioc-reinit.rst |  51 
>  .../media/uapi/mediactl/request-api.rst   | 245 ++
>  .../uapi/mediactl/request-func-close.rst  |  48 
>  .../uapi/mediactl/request-func-ioctl.rst  |  67 +
>  .../media/uapi/mediactl/request-func-poll.rst |  77 ++
>  Documentation/media/uapi/v4l/buffer.rst   |  21 +-
>  .../media/uapi/v4l/vidioc-g-ext-ctrls.rst |  53 +++-
>  Documentation/media/uapi/v4l/vidioc-qbuf.rst  |  32 ++-
>  .../media/videodev2.h.rst.exceptions  |   1 +
>  13 files changed, 739 insertions(+), 10 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 ..34434e2b3918
> --- /dev/null
> +++ b/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
> @@ -0,0 +1,65 @@
> +.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH 
> no-invariant-sections
> +
> +.. _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, int *argp )
> +:name: MEDIA_IOC_REQUEST_ALLOC
> +
> +
> +Arguments
> +=
> +
> +``fd``
> +File descriptor returned by :ref:`open() `.
> +
> +``argp``
> +Pointer to an integer.

Nitpick: I would name it as ``request_fd``.

> +
> +
> +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 ``*argp``.
> +
> +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.
> +
> +Return Value
> +
> +
> +On success 0 is returned, on error -1 and the ``errno`` variable is set
> +appropriately. 

Re: [PATCH v2 0/2] media: i2c: ov5640: Re-work MIPI startup sequence

2018-08-14 Thread jacopo mondi
Hi Steve,

On Tue, Aug 14, 2018 at 09:51:04AM -0700, Steve Longerbeam wrote:
> Hi Jacopo,
>
>
> On 08/14/2018 08:35 AM, jacopo mondi wrote:
> >Hi Steve,
> >sorry for resurecting this.
> >
> >
> >>>I'm sorry I'm not sur I'm following. Does this mean that with that bug
> >>>you are referring to up here fixed by my last patch you have capture
> >>>working?
> >>No, capture still not working for me on SabreSD, even after fixing
> >>the bug in 476dec0 "media: ov5640: Add horizontal and vertical totals",
> >>by either using your patchset, or by running version 476dec0 of ov5640.c
> >>with the call to ov5640_set_timings() moved to the correct places as
> >>described below.
> >>
> >I've been reported a bug on exposure handling that makes the first
> >captured frames all black. Both me and Hugues have tried to fix the
> >issue (him with a more complete series, but that's another topic).
> >See [1] and [2]
> >
> >It might be possible that you're getting blank frames with this series
> >applied? I never seen them as I'm skipping the first frames when
> >capturing, but I've now tested and without the exposure fixes (either
> >[1] or [2]) I actually have blank frames.
> >
> >If that's the case for you too (which I hope so much) would you be
> >available to test again this series with exposure fixes on top?
> >On my platform that actually makes all frames correct.
> >
> >Thanks
> >j
> >
> >[1] [PATCH 0/2] media: ov5640: Fix set_timings and auto-exposure
> >[2] [PATCH v2 0/5] Fix OV5640 exposure & gain
> >
>
> It's not clear to me which patch sets you would like me to test.
> Just [1] and [2], or [1], [2], and "media: i2c: ov5640: Re-work MIPI startup
> sequence"?
>
I have tested on my board the following:
v4.18-rc2 + MIPI Fix + Timings + Hugues' exposure fix

Without Hugues' patches I get blank frames (the first ones at least)
Without MIPI startup reowkr and timings I get the LP-11 error on the
CSI-2 bus.

As Hugues' series has to be rebased on mine, I have prepared a branch
here for you if you feel like testing it:
git://jmondi.org/linux ov5640/timings_exposure

Thanks
   j


> Steve
>
>
>


signature.asc
Description: PGP signature


Re: [PATCH v2 0/2] media: i2c: ov5640: Re-work MIPI startup sequence

2018-08-14 Thread Steve Longerbeam

Hi Jacopo,


On 08/14/2018 08:35 AM, jacopo mondi wrote:

Hi Steve,
sorry for resurecting this.



I'm sorry I'm not sur I'm following. Does this mean that with that bug
you are referring to up here fixed by my last patch you have capture
working?

No, capture still not working for me on SabreSD, even after fixing
the bug in 476dec0 "media: ov5640: Add horizontal and vertical totals",
by either using your patchset, or by running version 476dec0 of ov5640.c
with the call to ov5640_set_timings() moved to the correct places as
described below.


I've been reported a bug on exposure handling that makes the first
captured frames all black. Both me and Hugues have tried to fix the
issue (him with a more complete series, but that's another topic).
See [1] and [2]

It might be possible that you're getting blank frames with this series
applied? I never seen them as I'm skipping the first frames when
capturing, but I've now tested and without the exposure fixes (either
[1] or [2]) I actually have blank frames.

If that's the case for you too (which I hope so much) would you be
available to test again this series with exposure fixes on top?
On my platform that actually makes all frames correct.

Thanks
j

[1] [PATCH 0/2] media: ov5640: Fix set_timings and auto-exposure
[2] [PATCH v2 0/5] Fix OV5640 exposure & gain



It's not clear to me which patch sets you would like me to test.
Just [1] and [2], or [1], [2], and "media: i2c: ov5640: Re-work MIPI 
startup sequence"?


Steve





Re: [PATCH v2 2/7] [media] dt-bindings: tvp5150: Add input port connectors DT bindings

2018-08-14 Thread Marco Felsch
On 18-08-13 15:41, Rob Herring wrote:
> On Mon, Aug 13, 2018 at 11:25:03AM +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 
> > 
> > ---
> > Changelog:
> > v2:
> > - adapt port layout in accordance with
> >   https://www.spinics.net/lists/linux-media/msg138546.html with the
> >   svideo-connector deviation (use only one endpoint)
> > ---
> >  .../devicetree/bindings/media/i2c/tvp5150.txt | 191 +-
> >  1 file changed, 185 insertions(+), 6 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt 
> > b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > index 8c0fc1a26bf0..d647d671f14a 100644
> > --- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt
> > @@ -12,11 +12,31 @@ 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 physical 
> > 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
> > + Y-OUT src 2
> > +
> > +The device node must contain at least one sink port and the src port. Each 
> > input
> > +port must be linked to an endpoint defined in
> > +Documentation/devicetree/bindings/display/connector/analog-tv-connector.txt.
> >  The
> > +port/connector layout is as follows
> > +
> > +tvp-5150 port@0 (AIP1A)
> > +   endpoint@0 ---> Comp0-Con  port
> > +   endpoint@1 ---> Svideo-Con port
> > +tvp-5150 port@1 (AIP1B)
> > +   endpoint   ---> Comp1-Con  port
> > +tvp-5150 port@2
> > +   endpoint (video bitstream output at YOUT[0-7] parallel bus)
> > +
> > +Required Endpoint Properties for parallel synchronization on output port:
> >  
> >  - hsync-active: active state of the HSYNC signal. Must be <1> (HIGH).
> >  - vsync-active: active state of the VSYNC signal. Must be <1> (HIGH).
> > @@ -26,7 +46,140 @@ Required Endpoint Properties for parallel 
> > synchronization:
> >  If none of hsync-active, vsync-active and field-even-active is specified,
> >  the endpoint is assumed to use embedded BT.656 synchronization.
> >  
> > -Example:
> > +Examples:
> 
> Is it really necessary to enumerate every possibility? Just show the 
> most complicated case which is a superset of the rest.

I just wanted to be a bit more verbose, since not all users (e.g.
beginners) know how the of_graph works. Anyway, I can drop the 1st and
2nd example.

> 
> > +
> > +One Input:
> > +
> > +connector {
> > +   compatible = "composite-video-connector";
> > +   label = "Composite0";
> > +
> > +   port {
> > +   composite0_to_tvp5150: endpoint {
> > +   remote-endpoint = <&tvp5150_to_composite0>;
> > +   };
> > +   };
> > +};
> > +
> > +&i2c2 {
> > +   ...
> > +   tvp5150@5c {
> > +   compatible = "ti,tvp5150";
> > +   reg = <0x5c>;
> > +   pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>;
> > +   reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
> > +
> > +   port@0 {
> > +   reg = <0>;
> > +
> > +   tvp5150_to_composite0: endpoint {
> > +   remote-endpoint = <&composite0_to_tvp5150>;
> > +   };
> > +   };
> > +
> > +   port@2 {
> > +   reg = <2>;
> > +
> > +   tvp5150_1: endpoint {
> > +   remote-endpoint = <&ccdc_ep>;
> > +   };
> > +   };
> > +   };
> > +};
> > +
> > +Two Inputs:
> > +
> > +comp_connector_1 {
> > +   compatible = "composite-video-connector";
> > +   label = "Composite1";
> > +
> > +   port {
> > +   composite1_to_tvp5150: endpoint {
> > +   remote-endpoint = <&tvp5150_to_composite1>

Re: [PATCH 2/2] media: ov5640: Fix auto-exposure disabling

2018-08-14 Thread jacopo mondi
Hi Hugues,

On Tue, Aug 07, 2018 at 08:53:23AM +, Hugues FRUCHET wrote:
> Hi Jacopo,
>
> In serie "[PATCH 0/5] Fix OV5640 exposure & gain"
> https://www.mail-archive.com/linux-media@vger.kernel.org/msg133269.html
> I've tried to collect fixes around exposure/gain, not only the exposure
> regression and I would prefer to keep it consistent with the associated
> procedure test.

You're right. Please see my other reply, I mixed two different issues
in this series probably.

> Moreover I dislike the internal use of control framework functions to
> disable/enable exposure/gain, on my opinion this has to be kept simpler
> by just disabling/enabling the right registers.

Why that? I thought changing parameters exposed as controls should go
through the control framework to ensure consistency. Maybe I'm wrong.

> Would it be possible that you test my 5 patches serie on your side ?

I did. I re-based the series on top of my MIPI and timings fixes and
it actually solves the exposure issues I didn't know I had :)

I'll comment on v2 as well as soon as I'll get an answer from Steve on
the CSI-2 issue.

Thanks
   j

>
> Best regards,
> Hugues.
>
> On 07/18/2018 03:04 PM, jacopo mondi wrote:
> > Hi again,
> >
> > On Wed, Jul 18, 2018 at 01:19:03PM +0200, Jacopo Mondi wrote:
> >> As of:
> >> commit bf4a4b518c20 ("media: ov5640: Don't force the auto exposure state at
> >> start time") auto-exposure got disabled before programming new capture 
> >> modes to
> >> the sensor. Unfortunately the function used to do that 
> >> (ov5640_set_exposure())
> >> does not enable/disable auto-exposure engine through register 0x3503[0] 
> >> bit, but
> >> programs registers [0x3500 - 0x3502] which represent the desired exposure 
> >> time
> >> when running with manual exposure. As a result, auto-exposure was not 
> >> actually
> >> disabled at all.
> >>
> >> To actually disable auto-exposure, go through the control framework 
> >> instead of
> >> calling ov5640_set_exposure() function directly.
> >>
> >> Also, as auto-gain and auto-exposure are disabled un-conditionally but only
> >> restored to their previous values in ov5640_set_mode_direct() function, 
> >> move
> >> controls restoring so that their value is re-programmed opportunely after
> >> either ov5640_set_mode_direct() or ov5640_set_mode_exposure_calc() have 
> >> been
> >> executed.
> >>
> >> Fixes: bf4a4b518c20 ("media: ov5640: Don't force the auto exposure state 
> >> at start time")
> >> Signed-off-by: Jacopo Mondi 
> >>
> >> ---
> >> Is it worth doing with auto-gain what we're doing with auto-exposure? 
> >> Cache the
> >> value and then re-program it instead of unconditionally disable/enable it?
> >
> > I have missed this patch from Hugues that address almost the same
> > issue
> > https://www.mail-archive.com/linux-media@vger.kernel.org/msg133264.html
> >
> > I feel this new one is simpler, and unless we want to avoid going
> > through the control framework, it is not worth adding new functions to
> > handle auto-exposure as Hugues' patch is doing.
> >
> > Hugues, do you have comments? Feel free to add your sob or rb tags if
> > you like to.
> >
> > Thanks
> > j
> >
> >>
> >> Thanks
> >>j
> >> ---
> >> ---
> >>   drivers/media/i2c/ov5640.c | 29 +
> >>   1 file changed, 13 insertions(+), 16 deletions(-)
> >>
> >> diff --git a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
> >> index 12b3496..bc75cb7 100644
> >> --- a/drivers/media/i2c/ov5640.c
> >> +++ b/drivers/media/i2c/ov5640.c
> >> @@ -1588,25 +1588,13 @@ static int ov5640_set_mode_exposure_calc(struct 
> >> ov5640_dev *sensor,
> >>* change mode directly
> >>*/
> >>   static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
> >> -const struct ov5640_mode_info *mode,
> >> -s32 exposure)
> >> +const struct ov5640_mode_info *mode)
> >>   {
> >> -  int ret;
> >> -
> >>if (!mode->reg_data)
> >>return -EINVAL;
> >>
> >>/* Write capture setting */
> >> -  ret = ov5640_load_regs(sensor, mode);
> >> -  if (ret < 0)
> >> -  return ret;
> >> -
> >> -  /* turn auto gain/exposure back on for direct mode */
> >> -  ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 1);
> >> -  if (ret)
> >> -  return ret;
> >> -
> >> -  return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, exposure);
> >> +  return  ov5640_load_regs(sensor, mode);
> >>   }
> >>
> >>   static int ov5640_set_mode(struct ov5640_dev *sensor,
> >> @@ -1626,7 +1614,7 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
> >>return ret;
> >>
> >>exposure = sensor->ctrls.auto_exp->val;
> >> -  ret = ov5640_set_exposure(sensor, V4L2_EXPOSURE_MANUAL);
> >> +  ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, V4L2_EXPOSURE_MANUAL);
> >>if (ret)
> >>return ret;
> >>
> >> @@ -1642,12 +1630,21 @@ static int ov5640_set_mode(struct ov5640_dev 
> >> *sensor,
> >> *

Re: [PATCH 1/2] media: ov5640: Fix timings setup code

2018-08-14 Thread jacopo mondi
Hi Hugues,
   I'll reply to your v2 series shortly, but let me point out one
thing before.

+steve

On Tue, Aug 07, 2018 at 08:53:53AM +, Hugues FRUCHET wrote:
> Hi Jacopo,
>
> Thanks for this patch, when testing on my side I don't see special
> regression or enhancement with that fix, particularly on image quality
> (exposure, ...),

On imx.6 platforms I need this patch along with the MIPI interface
setup fixes sent here [1] to have capture working.

I messed up a bit, as I've sent the "timings fixes" in two series,
this one I'm replying to and the one I've pasted the link of, even if
those series had two different purposes.

So, this patch in my setup does not fixes an image quality issues, but
instead takes part in solving a problems with MIPI CSI-2 on imx.6
platforms.

I asked Steve Longerbeam to test on his imx.6 platform and he reported
his issues was not fixed and he got blank frames ( I was very
disappointed by the different results we had, but moved on and kept
carrying those patches in my tree, as otherwise MIPI interface failed
to startup).

Now I have asked Steve if he might have blank frames, which might be
an exposure related issue, I never had as I skept the first frames,
which are usually the blank one (you're cc-ed).

I believe too your exposure+gain series should be applied and
should supersed [2/2] of this series, but this timing fix is necessary
for me, and I hope Steve's problem are related to exposure handling
issues your series might fix as it did for me.

> do you have a test procedure that underline the issue ?
> For example on my side when I do 5Mp then QVGA capture, pictures are
> overexposed/greenish:

I do capture with yavta, I usually skept the first 7 frames and then
captured 3. Without exposure fix (my patch or your series) the first
frames are black.

This driver is making our life miserable, isn't it? :)

Thanks
   j

[1] https://www.spinics.net/lists/linux-media/msg137557.html


signature.asc
Description: PGP signature


Re: [PATCH v2 0/2] media: i2c: ov5640: Re-work MIPI startup sequence

2018-08-14 Thread jacopo mondi
Hi Steve,
   sorry for resurecting this.

On Mon, Jul 16, 2018 at 09:26:13AM -0700, Steve Longerbeam wrote:
>
>
> On 07/16/2018 01:29 AM, jacopo mondi wrote:
> >Hi Steve,
> >thanks for keep testing it
> >
> >On Sat, Jul 14, 2018 at 01:02:32PM -0700, Steve Longerbeam wrote:
> >>
> >>On 07/14/2018 12:41 PM, Steve Longerbeam wrote:
> >>>Hi Jacopo,
> >>>
> >>>
> >>>On 07/14/2018 11:57 AM, Steve Longerbeam wrote:
> Hi Jacopo,
> 
> Pardon the late reply, see below.
> 
> On 07/11/2018 12:21 AM, jacopo mondi wrote:
> >Hi Steve,
> >
> >On Tue, Jul 10, 2018 at 02:10:54PM -0700, Steve Longerbeam wrote:
> >>Hi Jacopo,
> >>
> >>Sorry to report my testing on SabreSD has same result
> >>as last time. This series fixes the LP-11 timeout at stream
> >>on but captured images are still blank. I tried the 640x480
> >>mode with UYVY2X8. Here is the pad config:
> >This saddens me :(
> >
> >I'm capturing with the same format and sizes... this shouldn't be the
> >issue
> >
> >Could you confirm this matches what you have in your tree?
> >5dc2c80 media: ov5640: Fix timings setup code
> >b35e757 media: i2c: ov5640: Re-work MIPI startup sequence
> >3c4a737 media: ov5640: fix frame interval enumeration
> >41cb1c7 media: ov5640: adjust xclk_max
> >c3f3ba3 media: ov5640: add support of module orientation
> >ce85705 media: ov5640: add HFLIP/VFLIP controls support
> >8663341 media: ov5640: Program the visible resolution
> >476dec0 media: ov5640: Add horizontal and vertical totals
> >dba13a0 media: ov5640: Change horizontal and vertical resolutions name
> >8f57c2f media: ov5640: Init properly the SCLK dividers
> Yes, I have that commit sequence.
> 
> FWIW, I can verify what Jagan Teki reported earlier, that the driver
> still
> works on the SabreSD platform at:
> 
> dba13a0 media: ov5640: Change horizontal and vertical resolutions name
> 
> and is broken at:
> 
> 476dec0 media: ov5640: Add horizontal and vertical totals
> 
> with LP-11 timeout at the mipi csi-2 receiver:
> 
> [   80.763189] imx6-mipi-csi2: LP-11 timeout, phy_state = 0x0230
> [   80.769599] ipu1_csi1: pipeline start failed with -110
> >>>And I discovered the bug in 476dec0 "media: ov5640: Add horizontal and
> >>>vertical totals". The call to ov5640_set_timings() needs to be moved
> >>>before the
> >>>calls to ov5640_get_vts() and ov5640_get_hts(). But I see you have
> >>>discovered
> >>>that as well, and fixed in the second patch in your series.
> >>>
> >I'm sorry I'm not sur I'm following. Does this mean that with that bug
> >you are referring to up here fixed by my last patch you have capture
> >working?
>
> No, capture still not working for me on SabreSD, even after fixing
> the bug in 476dec0 "media: ov5640: Add horizontal and vertical totals",
> by either using your patchset, or by running version 476dec0 of ov5640.c
> with the call to ov5640_set_timings() moved to the correct places as
> described below.
>

I've been reported a bug on exposure handling that makes the first
captured frames all black. Both me and Hugues have tried to fix the
issue (him with a more complete series, but that's another topic).
See [1] and [2]

It might be possible that you're getting blank frames with this series
applied? I never seen them as I'm skipping the first frames when
capturing, but I've now tested and without the exposure fixes (either
[1] or [2]) I actually have blank frames.

If that's the case for you too (which I hope so much) would you be
available to test again this series with exposure fixes on top?
On my platform that actually makes all frames correct.

Thanks
   j

[1] [PATCH 0/2] media: ov5640: Fix set_timings and auto-exposure
[2] [PATCH v2 0/5] Fix OV5640 exposure & gain

> Steve
>
> >>But strangely, if I revert to 476dec0, and then move the call to
> >>ov5640_set_timings()
> >>to just after ov5640_load_regs() in ov5640_set_mode_exposure_calc() and
> >>ov5640_set_mode_direct(), the LP-11 timeouts are still present. So I can
> >>confirm
> >>this strangeness which you already pointed out below [1].
> >>
> >>
> >>>The version I'm sending here re-introduces some of the timings
> >>>parameters in the
> >>>initial configuration blob (not in the single mode ones), which
> >>>apparently has
> >>>to be at least initially programmed to allow the driver to later
> >>>program them
> >>>singularly in the 'set_timings()' function. Unfortunately I do not
> >>>have a real
> >>>rationale behind this which explains why it has to be done this
> >>>way :(
> >>>
> >>[1] here :)
> >>
> >>Steve
> >>
> >>
>


signature.asc
Description: PGP signature


Re: [PATCH 01/14] staging: media: tegra-vde: Support BSEV clock and reset

2018-08-14 Thread Dmitry Osipenko
On Tuesday, 14 August 2018 18:05:51 MSK Dmitry Osipenko wrote:
> On Tuesday, 14 August 2018 17:21:24 MSK Thierry Reding wrote:
> > On Mon, Aug 13, 2018 at 06:09:46PM +0300, Dmitry Osipenko wrote:
> > > On Monday, 13 August 2018 17:50:14 MSK Thierry Reding wrote:
> > > > From: Thierry Reding 
> > > > 
> > > > The BSEV clock has a separate gate bit and can not be assumed to be
> > > > always enabled. Add explicit handling for the BSEV clock and reset.
> > > > 
> > > > This fixes an issue on Tegra124 where the BSEV clock is not enabled
> > > > by default and therefore accessing the BSEV registers will hang the
> > > > CPU if the BSEV clock is not enabled and the reset not deasserted.
> > > > 
> > > > Signed-off-by: Thierry Reding 
> > > > ---
> > > 
> > > Are you sure that BSEV clock is really needed for T20/30? I've tried
> > > already to disable the clock explicitly and everything kept working,
> > > though I'll try again.
> > 
> > I think you're right that these aren't strictly required for VDE to work
> > on Tegra20 and Tegra30. However, the BSEV clock and reset do exist on
> > those platforms, so I didn't see a reason why they shouldn't be handled
> > uniformly across all generations.
> 
> It's a bit messy to have unsed clock being enabled.
> 
> I guess BSEV clock on T20/30 only enables the AES engine. If the decryption
> engine is integrated with the video decoder, then the clock and reset should
> be requested by the driver, but BSEV should be kept disabled if it's not
> used.

Though even if encryption is not directly integrated with the video decoding, 
then it still makes sense to define the clock and reset in DT without using 
them by the VDE driver since the HW registers space is shared. If somebody 
would like to implement the AES driver, it could be made as a sub-device of 
VDE.




Re: [PATCH 01/14] staging: media: tegra-vde: Support BSEV clock and reset

2018-08-14 Thread Dmitry Osipenko
On Tuesday, 14 August 2018 17:21:24 MSK Thierry Reding wrote:
> On Mon, Aug 13, 2018 at 06:09:46PM +0300, Dmitry Osipenko wrote:
> > On Monday, 13 August 2018 17:50:14 MSK Thierry Reding wrote:
> > > From: Thierry Reding 
> > > 
> > > The BSEV clock has a separate gate bit and can not be assumed to be
> > > always enabled. Add explicit handling for the BSEV clock and reset.
> > > 
> > > This fixes an issue on Tegra124 where the BSEV clock is not enabled
> > > by default and therefore accessing the BSEV registers will hang the
> > > CPU if the BSEV clock is not enabled and the reset not deasserted.
> > > 
> > > Signed-off-by: Thierry Reding 
> > > ---
> > 
> > Are you sure that BSEV clock is really needed for T20/30? I've tried
> > already to disable the clock explicitly and everything kept working,
> > though I'll try again.
> 
> I think you're right that these aren't strictly required for VDE to work
> on Tegra20 and Tegra30. However, the BSEV clock and reset do exist on
> those platforms, so I didn't see a reason why they shouldn't be handled
> uniformly across all generations.

It's a bit messy to have unsed clock being enabled.

I guess BSEV clock on T20/30 only enables the AES engine. If the decryption 
engine is integrated with the video decoder, then the clock and reset should 
be requested by the driver, but BSEV should be kept disabled if it's not used.

If BSEV clock isn't powering anything related to VDE on T20/30, then let's 
make BSEV clock and reset control optional. For the clock we could check 
whether err = -ENOENT and continue, later we may switch to 
devm_clk_get_optional() of the upcoming [0]. For the reset there is 
devm_reset_control_get_optional(). 

Please try to verify by all means that we can omit BSEV on T20/30. If you are 
not sure, then let's make them optional as we can always make them required 
later.

P.S. I'll test and review all the patches during the next days. 

[0] https://lkml.org/lkml/2018/7/18/460




Re: qcom: update firmware file for Venus on SDM845

2018-08-14 Thread Josh Boyer
On Fri, Aug 10, 2018 at 5:44 AM Vikash Garodia  wrote:
>
> hi,
>
> This pull request updates firmware files for Venus h/w codec found on the 
> Qualcomm SDM845 chipset.
>
> The following changes since commit 7b5835fd37630d18ac0c755329172f6a17c1af29:
>
>   linux-firmware: add firmware for mt76x2u (2018-07-30 07:20:31 -0400)
>
> are available in the git repository at:
>
>   https://github.com/vgarodia/venus_firmware_23 master
>
> for you to fetch changes up to 6ae7a5bf57f035aecc7613943528e52ada7e1e03:
>
>   qcom: update venus firmware files for v5.2 (2018-08-10 12:57:47 +0530)
>
> 
> Vikash Garodia (1):
>   qcom: update venus firmware files for v5.2
>
>  WHENCE   |   2 +-
>  qcom/venus-5.2/venus.b00 | Bin 212 -> 212 bytes
>  qcom/venus-5.2/venus.b01 | Bin 6600 -> 6600 bytes
>  qcom/venus-5.2/venus.b02 | Bin 819552 -> 837304 bytes
>  qcom/venus-5.2/venus.b03 | Bin 33536 -> 33640 bytes
>  qcom/venus-5.2/venus.mbn | Bin 865408 -> 883264 bytes
>  qcom/venus-5.2/venus.mdt | Bin 6812 -> 6812 bytes
>  7 files changed, 1 insertion(+), 1 deletion(-)

Pulled and pushed out.  Thanks.

josh


[PATCHv18 16/35] v4l2-ctrls: add v4l2_ctrl_request_hdl_find/put/ctrl_find functions

2018-08-14 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   | 49 +++-
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index 6d34d7a6f235..a197b60183f5 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, &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 f4156544150b..53ca4df0c353 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -,7 +,54 @@ 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.
+ *
+ * Note that in state VALIDATING the req_queue_mutex is held, so
+ * no objects can be added or deleted from the request.
+ *
+ * In state QUEUED it is the driver that will have to ensure this.
+ */
+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(&hdl->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



[PATCHv18 21/35] vb2: drop VB2_BUF_STATE_PREPARED, use bool prepared/synced instead

2018-08-14 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| 10 -
 3 files changed, 44 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(&q->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;
}
 
- 

[PATCHv18 09/35] videodev2.h: add request_fd field to v4l2_ext_controls

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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, &p32->count) ||
put_user(count, &p64->count) ||
assign_in_user(&p64->error_idx, &p32->error_idx) ||
+   assign_in_user(&p64->request_fd, &p32->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, &p64->count) ||
put_user(count, &p32->count) ||
assign_in_user(&p32->error_idx, &p64->error_idx) ||
+   assign_in_user(&p32->request_fd, &p64->request_fd) ||
copy_in_user(p32->reserved, p64->reserved, sizeof(p32->reserved)) ||
get_user(kcontrols, &p64->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



[PATCHv18 13/35] v4l2-ctrls: use ref in helper instead of ctrl

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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 95e60d7ee32b..c20e74ba48ab 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



[PATCHv18 15/35] v4l2-ctrls: support g/s_ext_ctrls for requests

2018-08-14 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 = &ctrl;
 
-   ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, &ctrls);
+   ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, NULL, &ctrls);
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 89e7bfee108f..6d34d7a6f235 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)
+static int v4l2_g_ext_ctrls_common(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, &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 = &new_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_common(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_common(struct v4l2_fh *fh,
+   struct v4l2_ctrl_handler *hdl,
+  

[PATCHv18 27/35] videobuf2-core: add request helper functions

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 .../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 16c9a08192cf..f941bf4bd55f 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 == &vb2_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(&req->lock, flags);
+   list_for_each_entry(obj, &req->objects, list) {
+   if (vb2_request_object_is_buffer(obj)) {
+   has_buffers = true;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(&req->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 957b11c675cb..a9f2a7eae49a 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -1172,4 +1172,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



[PATCHv18 14/35] v4l2-ctrls: add core request support

2018-08-14 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 | 336 ++-
 include/media/v4l2-ctrls.h   |  51 
 2 files changed, 381 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index c20e74ba48ab..89e7bfee108f 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(&hdl->ctrls);
INIT_LIST_HEAD(&hdl->ctrl_refs);
+   INIT_LIST_HEAD(&hdl->requests);
+   INIT_LIST_HEAD(&hdl->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(&hdl->requests)) {
+   struct v4l2_ctrl_handler *req, *next_req;
+
+   list_for_each_entry_safe(req, next_req, &hdl->requests, 
requests) {
+   media_request_object_unbind(&req->req_obj);
+   media_request_object_put(&req->req_obj);
+   }
+   }
mutex_lock(hdl->lock);
/* Free all nodes */
list_for_each_entry_safe(ref, next_ref, &hdl->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 != &hdl->_lock);
+
+   mutex_lock(from->lock);
+   list_for_each_entry(ref, &from->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, &new_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_han

[PATCHv18 31/35] v4l2-mem2mem: add vb2_m2m_request_queue

2018-08-14 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 | 63 ++
 include/media/v4l2-mem2mem.h   |  4 ++
 2 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c 
b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 4de8fa163fd3..d7806db222d8 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -387,7 +387,7 @@ static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx 
*m2m_ctx)
spin_unlock_irqrestore(&m2m_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) {
@@ -478,8 +478,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;
@@ -501,14 +507,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);
 
@@ -952,6 +953,52 @@ 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 objects. Note that buffer objects are at the end of the
+* objects list, after all other object types. Once buffer objects
+* are queued, the driver might delete them immediately (if the driver
+* processes the buffer at once), so we have to use
+* list_for_each_entry_safe() to handle the case where the object we
+* queue is deleted.
+*/
+   list_for_each_entry_safe(obj, obj_safe, &req->objects, list) {
+   struct v4l2_m2m_ctx *m2m_ctx_obj;
+   struct vb2_buffer *vb;
+
+   if (!obj->ops->queue)
+   continue;
+
+   if (vb2_request_object_is_buffer(obj)) {
+   /* 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_remo

[PATCHv18 30/35] videobuf2-v4l2: refuse qbuf if queue uses requests or vv.

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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 364b1fea3826..a70df16d68f1 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



[PATCHv18 08/35] v4l2-dev: lock req_queue_mutex

2018-08-14 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   | 18 --
 drivers/media/v4l2-core/v4l2-ioctl.c | 22 +-
 2 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-dev.c 
b/drivers/media/v4l2-core/v4l2-dev.c
index 69e775930fc4..feb74942 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -444,8 +444,22 @@ static int v4l2_release(struct inode *inode, struct file 
*filp)
struct video_device *vdev = video_devdata(filp);
int ret = 0;
 
-   if (vdev->fops->release)
-   ret = vdev->fops->release(filp);
+   /*
+* 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 (vdev->fops->release) {
+   if (v4l2_device_supports_requests(vdev->v4l2_dev)) {
+   mutex_lock(&vdev->v4l2_dev->mdev->req_queue_mutex);
+   ret = vdev->fops->release(filp);
+   mutex_unlock(&vdev->v4l2_dev->mdev->req_queue_mutex);
+   } else {
+   ret = vdev->fops->release(filp);
+   }
+   }
+
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, &vfd->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 = &vfd->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



[PATCHv18 33/35] vim2m: support requests

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

Add support for requests to vim2m.

Signed-off-by: Hans Verkuil 
Reviewed-by: Mauro Carvalho Chehab 
---
 drivers/media/platform/vim2m.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 6f87ef025ff1..5423f0dd0821 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -379,8 +379,16 @@ 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 any */
+   v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req,
+   &ctx->hdl);
+
device_process(ctx, src_buf, dst_buf);
 
+   /* Complete request controls if any */
+   v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req,
+  &ctx->hdl);
+
/* Run delayed work, which simulates a hardware irq  */
schedule_delayed_work(&dev->work_run, msecs_to_jiffies(ctx->transtime));
 }
@@ -808,12 +816,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,
+  &ctx->hdl);
spin_lock_irqsave(&ctx->dev->irqlock, flags);
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
spin_unlock_irqrestore(&ctx->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, &ctx->hdl);
+}
+
 static const struct vb2_ops vim2m_qops = {
.queue_setup = vim2m_queue_setup,
.buf_prepare = vim2m_buf_prepare,
@@ -822,6 +839,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 +1006,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 +1059,7 @@ static int vim2m_probe(struct platform_device *pdev)
dev->mdev.dev = &pdev->dev;
strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
media_device_init(&dev->mdev);
+   dev->mdev.ops = &m2m_media_ops;
dev->v4l2_dev.mdev = &dev->mdev;
 
ret = v4l2_m2m_register_media_controller(dev->m2m_dev,
-- 
2.18.0



[PATCHv18 12/35] v4l2-ctrls: alloc memory for p_req

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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..95e60d7ee32b 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 size_extra_req = 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)
+   size_extra_req = ctrl->elems * ctrl->elem_size;
+   new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL);
if (!new_ref)
return handler_set_err(hdl, -ENOMEM);
new_ref->ctrl = ctrl;
new_ref->from_other_dev = from_other_dev;
+   if (size_extra_req)
+   new_ref->p_req.p = &new_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



[PATCHv18 23/35] vb2: add init_buffer buffer op

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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 15a14b1e5c0b..2eb24961183e 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -412,6 +412,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 &vb2_buffer initialize the extra data after
+ * struct vb2_buffer.
+ * For V4L2 this is a &struct vb2_v4l2_buffer.
  * @fill_user_buffer:  given a &vb2_buffer fill in the userspace structure.
  * For V4L2 this is a &struct v4l2_buffer.
  * @fill_vb2_buffer:   given a userspace structure, fill in the &vb2_buffer.
@@ -422,6 +425,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



[PATCHv18 32/35] vim2m: use workqueue

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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(&dev->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(&dev->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 = &dev->vfd;
vfd->lock = &dev->dev_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
+   INIT_DELAYED_WORK(&dev->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(&dev->v4l2_dev,
"Device registered as /dev/video%d\n", vfd->num);
 
-   timer_setup(&dev->timer, device_isr, 0);
platform_set_drvdata(pdev, dev);
 
dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
@@ -1083,7 +1079,6 @@ static int vim2m_remove(struct platform_device *pdev)
media_device_cleanup(&dev->mdev);
 #endif
v4l2_m2m_release(dev->m2m_dev);
-   del_timer_sync(&dev->timer);
video_unregister_device(&dev->vfd);
v4l2_device_unregister(&dev->v4l2_dev);
 
-- 
2.18.0



[PATCHv18 17/35] videobuf2-v4l2: move __fill_v4l2_buffer() function

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

Move the __fill_v4l2_buffer() to before the vb2_queue_or_prepare_buf()
function to prepare for the next two patches.

No other changes.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-v4l2.c   | 264 +-
 1 file changed, 132 insertions(+), 132 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 886a2d8d5c6c..408fd7ce9c09 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -154,138 +154,6 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
pr_warn("use the actual size instead.\n");
 }
 
-static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
-   const char *opname)
-{
-   if (b->type != q->type) {
-   dprintk(1, "%s: invalid buffer type\n", opname);
-   return -EINVAL;
-   }
-
-   if (b->index >= q->num_buffers) {
-   dprintk(1, "%s: buffer index out of range\n", opname);
-   return -EINVAL;
-   }
-
-   if (q->bufs[b->index] == NULL) {
-   /* Should never happen */
-   dprintk(1, "%s: buffer is NULL\n", opname);
-   return -EINVAL;
-   }
-
-   if (b->memory != q->memory) {
-   dprintk(1, "%s: invalid memory type\n", opname);
-   return -EINVAL;
-   }
-
-   return __verify_planes_array(q->bufs[b->index], b);
-}
-
-/*
- * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
- * returned to userspace
- */
-static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
-{
-   struct v4l2_buffer *b = pb;
-   struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-   struct vb2_queue *q = vb->vb2_queue;
-   unsigned int plane;
-
-   /* Copy back data such as timestamp, flags, etc. */
-   b->index = vb->index;
-   b->type = vb->type;
-   b->memory = vb->memory;
-   b->bytesused = 0;
-
-   b->flags = vbuf->flags;
-   b->field = vbuf->field;
-   b->timestamp = ns_to_timeval(vb->timestamp);
-   b->timecode = vbuf->timecode;
-   b->sequence = vbuf->sequence;
-   b->reserved2 = 0;
-   b->reserved = 0;
-
-   if (q->is_multiplanar) {
-   /*
-* Fill in plane-related data if userspace provided an array
-* for it. The caller has already verified memory and size.
-*/
-   b->length = vb->num_planes;
-   for (plane = 0; plane < vb->num_planes; ++plane) {
-   struct v4l2_plane *pdst = &b->m.planes[plane];
-   struct vb2_plane *psrc = &vb->planes[plane];
-
-   pdst->bytesused = psrc->bytesused;
-   pdst->length = psrc->length;
-   if (q->memory == VB2_MEMORY_MMAP)
-   pdst->m.mem_offset = psrc->m.offset;
-   else if (q->memory == VB2_MEMORY_USERPTR)
-   pdst->m.userptr = psrc->m.userptr;
-   else if (q->memory == VB2_MEMORY_DMABUF)
-   pdst->m.fd = psrc->m.fd;
-   pdst->data_offset = psrc->data_offset;
-   memset(pdst->reserved, 0, sizeof(pdst->reserved));
-   }
-   } else {
-   /*
-* We use length and offset in v4l2_planes array even for
-* single-planar buffers, but userspace does not.
-*/
-   b->length = vb->planes[0].length;
-   b->bytesused = vb->planes[0].bytesused;
-   if (q->memory == VB2_MEMORY_MMAP)
-   b->m.offset = vb->planes[0].m.offset;
-   else if (q->memory == VB2_MEMORY_USERPTR)
-   b->m.userptr = vb->planes[0].m.userptr;
-   else if (q->memory == VB2_MEMORY_DMABUF)
-   b->m.fd = vb->planes[0].m.fd;
-   }
-
-   /*
-* Clear any buffer state related flags.
-*/
-   b->flags &= ~V4L2_BUFFER_MASK_FLAGS;
-   b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK;
-   if (!q->copy_timestamp) {
-   /*
-* For non-COPY timestamps, drop timestamp source bits
-* and obtain the timestamp source from the queue.
-*/
-   b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-   b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-   }
-
-   switch (vb->state) {
-   case VB2_BUF_STATE_QUEUED:
-   case VB2_BUF_STATE_ACTIVE:
-   b->flags |= V4L2_BUF_FLAG_QUEUED;
-   break;
-   case VB2_BUF_STATE_ERROR:
-   b->flags |= V4L2_BUF_FLAG_ERROR;
-   /* fall through */
-   case VB2_BUF_STATE_DON

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

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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



[PATCHv18 28/35] videobuf2-v4l2: add vb2_request_queue/validate helpers

2018-08-14 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   | 51 +++
 include/media/videobuf2-v4l2.h|  4 ++
 2 files changed, 55 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 9c652afa62ab..364b1fea3826 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -1100,6 +1100,57 @@ void vb2_ops_wait_finish(struct vb2_queue *vq)
 }
 EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
 
+/*
+ * Note that this function is called during validation time and
+ * thus the req_queue_mutex is held to ensure no request objects
+ * can be added or deleted while validating. So there is no need
+ * to protect the objects list.
+ */
+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, &req->objects, list) {
+   if (!obj->ops->prepare)
+   continue;
+
+   ret = obj->ops->prepare(obj);
+   if (ret)
+   break;
+   }
+
+   if (ret) {
+   list_for_each_entry_continue_reverse(obj, &req->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 objects. Note that buffer objects are at the end of the
+* objects list, after all other object types. Once buffer objects
+* are queued, the driver might delete them immediately (if the driver
+* processes the buffer at once), so we have to use
+* list_for_each_entry_safe() to handle the case where the object we
+* queue is deleted.
+*/
+   list_for_each_entry_safe(obj, obj_safe, &req->objects, list)
+   if (obj->ops->queue)
+   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



Re: [PATCH 01/14] staging: media: tegra-vde: Support BSEV clock and reset

2018-08-14 Thread Thierry Reding
On Mon, Aug 13, 2018 at 06:09:46PM +0300, Dmitry Osipenko wrote:
> On Monday, 13 August 2018 17:50:14 MSK Thierry Reding wrote:
> > From: Thierry Reding 
> > 
> > The BSEV clock has a separate gate bit and can not be assumed to be
> > always enabled. Add explicit handling for the BSEV clock and reset.
> > 
> > This fixes an issue on Tegra124 where the BSEV clock is not enabled
> > by default and therefore accessing the BSEV registers will hang the
> > CPU if the BSEV clock is not enabled and the reset not deasserted.
> > 
> > Signed-off-by: Thierry Reding 
> > ---
> 
> Are you sure that BSEV clock is really needed for T20/30? I've tried already 
> to disable the clock explicitly and everything kept working, though I'll try 
> again.

I think you're right that these aren't strictly required for VDE to work
on Tegra20 and Tegra30. However, the BSEV clock and reset do exist on
those platforms, so I didn't see a reason why they shouldn't be handled
uniformly across all generations.

> The device-tree changes should be reflected in the binding documentation.

Indeed, I forgot to update that.

Thierry


signature.asc
Description: PGP signature


[PATCHv18 18/35] videobuf2-v4l2: replace if by switch in __fill_vb2_buffer()

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

Replace 'if' statements by a switch in __fill_vb2_buffer()
in preparation of the next patch.

No other changes.

Signed-off-by: Hans Verkuil 
---
 .../media/common/videobuf2/videobuf2-v4l2.c   | 21 ---
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 408fd7ce9c09..57848ddc584f 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -190,21 +190,25 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
vbuf->sequence = 0;
 
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
-   if (b->memory == VB2_MEMORY_USERPTR) {
+   switch (b->memory) {
+   case VB2_MEMORY_USERPTR:
for (plane = 0; plane < vb->num_planes; ++plane) {
planes[plane].m.userptr =
b->m.planes[plane].m.userptr;
planes[plane].length =
b->m.planes[plane].length;
}
-   }
-   if (b->memory == VB2_MEMORY_DMABUF) {
+   break;
+   case VB2_MEMORY_DMABUF:
for (plane = 0; plane < vb->num_planes; ++plane) {
planes[plane].m.fd =
b->m.planes[plane].m.fd;
planes[plane].length =
b->m.planes[plane].length;
}
+   break;
+   default:
+   break;
}
 
/* Fill in driver-provided information for OUTPUT types */
@@ -255,14 +259,17 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
 * the driver should use the allow_zero_bytesused flag to keep
 * old userspace applications working.
 */
-   if (b->memory == VB2_MEMORY_USERPTR) {
+   switch (b->memory) {
+   case VB2_MEMORY_USERPTR:
planes[0].m.userptr = b->m.userptr;
planes[0].length = b->length;
-   }
-
-   if (b->memory == VB2_MEMORY_DMABUF) {
+   break;
+   case VB2_MEMORY_DMABUF:
planes[0].m.fd = b->m.fd;
planes[0].length = b->length;
+   break;
+   default:
+   break;
}
 
if (V4L2_TYPE_IS_OUTPUT(b->type)) {
-- 
2.18.0



[PATCHv18 20/35] davinci_vpfe: remove bogus vb2->state check

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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, &vpfe_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



[PATCHv18 25/35] videobuf2-core: integrate with media requests

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 .../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..a6f4e9ac77b0 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(&q->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(&vb->req_obj);
+   media_request_object_put(&vb->req_obj);
+   }
+
spin_unlock_irqrestore(&q->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) {
+   

[PATCHv18 06/35] media-request: add media_request_object_find

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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 8d3c7360c8f3..4b0ce8fde7c9 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -342,6 +342,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(&req->lock, flags);
+   list_for_each_entry(obj, &req->objects, list) {
+   if (obj->ops == ops && obj->priv == priv) {
+   media_request_object_get(obj);
+   found = obj;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(&req->lock, flags);
+   return found;
+}
+EXPORT_SYMBOL_GPL(media_request_object_find);
+
 void media_request_object_put(struct media_request_object *obj)
 {
kref_put(&obj->kref, media_request_object_release);
diff --git a/include/media/media-request.h b/include/media/media-request.h
index 1c3e5d804d07..ac02019c1d77 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
  *
@@ -331,6 +351,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



[PATCHv18 10/35] v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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(&dev->hdl, 9);
if (subdev)
-   v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler, 
NULL);
+   v4l2_ctrl_add_handler(&dev->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(&dev->hdl, 2);
if (subdev)
v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler,
- NULL);
+ NULL, true);
break;
default:
v4l2_ctrl_handler_init(&dev->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(&btv->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(&dev->cxhdl, tsport->height == 576);
-   v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->cxhdl.hdl, NULL);
+   v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->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(&dev->cxhdl, 36);
if (err)
goto fail_core;
-   v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL);
+   v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL, false);
 
/* blackbird stuff */
pr_info("cx23416 based mpeg encoder (blackbird reference desi

[PATCHv18 07/35] v4l2-device.h: add v4l2_device_supports_requests() helper

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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



[PATCHv18 19/35] vb2: store userspace data in vb2_v4l2_buffer

2018-08-14 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   | 60 +++
 drivers/media/dvb-core/dvb_vb2.c  |  3 +-
 include/media/videobuf2-core.h|  3 +-
 include/media/videobuf2-v4l2.h|  2 +
 5 files changed, 72 insertions(+), 39 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)
retu

[PATCHv18 03/35] media-request: implement media requests

2018-08-14 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  |  24 +-
 drivers/media/media-request.c | 464 ++
 include/media/media-device.h  |  29 +++
 include/media/media-request.h | 334 
 5 files changed, 849 insertions(+), 5 deletions(-)
 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..d78e991bce46 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,10 +378,19 @@ static long media_device_get_topology(struct media_device 
*mdev, void *arg)
return ret;
 }
 
+static long media_device_request_alloc(struct media_device *mdev,
+  int *alloc_fd)
+{
+   if (!mdev->ops || !mdev->ops->req_validate || !mdev->ops->req_queue)
+   return -ENOTTY;
+
+   return media_request_alloc(mdev, alloc_fd);
+}
+
 static long copy_arg_from_user(void *karg, void __user *uarg, unsigned int cmd)
 {
-   /* All media IOCTLs are _IOWR() */
-   if (copy_from_user(karg, uarg, _IOC_SIZE(cmd)))
+   if ((_IOC_DIR(cmd) & _IOC_WRITE) &&
+   copy_from_user(karg, uarg, _IOC_SIZE(cmd)))
return -EFAULT;
 
return 0;
@@ -388,8 +398,8 @@ static long copy_arg_from_user(void *karg, void __user 
*uarg, unsigned int cmd)
 
 static long copy_arg_to_user(void __user *uarg, void *karg, unsigned int cmd)
 {
-   /* All media IOCTLs are _IOWR() */
-   if (copy_to_user(uarg, karg, _IOC_SIZE(cmd)))
+   if ((_IOC_DIR(cmd) & _IOC_READ) &&
+   copy_to_user(uarg, karg, _IOC_SIZE(cmd)))
return -EFAULT;
 
return 0;
@@ -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,9 +708,13 @@ void media_device_init(struct media_device *mdev)
INIT_LIST_HEAD(&mdev->pads);
INIT_LIST_HEAD(&mdev->links);
INIT_LIST_HEAD(&mdev->entity_notify);
+
+   mutex_init(&mdev->req_queue_mutex);
mutex_init(&mdev->graph_mutex);
ida_init(&mdev->entity_internal_idx);
 
+   atomic_set(&mdev->request_id, 0);
+
dev_dbg(mdev->dev, "Media device initialized\n");
 }
 EXPORT_SYMBOL_GPL(media_device_init);
@@ -710,6 +725,7 @@ void media_device_cleanup(struct media_device *mdev)
mdev->entity_internal_idx_max = 0;
media_graph_walk_cleanup(&mdev->pm_count_walk);
mutex_destroy(&mdev->graph_mutex);
+   mutex_destroy(&mdev->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 ..

[PATCHv18 02/35] uapi/linux/media.h: add request API

2018-08-14 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 | 8 
 1 file changed, 8 insertions(+)

diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index 36f76e777ef9..e5d0c5c611b5 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -369,6 +369,14 @@ struct media_v2_topology {
 #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_IOR ('|', 0x05, int)
+
+/*
+ * 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



[PATCHv18 11/35] v4l2-ctrls: prepare internal structs for request API

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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(&hdl->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 &struct 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 &struct media_request_object, used to link into a
+ * &struct 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



[PATCHv18 34/35] vivid: add mc

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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 = &dev->mdev;
+
+   /* Initialize media device */
+   strlcpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
+   dev->mdev.dev = &pdev->dev;
+   media_device_init(&dev->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 = &dev->mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(&vfd->entity, 1, 
&dev->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 = &dev->mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE;
+   ret = media_entity_pads_init(&vfd->entity, 1, 
&dev->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(&vfd->entity, 1, 
&dev->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(&vfd->entity, 1, 
&dev->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 = &dev->mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(&vfd->entity, 1, 
&dev->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(&dev->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(&dev->mdev);
+#endif
video_unregister_device(&dev->radio_tx_dev);
video_unregister_device(&dev->radio_rx_dev);
video_unregister_device(&dev->sdr_cap_dev);
@@ -1445,6 +1502,10 @@ static int vivid_remove(struct platform_device *pdev)
   

[PATCHv18 29/35] videobuf2-core: add uses_requests/qbuf flags

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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 f941bf4bd55f..2dc3fc935f87 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 a9f2a7eae49a..881f53b38b26 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -472,6 +472,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 &struct 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
@@ -539,6 +545,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



[PATCHv18 35/35] vivid: add request support

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

Add support for requests to vivid.

Signed-off-by: Hans Verkuil 
Reviewed-by: Mauro Carvalho Chehab 
---
 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 = &pdev->dev;
media_device_init(&dev->mdev);
+   dev->mdev.ops = &vivid_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,
+   &dev->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,
+  &dev->ctrl_hdl_vid_cap);
vb2_buffer_done(&vid_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vid_cap buffer %d done\n",
@@ -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,
+   &dev->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,
+  &dev->ctrl_hdl_vbi_cap);
vb2_buffer_done(&vbi_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vbi_cap %d done\n",
@@ -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(&buf->list);
+   v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
+  &dev->ctrl_hdl_vid_cap);
vb2_buffer_done(&buf->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(&buf->list);
+   v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
+  &dev->ctrl_hdl_vbi_cap);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERRO

[PATCHv18 24/35] videobuf2-core: embed media_request_object

2018-08-14 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 2eb24961183e..413b8b2dc485 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



[PATCHv18 22/35] videodev2.h: Add request_fd field to v4l2_buffer

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 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(&buf->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, &p32->memory) ||
put_user(memory, &p64->memory) ||
get_user(length, &p32->length) ||
-   put_user(length, &p64->length))
+   put_user(length, &p64->length) ||
+   get_user(request_fd, &p32->request_fd) ||
+   put_user(request_fd, &p64->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(&p32->timecode, &p64->timecode, sizeof(p64->timecode)) 
||
assign_in_user(&p32->sequence, &p64->sequence) ||
assign_in_user(&p32->reserved2, &p64->reserved2) ||
-   assign_in_user(&p32->reserved, &p64->reserved) ||
+   assign_in_user(&p32->request_fd, &p64->request_fd) ||
get_user(length, &p64->length) ||
put_user(length, &p32->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..9112

[PATCHv18 01/35] Documentation: v4l: document request API

2018-08-14 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 |  65 +
 .../uapi/mediactl/media-request-ioc-queue.rst |  82 ++
 .../mediactl/media-request-ioc-reinit.rst |  51 
 .../media/uapi/mediactl/request-api.rst   | 245 ++
 .../uapi/mediactl/request-func-close.rst  |  48 
 .../uapi/mediactl/request-func-ioctl.rst  |  67 +
 .../media/uapi/mediactl/request-func-poll.rst |  77 ++
 Documentation/media/uapi/v4l/buffer.rst   |  21 +-
 .../media/uapi/v4l/vidioc-g-ext-ctrls.rst |  53 +++-
 Documentation/media/uapi/v4l/vidioc-qbuf.rst  |  32 ++-
 .../media/videodev2.h.rst.exceptions  |   1 +
 13 files changed, 739 insertions(+), 10 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 ..34434e2b3918
--- /dev/null
+++ b/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
@@ -0,0 +1,65 @@
+.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH 
no-invariant-sections
+
+.. _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, int *argp )
+:name: MEDIA_IOC_REQUEST_ALLOC
+
+
+Arguments
+=
+
+``fd``
+File descriptor returned by :ref:`open() `.
+
+``argp``
+Pointer to an integer.
+
+
+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 ``*argp``.
+
+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.
+
+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 
b/Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
new file mode 100644
index ..d4f8119e0643
--- /dev/null
+++ b/Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
@@ -0,0 +1,82 @@
+.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH 
no-invariant-sections
+
+.. _media_request_ioc_queue:
+
+**

[PATCHv18 26/35] videobuf2-v4l2: integrate with media requests

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 .../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 a6f4e9ac77b0..16c9a08192cf 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 *opn

[PATCHv18 00/35] Request API

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

Hi all,

This is version 18 of the Request API series. The intention is that
this will become a topic branch in preparation of merging this for
4.20 together with the cedrus staging driver.

I incorporated Mauro's review comments and a review comment from
Ezequiel in v18.

The main change is that I reverted back to a simple int argument for the
MEDIA_IOC_REQUEST_ALLOC ioctl. Mauro prefers it and I think he is right.
It was what we had originally as well.

Besides all the review comments I also fixed a bug. See:
https://www.mail-archive.com/linux-media@vger.kernel.org/msg134311.html

And sparse warned me about a poll prototype change, so the
media_request_poll() was slightly changed (use of EPOLL* instead of POLL*
and a __poll_t return type).

I also split up the old patch 17/34 into three patches: the first just
moves a function up in the source, the second replaces 'if' statements
with a switch, and the third is the actual patch that does the real
work. There is now much less noise in that patch and it should be much easier
to review.

Finally the RFC debugfs patch has been dropped from this series.

This patch series is also available here:

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

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

To avoid having to do a full review again I made a diff between
v17 and v18 that is much easier to understand. I added it below
the line (note that the removal of the debugfs patch is not included
in this diff, it's not useful).

Regards,

Hans

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

Hans Verkuil (32):
  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
  videobuf2-v4l2: move __fill_v4l2_buffer() function
  videobuf2-v4l2: replace if by switch in __fill_vb2_buffer()
  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

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 |  65 +++
 .../uapi/mediactl/media-request-ioc-queue.rst |  82 +++
 .../mediactl/media-request-ioc-reinit.rst |  51 ++
 .../media/uapi/mediactl/request-api.rst   | 245 
 .../uapi/mediactl/request-func-close.rst  |  48 ++
 .../uapi/mediactl/request-func-ioctl.rst  |  67 +++
 .../media/uapi/mediactl/request-func-poll.rst |  77 +++
 Documentation/media/uapi/v4l/buffer.rst   |  21 +-
 .../media/uapi/v4l/vidioc-g-ext-ctrls.rst |  53 +-
 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   | 508 +++-
 drivers/media/dvb-core/dvb_vb2.c  |   5 +-
 drivers/media/dvb-frontends/rtl2832_sdr.c |   5 +-
 drivers/media/media-device.c  |  24 +-
 drivers/media/media-request.c | 489 
 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/ispvid

[PATCHv18 05/35] media-request: add media_request_get_by_fd

2018-08-14 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 
Reviewed-by: Mauro Carvalho Chehab 
---
 include/media/media-request.h | 24 
 1 file changed, 24 insertions(+)

diff --git a/include/media/media-request.h b/include/media/media-request.h
index 9664ebac5dc4..1c3e5d804d07 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



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

2018-08-14 Thread Hans Verkuil
On 04/08/18 14:44, Hans Verkuil wrote:
> 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
> 



> +static long media_request_ioctl_queue(struct media_request *req)
> +{
> + struct media_device *mdev = req->mdev;
> + enum media_request_state state;
> + unsigned long flags;
> + int ret;
> +
> + dev_dbg(mdev->dev, "request: queue %s\n", req->debug_str);
> +
> + /*
> +  * Ensure the request that is validated will be the one that gets queued
> +  * next by serialising the queueing process. This mutex is also used
> +  * to serialize with canceling a vb2 queue and with setting values such
> +  * as controls in a request.
> +  */
> + mutex_lock(&mdev->req_queue_mutex);
> +
> + media_request_get(req);

Here we get a reference to the request...

> +
> + spin_lock_irqsave(&req->lock, flags);
> + if (req->state == MEDIA_REQUEST_STATE_IDLE)
> + req->state = MEDIA_REQUEST_STATE_VALIDATING;
> + state = req->state;
> + spin_unlock_irqrestore(&req->lock, flags);
> + if (state != MEDIA_REQUEST_STATE_VALIDATING) {
> + dev_dbg(mdev->dev,
> + "request: unable to queue %s, request in state %s\n",
> + req->debug_str, media_request_state_str(state));

...but we didn't put it again in this error path. Thus this request is never
released.

Fixed by adding a media_request_put(req) here.

Found with v4l2-compliance.

> + mutex_unlock(&mdev->req_queue_mutex);
> + return -EBUSY;
> + }
> +
> + ret = mdev->ops->req_validate(req);
> +
> + /*
> +  * If the req_validate was successful, then we mark the state as QUEUED
> +  * and call req_queue. The reason we set the state first is that this
> +  * allows req_queue to unbind or complete the queued objects in case
> +  * they are immediately 'consumed'. State changes from QUEUED to another
> +  * state can only happen if either the driver changes the state or if
> +  * the user cancels the vb2 queue. The driver can only change the state
> +  * after each object is queued through the req_queue op (and note that
> +  * that op cannot fail), so setting the state to QUEUED up front is
> +  * safe.
> +  *
> +  * The other reason for changing the state is if the vb2 queue is
> +  * canceled, and that uses the req_queue_mutex which is still locked
> +  * while req_queue is called, so that's safe as well.
> +  */
> + spin_lock_irqsave(&req->lock, flags);
> + req->state = ret ? MEDIA_REQUEST_STATE_IDLE
> +  : MEDIA_REQUEST_STATE_QUEUED;
> + spin_unlock_irqrestore(&req->lock, flags);
> +
> + if (!ret)
> + mdev->ops->req_queue(req);
> +
> + mutex_unlock(&mdev->req_queue_mutex);
> +
> + if (ret) {
> + dev_dbg(mdev->dev, "request: can't queue %s (%d)\n",
> + req->debug_str, ret);
> + media_request_put(req);
> + }
> +
> + return ret;
> +}

Regards,

Hans


Re: [BUG, RFC] media: Wrong module gets acquired

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 11:35:01 +0300
Sakari Ailus  escreveu:

> Hi Pert,
> 
> On Mon, Aug 13, 2018 at 06:33:12PM +0200, petrcve...@gmail.com wrote:
> > From: Petr Cvek 
> > 
> > When transferring a media sensor driver from the soc_camera I've found
> > the controller module can get removed (which will cause a stack dump
> > because the sensor driver depends on resources from the controller driver). 
> >  
> 
> There may be a kernel oops if a resource used by another driver goes away.
> But the right fix isn't to prevent unloading that module. Instead, one way
> to address the problem would be to have persistent clock objects that would
> not be dependent on the driver that provides them.
> 
> > 
> > When I've tried to remove the driver module of the sensor it said the
> > resource was busy (without a reference name) though is should be
> > possible to remove the sensor driver because it is at the end of
> > the dependency list and not to remove the controller driver.  
> 
> That might be one day possible but it is not today.
> 
> You'll still need to acquire the sensor module as well as it registers a
> media entity as well as a sub-device.

Let put my 2 cents here.

Usually, the same problem of removing modules happen if you just
ask the driver's core to unbind a module (with can be done via
sysfs).

Removing/unbinding a driver that uses media controller should work,
if the unbinding code at the driver (e. g. i2c_driver::remove field)
would delete the media controller entities, and the caller driver
doesn't cache it.

The USB drivers whose exports their topology via the media controller
(like em28xx) supports removing an I2C driver without crashing.

Btw, em28xx is an interesting example, as it has a main driver, several
sub-drivers and several I2C drivers.

There, basically, em28xx loads their sub-drivers, with causes the
sub-drivers to increment their device refcount. The same applies
to the I2C drivers. If one wants to remove em28xx from the memory,
it need to remove first the I2C drivers, then the em28xx-foo
sub-drivers, and finally em28xx itself. 

This use to work pretty well (except when some unbind regression gets
introduced).

I use this a lot when testing usb drivers, as it prevents me to boot
the Kernel every time.

-

It could be harder when it has cross-dependencies with other stuff
that aren't properly mapped (clock, gpio, etc). On such cases, the
best way is to use i2c_driver::suppress_bind_attrs, instead of
hacking the v4l2 core.

I didn't look into details (nor did any tests on this RFC patch),
but whatever is there at the core, it should be allowing unbinding
a module, if they don't use suppress_bind_attrs=true.

> 
> > 
> > I've dig into the called functions and I've found this in
> > drivers/media/v4l2-core/v4l2-device.c:
> > 
> > /*
> >  * The reason to acquire the module here is to avoid unloading
> >  * a module of sub-device which is registered to a media
> >  * device. To make it possible to unload modules for media
> >  * devices that also register sub-devices, do not
> >  * try_module_get() such sub-device owners.
> >  */
> > sd->owner_v4l2_dev = v4l2_dev->dev && v4l2_dev->dev->driver &&
> > sd->owner == v4l2_dev->dev->driver->owner;
> > 
> > if (!sd->owner_v4l2_dev && !try_module_get(sd->owner))
> > return -ENODEV;
> > 
> > It basicaly checks if subdevice (=sensor) is a same module as the media
> > device (=controller) and if they are different it acquires the module.
> > 
> > The acquired module is the one in sd->owner, which is the same module from
> > which the function is called (-> sensor aquires itself). Is this
> > functionality valid (should the subdevice really be unloadable)? When
> > I've patched the module to aquire the controller instead the module, the
> > removal worked as expected (sensor free to go, controller not).
> > 
> > If this is really a bug (= there isn't a sensor which cannot be unloaded 
> > from
> > a controller?) then I send a new patch with reworded commentary.
> > 
> > Signed-off-by: Petr Cvek 
> > ---
> >  drivers/media/v4l2-core/v4l2-device.c | 7 ---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/media/v4l2-core/v4l2-device.c 
> > b/drivers/media/v4l2-core/v4l2-device.c
> > index 3940e55c72f1..1dec61cd560c 100644
> > --- a/drivers/media/v4l2-core/v4l2-device.c
> > +++ b/drivers/media/v4l2-core/v4l2-device.c
> > @@ -173,7 +173,8 @@ int v4l2_device_register_subdev(struct v4l2_device 
> > *v4l2_dev,
> > sd->owner_v4l2_dev = v4l2_dev->dev && v4l2_dev->dev->driver &&
> > sd->owner == v4l2_dev->dev->driver->owner;
> >  
> > -   if (!sd->owner_v4l2_dev && !try_module_get(sd->owner))
> > +   if (!sd->owner_v4l2_dev &&
> > +   !try_module_get(v4l2_dev->dev->driver->owner))
> > return -ENODEV;
> >  
> > sd->v4l2_dev = v4l2_dev;
> > @@ -209,7 +210,7 @@ int v4l2_device_register_subdev(struct v4l2_device 
> > *v4l2_dev,
> 

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

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 14:00:16 +0200
Hans Verkuil  escreveu:

> On 09/08/18 22:03, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:45:00 +0200
> > Hans Verkuil  escreveu:
> >   
> >> 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(&vdev->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(&vdev->v4l2_dev->mdev->req_queue_mutex);
> >> +  
> > 
> > This will very likely generate sparse warnings. See my discussions
> > with that regards with Linus.
> > 
> > The only way to avoid it would be to do something like:
> > 
> > if (v4l2_device_supports_requests(vdev->v4l2_dev)) {
> > mutex_lock(&vdev->v4l2_dev->mdev->req_queue_mutex);
> > if (vdev->fops->release)
> > ret = vdev->fops->release(filp);
> > mutex_unlock(&vdev->v4l2_dev->mdev->req_queue_mutex);
> > } else {
> > if (vdev->fops->release)
> > ret = vdev->fops->release(filp);
> > }  
> 
> I've changed this.
> 
> >   
> >>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, &vfd->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 = &vfd->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;
> >> +  }  
> > 
> > Same applies here.  
> 
> I've kept this. I don't get any sparse warnings for this, but if they appear
> then the only way to fix it is likely to split this function into two,
> one that takes the lock(s) and one unlocked variant that does the actual
> job.
> 
> If we need that, then that's a separate patch on top of this patch series.

Works for me.

Thanks,
Mauro


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

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 11:57:48 +0200
Hans Verkuil  escreveu:

> On 14/08/18 10:46, Mauro Carvalho Chehab wrote:
> > Em Fri, 10 Aug 2018 09:21:59 +0200
> > Hans Verkuil  escreveu:
> >   
> >> On 08/09/2018 07:53 PM, Mauro Carvalho Chehab wrote:  
> >>> Em Sat,  4 Aug 2018 14:44:54 +0200
> >>> Hans Verkuil  escreveu:
> >>> 
>  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)
> > 
> > The definition here is wrong... the fd field is not R/W, it is just R, as no
> > fields inside this struct should be filled by userspace.
> > The right declaration for it would be:
> > 
> > #define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, struct 
> > media_request_alloc)
> > 
> > I do have a strong opinion here: ioctls that just return stuff should use 
> > _IOR.  
> 
> You are right, this should be _IOR.
> 
> >   
> >>>
> >>> Same comment as in patch 1: keep it simpler: just pass a s32 * as the
> >>> argument for this ioctl.
> >>
> >> Same comment as in patch 1: I have no strong opinion, but I want the input 
> >> from others
> >> as well.  
> > 
> > I'm transcribing a comment you wrote on patch 01/34 here, for the sake of
> > keeping everything on a single thread:
> >   
> >> The first version just had a s32 argument, not a struct. The main reason 
> >> for
> >> going back to a struct was indeed to make it easier to add new fields in 
> >> the
> >> future. I don't foresee any, but then, you never do.  
> > 
> > First of all, if we declare it as it should be, e. g.: 
> > 
> > #define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, int) 
> > 
> > If later find the need for some struct:
> > 
> > struct media_request_alloc {
> > __s32 fd;
> > __s32 foo;
> > } __packed;
> > 
> > Assuming that "foo" is a write argument, we'll then have:
> > 
> > #define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, int) 
> > #define MEDIA_IOC_REQUEST_ALLOC_V2  _IOWR('|', 0x05, struct 
> > media_request_alloc)  
> > 
> > The size of the ioctl will also be different, and also the direction.
> > So, the magic number will be different.
> > 
> > The Kernel can easily handle it on both ways, and, as 
> > MEDIA_IOC_REQUEST_ALLOC has only an integer output parameter, 
> > there's no need for compat32 or to keep any old struct.
> > The MEDIA_IOC_REQUEST_ALLOC code handler will still be very simple,
> > and backward compatible comes for free.
> > 
> > If, on the other hand, we declare it as:
> > #define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, struct 
> > media_request_alloc_old)
> > 
> > And then we change it to:
> > #define MEDIA_IOC_REQUEST_ALLOC _IORW('|', 0x05, struct 
> > media_request_alloc_new)
> > 
> > Keeping backward compatible will be painful, and will require efforts for
> > no gain.  
> 
> In the kernel it doesn't matter much, I agree. But applications that have to
> be able to handle both old and new ioctls will have to switch between either
> an fd or a struct. Whereas if we use a struct from the beginning, then the
> only difference between the old and new ioctls are whether or not additional
> fields beyond the first fd field are set.

Well, if we change the API by adding other fields, applications will need
both behaviors anyway, if they want to support multiple kernel versions
and need the newer version behavior, if available.

> As mentioned before, I don't have very strong feelings about this, but I
> do want input from others on this before making this change.

Feel free to wait for other inputs.

> Frankly, I think it is unlikely that we will need more fields beyond just
> th

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

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 11:51:30 +0200
Hans Verkuil  escreveu:

> On 14/08/18 10:48, Mauro Carvalho Chehab wrote:
> > Em Tue, 14 Aug 2018 09:57:27 +0200
> > Hans Verkuil  escreveu:
> >   
> >> On 09/08/18 19:43, Mauro Carvalho Chehab wrote:  
>  diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst 
>  b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
>  index 9e448a4aa3aa..0e415f2551b2 100644
>  --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
>  +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
>  @@ -65,7 +65,7 @@ To enqueue a :ref:`memory mapped ` buffer 
>  applications set the
>   with a pointer to this structure the driver sets the
>   ``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_QUEUED`` flags and clears
>   the ``V4L2_BUF_FLAG_DONE`` flag in the ``flags`` field, or it returns an
>  -EINVAL error code.
>  +``EINVAL`` error code.
> >>>
> >>> Side note: we should likely do a similar replacement on all other places
> >>> inside the media uAPI docs.
> >>> 
>   
>   To enqueue a :ref:`user pointer ` buffer applications set the
>   ``memory`` field to ``V4L2_MEMORY_USERPTR``, the ``m.userptr`` field to
>  @@ -98,6 +98,25 @@ dequeued, until the :ref:`VIDIOC_STREAMOFF 
>  ` or
>   :ref:`VIDIOC_REQBUFS` ioctl is called, or until the
>   device is closed.
>   
>  +The ``request_fd`` field can be used with the ``VIDIOC_QBUF`` ioctl to 
>  specify
> >>>
> >>> Please prefer using :ref: for QBUF too, e. g.: 
> >>>   :ref:`ioctl VIDIOC_QBUF `
> >>
> >> Does this make sense when you are in the QBUF documentation itself? Using 
> >> :ref: will
> >> just link back to the same page.
> >>
> >> We need some guidelines here. I personally don't think this makes sense.  
> > 
> > I'm almost sure we're doing the same on every other place within media 
> > docs.  
> 
> Not in vidioc-qbuf.rst: there you never use :ref: to refer to a QBUF/DQBUF.
> I want to keep this as-is. If we really want to change this, then it should
> be done for all vidioc-*.rst files.
> 
> A quick grep shows that this is very common:
> 
> git grep '``VIDIOC_' Documentation/media/uapi/v4l/vidioc-*
> 
> I honestly think it is silly and even confusing to use a :ref: to the page
> you are already on.
> 
> I keep this as-is since this is consistent with the usage elsewhere in 
> vidioc-qbuuf.rst.
> If we want to change this, then that's something we should do separately from 
> this
> patch.

Ok, let's be consistent with what's already there.

Thanks,
Mauro


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

2018-08-14 Thread Hans Verkuil
On 09/08/18 22:03, Mauro Carvalho Chehab wrote:
> Em Sat,  4 Aug 2018 14:45:00 +0200
> Hans Verkuil  escreveu:
> 
>> 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(&vdev->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(&vdev->v4l2_dev->mdev->req_queue_mutex);
>> +
> 
> This will very likely generate sparse warnings. See my discussions
> with that regards with Linus.
> 
> The only way to avoid it would be to do something like:
> 
>   if (v4l2_device_supports_requests(vdev->v4l2_dev)) {
>   mutex_lock(&vdev->v4l2_dev->mdev->req_queue_mutex);
>   if (vdev->fops->release)
>   ret = vdev->fops->release(filp);
>   mutex_unlock(&vdev->v4l2_dev->mdev->req_queue_mutex);
>   } else {
>   if (vdev->fops->release)
>   ret = vdev->fops->release(filp);
>   }

I've changed this.

> 
>>  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, &vfd->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 = &vfd->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;
>> +}
> 
> Same applies here.

I've kept this. I don't get any sparse warnings for this, but if they appear
then the only way to fix it is likely to split this function into two,
one that takes the lock(s) and one unlocked variant that does the actual
job.

If we need that, then that's a separate patch on top of this patch series.

Regards,

Hans

> 
>>  
>>  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);
> 
> This code looks really weird! are you locking in

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

2018-08-14 Thread Hans Verkuil
On 14/08/18 10:55, Mauro Carvalho Chehab wrote:
> Em Tue, 14 Aug 2018 10:45:57 +0200
> Hans Verkuil  escreveu:
> 
>> On 13/08/18 13:07, Mauro Carvalho Chehab wrote:
>>> Em Sat,  4 Aug 2018 14:45:08 +0200
>>> Hans Verkuil  escreveu:
>>>   
 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, &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;  
>>>
>>> Doesn't those helper functions (including this one) be serialized?  
>>
>> v4l2_ctrl_request_hdl_find() checks the request state to ensure this:
>> it is either VALIDATING (then the req_queue_mutex is locked) or QUEUED
>> and then it is under control of the driver. Of course, in that case the
>> driver should make sure that it doesn't complete the request in the
>> middle of calling this function. If a driver does that, then it is a driver
>> bug.
> 
> Please document it then, as I guess anyone that didn't worked at the
> request API patchset wouldn't guess when the driver needs to take
> the lock themselves.
> 
> From what I'm understanding, the driver needs to take the lock only
> when it is running a code that it is not called from an ioctl.
> right?

Drivers never take req_queue_mutex themselves. If they call this function
when in state QUEUED, then they might need to take a driver-specific mutex
or spinlock that protects against the request being completed by an
interrupt handler.

I very much doubt that this function is ever called when in QUEUED state,
the typical use-case is to call this during validation or when queuing
a validated request. In both cases there is no need to do any locking
since it is guaranteed that no control objects will be added/deleted during
that phase.

I've extended the req_queue documentation in media-device.h with
two extra sentences at the end:

 * @req_queue: Queue a validated request, cannot fail. If something goes
 * wrong when queueing this request then it should be marked
 * as such internally in the driver and any related buffers
 * must eventually return to vb2 with state VB2_BUF_STATE_ERROR.
 * The req_queue_mutex lock is held when this op is called.
 * It is important that vb2 buffer objects are queued last after
 * all other object types are queued: queueing a buffer kickstarts
 * the request processing, so all other objects related to the
 * request (and thus the buffer) must be available to the driver.
 * And once a buffer is queued, then the driver can complete
 * or delete objects from the request before req_queue exits.

This is important information that wasn't documented.

So nobody can add/remove objects from a request while in the req_validate()
callback. And nobody can add/remove objects from a request while in req_queue()
and non-buffer objects are queued.

Only once buffer objects are queued can objects be completed or removed from
the request and you have to be careful about that.

vb2_request_queue() does the right thing there: notice the 
list_for_each_entry_safe()
when iterating over the

Re: [BUG, RFC] media: Wrong module gets acquired

2018-08-14 Thread Petr Cvek
Dne 14.8.2018 v 10:35 Sakari Ailus napsal(a):
> Hi Pert,
> 

Hello,

thanks for answering

> On Mon, Aug 13, 2018 at 06:33:12PM +0200, petrcve...@gmail.com wrote:
>> From: Petr Cvek 
>>
>> When transferring a media sensor driver from the soc_camera I've found
>> the controller module can get removed (which will cause a stack dump
>> because the sensor driver depends on resources from the controller driver).
> 
> There may be a kernel oops if a resource used by another driver goes away.
> But the right fix isn't to prevent unloading that module. Instead, one way
> to address the problem would be to have persistent clock objects that would
> not be dependent on the driver that provides them.
> 

Yeah it is a hack, but it allows me to rmmod the sensor driver.
Otherwise it has a refcount "deadlock" as it holds the refcount on
itself. The _only_ way to unload the driver is to reboot.

ad clocks: Well the sensor driver and the controller are using
v4l2_clk_* so I was poking around that. Anyway the independent clock
object would be a problem, the clock control is inside the capture
driver register set (divider, enable) (I think) and it gets gated out
completely when the capture driver is unloaded. And when the clock is
stopped the sensor isn't responding to i2c commands. The clock control
is really dependent on the driver unless there is some callback to the
sensor which interrupts it from non-responding i2c transfers.

>>
>> When I've tried to remove the driver module of the sensor it said the
>> resource was busy (without a reference name) though is should be
>> possible to remove the sensor driver because it is at the end of
>> the dependency list and not to remove the controller driver.
> 
> That might be one day possible but it is not today.
> 
> You'll still need to acquire the sensor module as well as it registers a
> media entity as well as a sub-device.
> 

The ported sensor driver doesn't contain any media entity code.

best regards,
Petr


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

2018-08-14 Thread Hans Verkuil
On 14/08/18 10:46, Mauro Carvalho Chehab wrote:
> Em Fri, 10 Aug 2018 09:21:59 +0200
> Hans Verkuil  escreveu:
> 
>> On 08/09/2018 07:53 PM, Mauro Carvalho Chehab wrote:
>>> Em Sat,  4 Aug 2018 14:44:54 +0200
>>> Hans Verkuil  escreveu:
>>>   
 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)  
> 
> The definition here is wrong... the fd field is not R/W, it is just R, as no
> fields inside this struct should be filled by userspace.
> The right declaration for it would be:
> 
>   #define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, struct 
> media_request_alloc)
> 
> I do have a strong opinion here: ioctls that just return stuff should use 
> _IOR.

You are right, this should be _IOR.

> 
>>>
>>> Same comment as in patch 1: keep it simpler: just pass a s32 * as the
>>> argument for this ioctl.  
>>
>> Same comment as in patch 1: I have no strong opinion, but I want the input 
>> from others
>> as well.
> 
> I'm transcribing a comment you wrote on patch 01/34 here, for the sake of
> keeping everything on a single thread:
> 
>> The first version just had a s32 argument, not a struct. The main reason for
>> going back to a struct was indeed to make it easier to add new fields in the
>> future. I don't foresee any, but then, you never do.
> 
> First of all, if we declare it as it should be, e. g.: 
> 
> #define MEDIA_IOC_REQUEST_ALLOC   _IOR('|', 0x05, int) 
> 
> If later find the need for some struct:
> 
>   struct media_request_alloc {
>   __s32 fd;
>   __s32 foo;
>   } __packed;
> 
> Assuming that "foo" is a write argument, we'll then have:
> 
>   #define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, int) 
>   #define MEDIA_IOC_REQUEST_ALLOC_V2  _IOWR('|', 0x05, struct 
> media_request_alloc)  
> 
> The size of the ioctl will also be different, and also the direction.
> So, the magic number will be different.
> 
> The Kernel can easily handle it on both ways, and, as 
> MEDIA_IOC_REQUEST_ALLOC has only an integer output parameter, 
> there's no need for compat32 or to keep any old struct.
> The MEDIA_IOC_REQUEST_ALLOC code handler will still be very simple,
> and backward compatible comes for free.
> 
> If, on the other hand, we declare it as:
>   #define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, struct 
> media_request_alloc_old)
> 
> And then we change it to:
>   #define MEDIA_IOC_REQUEST_ALLOC _IORW('|', 0x05, struct 
> media_request_alloc_new)
> 
> Keeping backward compatible will be painful, and will require efforts for
> no gain.

In the kernel it doesn't matter much, I agree. But applications that have to
be able to handle both old and new ioctls will have to switch between either
an fd or a struct. Whereas if we use a struct from the beginning, then the
only difference between the old and new ioctls are whether or not additional
fields beyond the first fd field are set.

As mentioned before, I don't have very strong feelings about this, but I
do want input from others on this before making this change.

Frankly, I think it is unlikely that we will need more fields beyond just
the fd, but I've been wrong about such things before...

Regards,

Hans


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

2018-08-14 Thread Hans Verkuil
On 14/08/18 10:48, Mauro Carvalho Chehab wrote:
> Em Tue, 14 Aug 2018 09:57:27 +0200
> Hans Verkuil  escreveu:
> 
>> On 09/08/18 19:43, Mauro Carvalho Chehab wrote:
 diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst 
 b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
 index 9e448a4aa3aa..0e415f2551b2 100644
 --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
 +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
 @@ -65,7 +65,7 @@ To enqueue a :ref:`memory mapped ` buffer 
 applications set the
  with a pointer to this structure the driver sets the
  ``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_QUEUED`` flags and clears
  the ``V4L2_BUF_FLAG_DONE`` flag in the ``flags`` field, or it returns an
 -EINVAL error code.
 +``EINVAL`` error code.  
>>>
>>> Side note: we should likely do a similar replacement on all other places
>>> inside the media uAPI docs.
>>>   
  
  To enqueue a :ref:`user pointer ` buffer applications set the
  ``memory`` field to ``V4L2_MEMORY_USERPTR``, the ``m.userptr`` field to
 @@ -98,6 +98,25 @@ dequeued, until the :ref:`VIDIOC_STREAMOFF 
 ` or
  :ref:`VIDIOC_REQBUFS` ioctl is called, or until the
  device is closed.
  
 +The ``request_fd`` field can be used with the ``VIDIOC_QBUF`` ioctl to 
 specify  
>>>
>>> Please prefer using :ref: for QBUF too, e. g.: 
>>> :ref:`ioctl VIDIOC_QBUF `  
>>
>> Does this make sense when you are in the QBUF documentation itself? Using 
>> :ref: will
>> just link back to the same page.
>>
>> We need some guidelines here. I personally don't think this makes sense.
> 
> I'm almost sure we're doing the same on every other place within media docs.

Not in vidioc-qbuf.rst: there you never use :ref: to refer to a QBUF/DQBUF.
I want to keep this as-is. If we really want to change this, then it should
be done for all vidioc-*.rst files.

A quick grep shows that this is very common:

git grep '``VIDIOC_' Documentation/media/uapi/v4l/vidioc-*

I honestly think it is silly and even confusing to use a :ref: to the page
you are already on.

I keep this as-is since this is consistent with the usage elsewhere in 
vidioc-qbuuf.rst.
If we want to change this, then that's something we should do separately from 
this
patch.

Regards,

Hans

> 
>>
>> Regards,
>>
>>  Hans
> 
> 
> 
> Thanks,
> Mauro
> 



Re: Using big platform driver as foundation to implement TV driver framework in Linux

2018-08-14 Thread Mauro Carvalho Chehab
Hi Jesse,

Em Mon, 13 Aug 2018 01:32:45 +
Jesse Huang (黃建興)  escreveu:

> Hi Mchehab,
> Hi Linux-Media,
> 
> MTK/MStar try to move TV SOC proprietary driver framework to Linux TV driver.
> 
> But, we also need to share/re-use driver code to non-OS which is a size 
> limitation low cost system.
> 
> Normally, each Linux driver need to control registers directly by it self. 
> For example:
> ===(sample code begin)
> linux-3.18-exynos7270-sandbox.opensw0312.rebase-3d91408\drivers\media\pci\cx25821\cx25821-video.c
> static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type 
> i)
> {
> struct cx25821_channel *chan = video_drvdata(file);
> 
> if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
> return -EINVAL;
> 
> if (chan->streaming_fh && chan->streaming_fh != priv)
> return -EBUSY;
> chan->streaming_fh = priv;
> 
> return videobuf_streamon(&chan->vidq);
> }
> ===(sample code end)
> 
> 
> 
> But, in our concept, we hope to provide an entire proprietary a driver as a 
> “MTK TV platform driver”. Base on this driver to implement Linux standard TV 
> driver.
> If will look like this:
> ===(sample code begin)
> static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type 
> i)
> {
> return mtk_tv_platform->video->streamon();
> }
> 
> The mtk_tv_platform will be register when setup_arch()
> void __init setup_arch(char **cmdline_p)
> {
> return platform_device_register(&mtk_tv_platform);
> }
> ===(sample code end)
> 
> Would this kid of implement method can be accept for Linux upstream/submit 
> driver rule? What kind of framework design guide line/rule we should follow? 
> Would it possible to have some reference for us.
> 
> If this method is possible, we can share a lot of human resource to both 
> maintain for Linux and non-Linux project.

Not sure if I understand what you want to do.

The Linux Kernel is under a GPL version 2 license, meaning that
anyone wanting to do Kernel development should license their work
under those terms.

In other words, If you want to submit a driver to the Linux Kernel, the
needed software to control the hardware should all be upstreamed using
GPL version 2, including all register settings.

In the specific case of image enhancement algorithms, like 3A, we're
currently working on a solution that would allow a third party software
(ideally open source, but it could be a binary code) to run on
userspace, receiving metadata from the hardware via a documented
userspace, and using the standard V4L2 API to adjust the hardware,
after doing some (usually proprietary) processing.

So, if you're willing to contribute under this terms, we can help you.

It could still be possible to share code with other OS, depending on
how you write the driver, but we don't accept any other OS-dependent
code (like #ifdefs inside Linux). What other vendors usually do is
to either encapsulate the other-os dependent part on a different
source file (not submitted to Linux) or to internally have some
sort of process to strip #ifdefs when submitting drivers to Linux.

If otherwise all you want is to have a wrapper driver to run some
proprietary driver, then shipping such solution would likely be a
copyright violation and we can't help you.

Thanks,
Mauro


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

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 10:58:59 +0200
Hans Verkuil  escreveu:

> On 13/08/18 13:30, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:45:11 +0200
> > Hans Verkuil  escreveu:
> >   
> >> 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;  
> > 
> > Shouldn't be prepared cleaned as well on reqbufs?  
> 
> reqbufs calls queue_cancel which will in turn call the buf_finish op and sets
> prepared to false.

Ok. Not sure if I like to have it implicit somewhere.

> 
> >   
> >>}
> >>  
> >>spin_lock_irqsave(&q->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;
> >>}  
> > 
> > Hmm... is this hunk a bug fix? if so, please split into a separate patch
> > and add a c/c stable.  
> 
> No, just a clean up. I hate switch cases that do not end with a 'break'.
> I can leave it our if you prefer.

Ah, this is at the default clause. I don't personally add a break
after default: when it is the last clause. No need for that, and
very unlikely that it would ever cause problems.

Also, as now gcc complains about missing breaks, at the very unlikely
case where someone would add something after the default: clause,
gcc would warn.

So, for my taste, this is overkill.

> 
> >   
> >>  
> >>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)
> >> -

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

2018-08-14 Thread Mauro Carvalho Chehab
Em Fri, 10 Aug 2018 09:32:53 +0200
Hans Verkuil  escreveu:

> On 08/09/2018 09:55 PM, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:44:57 +0200
> > Hans Verkuil  escreveu:
> >   
> >> 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);  
> > 
> > EPERM? I guess ENOTTY would be better.
> > 
> > Any reason why using EPERM?  
> 
> This is called by e.g. VIDIOC_QBUF or VIDIOC_S/G/TRY_EXT_CTRLS where someone
> sets request_fd. Then this function is called to obtain the corresponding
> media_request struct. If requests are not supported, then EPERM is returned.
> 
> Returning ENOTTY would be wrong, since VIDIOC_QBUF etc. are definitely 
> implemented,
> instead they just do not permit the use of requests.
> 
> Let me know if I can add your Reviewed-by after this explanation.

Reviewed-by: Mauro Carvalho Chehab 

> 
> Regards,
> 
>   Hans



Thanks,
Mauro


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

2018-08-14 Thread Hans Verkuil
On 13/08/18 13:30, Mauro Carvalho Chehab wrote:
> Em Sat,  4 Aug 2018 14:45:11 +0200
> Hans Verkuil  escreveu:
> 
>> 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;
> 
> Shouldn't be prepared cleaned as well on reqbufs?

reqbufs calls queue_cancel which will in turn call the buf_finish op and sets
prepared to false.

> 
>>  }
>>  
>>  spin_lock_irqsave(&q->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;
>>  }
> 
> Hmm... is this hunk a bug fix? if so, please split into a separate patch
> and add a c/c stable.

No, just a clean up. I hate switch cases that do not end with a 'break'.
I can leave it our if you prefer.

> 
>>  
>>  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;
>> @@ -

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

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 10:34:47 +0200
Hans Verkuil  escreveu:

> >> +void v4l2_ctrl_request_setup(struct media_request *req,
> >> +   struct v4l2_ctrl_handler *main_hdl)
> >> +{
> >> +  struct media_request_object *obj;
> >> +  struct v4l2_ctrl_handler *hdl;
> >> +  struct v4l2_ctrl_ref *ref;
> >> +
> >> +  if (!req || !main_hdl)
> >> +  return;
> >> +
> >> +  if (WARN_ON(req->state != MEDIA_REQUEST_STATE_QUEUED))
> >> +  return;
> >> +
> >> +  obj = media_request_object_find(req, &req_ops, main_hdl);
> >> +  if (!obj)
> >> +  return;  
> > 
> > Shouldn't the above checks produce an error or print something at
> > the logs?  
> 
> Good question.
> 
> I think not. This situation would occur if the applications makes a request
> with only a buffer but no controls, thus making no changes to the controls in
> this request.
> 
> This is perfectly legal, so nothing needs to be logged here.

Ok, makes sense.

Please add a note at the source code explaining that, as this is
not obvious for a casual code reviewer.


Thanks,
Mauro


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

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 10:45:57 +0200
Hans Verkuil  escreveu:

> On 13/08/18 13:07, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:45:08 +0200
> > Hans Verkuil  escreveu:
> >   
> >> 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, &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;  
> > 
> > Doesn't those helper functions (including this one) be serialized?  
> 
> v4l2_ctrl_request_hdl_find() checks the request state to ensure this:
> it is either VALIDATING (then the req_queue_mutex is locked) or QUEUED
> and then it is under control of the driver. Of course, in that case the
> driver should make sure that it doesn't complete the request in the
> middle of calling this function. If a driver does that, then it is a driver
> bug.

Please document it then, as I guess anyone that didn't worked at the
request API patchset wouldn't guess when the driver needs to take
the lock themselves.

From what I'm understanding, the driver needs to take the lock only
when it is running a code that it is not called from an ioctl.
right?

Thanks,
Mauro


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

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 09:57:27 +0200
Hans Verkuil  escreveu:

> On 09/08/18 19:43, Mauro Carvalho Chehab wrote:
> >> diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst 
> >> b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> >> index 9e448a4aa3aa..0e415f2551b2 100644
> >> --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> >> +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
> >> @@ -65,7 +65,7 @@ To enqueue a :ref:`memory mapped ` buffer 
> >> applications set the
> >>  with a pointer to this structure the driver sets the
> >>  ``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_QUEUED`` flags and clears
> >>  the ``V4L2_BUF_FLAG_DONE`` flag in the ``flags`` field, or it returns an
> >> -EINVAL error code.
> >> +``EINVAL`` error code.  
> > 
> > Side note: we should likely do a similar replacement on all other places
> > inside the media uAPI docs.
> >   
> >>  
> >>  To enqueue a :ref:`user pointer ` buffer applications set the
> >>  ``memory`` field to ``V4L2_MEMORY_USERPTR``, the ``m.userptr`` field to
> >> @@ -98,6 +98,25 @@ dequeued, until the :ref:`VIDIOC_STREAMOFF 
> >> ` or
> >>  :ref:`VIDIOC_REQBUFS` ioctl is called, or until the
> >>  device is closed.
> >>  
> >> +The ``request_fd`` field can be used with the ``VIDIOC_QBUF`` ioctl to 
> >> specify  
> > 
> > Please prefer using :ref: for QBUF too, e. g.: 
> > :ref:`ioctl VIDIOC_QBUF `  
> 
> Does this make sense when you are in the QBUF documentation itself? Using 
> :ref: will
> just link back to the same page.
> 
> We need some guidelines here. I personally don't think this makes sense.

I'm almost sure we're doing the same on every other place within media docs.

> 
> Regards,
> 
>   Hans



Thanks,
Mauro


Re: why does aptina_pll_calculate insist on exact division?

2018-08-14 Thread Sakari Ailus
Hi,

On Tue, Aug 14, 2018 at 10:30:14AM +0300, Laurent Pinchart wrote:
> Hi Helmut,
> 
> (CC'ing Sakari Ailus who is our current PLL expert after spending so much 
> time 
> on the SMIA PLL code)
> 
> On Tuesday, 14 August 2018 09:35:40 EEST Helmut Grohne wrote:
> > Hi,
> > 
> > I tried using the aptina_pll_calculate for a "new" imager and ran into
> > problems. After filling out aptina_pll_limits from the data sheet, I was
> > having a hard time finding a valid pix_clock. Most of the ones I tried
> > are rejected by aptina_pll_calculate for various reasons. In particular,
> > no pix_clock close to pix_clock_max is allowed.

On many systems where such sensors are being used, you generally need to
use known-good link frequencies that have no EMI issues. Therefore the PLL
calculator uses this input, as well as the bits per pixel etc. platform
specific inputs and hardware limits to come up with the pixel rate. At
least for smiapp PLL calculator this is the highest possible rate, taking
the constraints into account.

> 
> How do you mean ? The only place where pix_clock_max is used is in the 
> following code:
> 
> if (pll->pix_clock == 0 || pll->pix_clock > limits->pix_clock_max) {
> dev_err(dev, "pll: invalid pixel clock frequency.\n");
> return -EINVAL;
> }
> 
> aptina_pll_calculate() rejects a request pixel clock value higher than the 
> pixel clock frequency higher limit, which is also given by the caller. That 
> shouldn't happen, it would be a bug in the caller.
> 
> > Why does the calculation method insist on exact division and avoiding
> > fractional numbers?
> 
> I'm not sure what you mean by avoiding fractional numbers. Could you please 
> elaborate ? Please keep in mind that I last touched the code 6 years, so my 
> memory isn't exactly fresh.
> 
> If you mean using floating point operations to calculate PLL parameters, 
> remember that the code runs in the Linux kernel, where floating point isn't 
> allowed. You would thus have to implement the algorithm using fixed-point 
> calculation.
> 
> > I'm using an ext_clock of 50 MHz. This clock is derived from a 33 MHz
> > clock and the 50 MHz is not attained exactly. Rather it ends up being
> > more like 49.76 Hz. This raises the question, what value I should
> > put into ext_clock (or the corresponding device tree property). Should I
> > use the requested frequency or the actual frequency?
> 
> There's no such thing as an exact frequency anyway, as it's a physical value. 
> I'd got for 50 MHz for simplicity.
> 
> > Worse, depending on the precise value of the ext_clock, aptina_pll_calculate
> > may or may not be able to compute pll parameters.
> > 
> > On the other hand, the manufacturer provided configuration tool happily
> > computes pll parameters that result in close, but not exactly, the
> > requested pix_clock. In particular, the pll parameters do not
> > necessarily result in a whole number. It appears to merely approximate
> > the requested frequency.
> 
> aptina_pll_calculate() also approximates the requested frequency, but as it 
> appears from your test, fails in some cases. That's certainly an issue in the 
> code and should be fixed. Feel free to convince the manufacturer to release 
> their PLL parameters computation code under the GPL ;-)
> 
> > Can you explain where the requirement to avoid fractional numbers comes
> > from? Would it be reasonable to use a different algorithm that avoids
> > this requirement?
> 
> Again, please elaborate on what you mean by avoiding fractional numbers. I 
> would certainly be open to a different algorithm (or possibly fixes to the 
> existing code), as long as it fulfills the requirements behind the current 
> implementation. In particular the code should compute the optimum PLL 
> parameters when multiple options are possible, and its complexity should be 
> lower than O(n^2) (ideally O(1), if not possible O(n)).
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 
> 
> 

-- 
Sakari Ailus
e-mail: sakari.ai...@iki.fi


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

2018-08-14 Thread Mauro Carvalho Chehab
Em Fri, 10 Aug 2018 09:21:59 +0200
Hans Verkuil  escreveu:

> On 08/09/2018 07:53 PM, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:44:54 +0200
> > Hans Verkuil  escreveu:
> >   
> >> 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)  

The definition here is wrong... the fd field is not R/W, it is just R, as no
fields inside this struct should be filled by userspace.
The right declaration for it would be:

#define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, struct 
media_request_alloc)

I do have a strong opinion here: ioctls that just return stuff should use _IOR.

> > 
> > Same comment as in patch 1: keep it simpler: just pass a s32 * as the
> > argument for this ioctl.  
> 
> Same comment as in patch 1: I have no strong opinion, but I want the input 
> from others
> as well.

I'm transcribing a comment you wrote on patch 01/34 here, for the sake of
keeping everything on a single thread:

> The first version just had a s32 argument, not a struct. The main reason for
> going back to a struct was indeed to make it easier to add new fields in the
> future. I don't foresee any, but then, you never do.

First of all, if we declare it as it should be, e. g.: 

#define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, int) 

If later find the need for some struct:

struct media_request_alloc {
__s32 fd;
__s32 foo;
} __packed;

Assuming that "foo" is a write argument, we'll then have:

#define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, int) 
#define MEDIA_IOC_REQUEST_ALLOC_V2  _IOWR('|', 0x05, struct 
media_request_alloc)  

The size of the ioctl will also be different, and also the direction.
So, the magic number will be different.

The Kernel can easily handle it on both ways, and, as 
MEDIA_IOC_REQUEST_ALLOC has only an integer output parameter, 
there's no need for compat32 or to keep any old struct.
The MEDIA_IOC_REQUEST_ALLOC code handler will still be very simple,
and backward compatible comes for free.

If, on the other hand, we declare it as:
#define MEDIA_IOC_REQUEST_ALLOC _IOR('|', 0x05, struct 
media_request_alloc_old)

And then we change it to:
#define MEDIA_IOC_REQUEST_ALLOC _IORW('|', 0x05, struct 
media_request_alloc_new)

Keeping backward compatible will be painful, and will require efforts for
no gain.

Thanks,
Mauro


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

2018-08-14 Thread Hans Verkuil
On 13/08/18 13:07, Mauro Carvalho Chehab wrote:
> Em Sat,  4 Aug 2018 14:45:08 +0200
> Hans Verkuil  escreveu:
> 
>> 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, &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;
> 
> Doesn't those helper functions (including this one) be serialized?

v4l2_ctrl_request_hdl_find() checks the request state to ensure this:
it is either VALIDATING (then the req_queue_mutex is locked) or QUEUED
and then it is under control of the driver. Of course, in that case the
driver should make sure that it doesn't complete the request in the
middle of calling this function. If a driver does that, then it is a driver
bug.

Regards,

Hans

> 
>> +}
>> +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(&hdl->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 */
>>  
> 
> 
> 
> Thanks,
> Mauro
> 



Re: why does aptina_pll_calculate insist on exact division?

2018-08-14 Thread Helmut Grohne
Hi,

Thank you for the quick and helpful answer.

On Tue, Aug 14, 2018 at 09:30:14AM +0200, Laurent Pinchart wrote:
> How do you mean ? The only place where pix_clock_max is used is in the 
> following code:
> 
> if (pll->pix_clock == 0 || pll->pix_clock > limits->pix_clock_max) {
> dev_err(dev, "pll: invalid pixel clock frequency.\n");
> return -EINVAL;
> }
> 
> aptina_pll_calculate() rejects a request pixel clock value higher than the 
> pixel clock frequency higher limit, which is also given by the caller. That 
> shouldn't happen, it would be a bug in the caller.

Of course, I am trying values lower than pix_clock_max. For a number of
imagers, that pix_clock_max is 74.25 MHz. It seems that any pix_clock of
at least 72 MHz is rejected here.

> I'm not sure what you mean by avoiding fractional numbers. Could you please 
> elaborate ? Please keep in mind that I last touched the code 6 years, so my 
> memory isn't exactly fresh.

The first thing the code does is computing the gcd of pix_clock and
ext_clock. Immediately, it conludes that m must be a multiple of
pix_clock / gcd(pix_clock, ext_clock). Varying either clock value
slightly causes large jumps in the computed gcd value (in particular, it
will be 1 whenever either clock happens to be a prime number).

> If you mean using floating point operations to calculate PLL parameters, 
> remember that the code runs in the Linux kernel, where floating point isn't 
> allowed. You would thus have to implement the algorithm using fixed-point 
> calculation.

I'm not after using floating points. In a sense, we are already
fixed-point calculation and the precision is 1 Hz. Rounding errors in
that range look ok to me.

> There's no such thing as an exact frequency anyway, as it's a physical value. 
> I'd got for 50 MHz for simplicity.

That's exactly my point. The exact value should not matter. However, for
the present aptina_pll_calculate, the exact value matters a lot. Were
you to use 4991 Hz as ext_clock (which happens to be prime, but
reasonably close), aptina_pll_calculate fails entirely as m is deemed to
be a multiple of the pix_clock in Hz. No imager allows for such large m
values and thus aptina_pll_calculate rejects any such configuration with
-EINVAL.

I'm arguing that rather than failing to compute pll parameters, it
should compromise on exactness. Presently, aptina_pll_calculate ensures
that whenever it is successful, the assertion pix_clock = ext_clock / n
* m / p1 holds exactly and all intermediate values are whole numbers.
I'm arguing that having it hold exactly reduces utility of
aptina_pll_calculate, because frequencies are not exact in the real
world. There is no need to have whole numbered frequencies.

> aptina_pll_calculate() also approximates the requested frequency, but as it 
> appears from your test, fails in some cases. That's certainly an issue in the 
> code and should be fixed. Feel free to convince the manufacturer to release 
> their PLL parameters computation code under the GPL ;-)

We both know that the exercise of extracting code from manufacturers is
futile.

However you appear to imply that aptina_pll_calculate should approximate
the requested frequency. That's not what it does today. That's a useful
answer to me already and I'll be looking into doing the work of coming
up with an alternative lifting the requirement.

> Again, please elaborate on what you mean by avoiding fractional numbers. I 
> would certainly be open to a different algorithm (or possibly fixes to the 
> existing code), as long as it fulfills the requirements behind the current 
> implementation. In particular the code should compute the optimum PLL 
> parameters when multiple options are possible, and its complexity should be 
> lower than O(n^2) (ideally O(1), if not possible O(n)).

Beware though that discussing complexities requires more precision as to
what "n" means here. The code interprets it as n = p1_max - p1_min (not
accounting for the gcd computation), which is not the usual
interpretation. What you really want is that it completes in a
reasonable amount of time on slow, embedded devices for any input.

Once you lift the exactness requirement, you optimize multiple aspects
simultaneously. The present code maximizes P1, but we also want to
minimize the difference between the requested pix_clock and the
resulting pix_clock. There has to be some kind of trade-off here. The
trade-off chosen by the present code is to always have that difference
be 0. Once non-zero differences are allowed, optimum is no longer
well-defined.

So could you go into more detail as to what "optimum PLL parameters"
mean to you?

Helmut


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

2018-08-14 Thread Hans Verkuil
On 13/08/18 12:55, Mauro Carvalho Chehab wrote:
> Em Sat,  4 Aug 2018 14:45:06 +0200
> Hans Verkuil  escreveu:
> 
>> 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(&hdl->ctrls);
>>  INIT_LIST_HEAD(&hdl->ctrl_refs);
>> +INIT_LIST_HEAD(&hdl->requests);
>> +INIT_LIST_HEAD(&hdl->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(&hdl->requests)) {
>> +struct v4l2_ctrl_handler *req, *next_req;
>> +
>> +list_for_each_entry_safe(req, next_req, &hdl->requests, 
>> requests) {
>> +media_request_object_unbind(&req->req_obj);
>> +media_request_object_put(&req->req_obj);
> 
> Hmm... while this would work for the trivial case where object_put()
> would just drop the object from the list if nobody else is using it,
> nothing prevents that, if v4l2_ctrl_handler_free() is called twice,
> it would do the wrong thing... as the only test here is if req_obj.reg 
> is not NULL, and not if the control framework is already done with the
> object.

v4l2_ctrl_handler_free sets hdl->buckets to NULL when done. And if it is
called twice it will detect that hdl->buckets == NULL and return.

So this isn't an issue.

> 
>> +}
>> +}
>>  mutex_lock(hdl->lock);
>>  /* Free all nodes */
>>  list_for_each_entry_safe(ref, next_ref, &hdl->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 != &hdl->_lock);
>>

Re: [BUG, RFC] media: Wrong module gets acquired

2018-08-14 Thread Sakari Ailus
Hi Pert,

On Mon, Aug 13, 2018 at 06:33:12PM +0200, petrcve...@gmail.com wrote:
> From: Petr Cvek 
> 
> When transferring a media sensor driver from the soc_camera I've found
> the controller module can get removed (which will cause a stack dump
> because the sensor driver depends on resources from the controller driver).

There may be a kernel oops if a resource used by another driver goes away.
But the right fix isn't to prevent unloading that module. Instead, one way
to address the problem would be to have persistent clock objects that would
not be dependent on the driver that provides them.

> 
> When I've tried to remove the driver module of the sensor it said the
> resource was busy (without a reference name) though is should be
> possible to remove the sensor driver because it is at the end of
> the dependency list and not to remove the controller driver.

That might be one day possible but it is not today.

You'll still need to acquire the sensor module as well as it registers a
media entity as well as a sub-device.

> 
> I've dig into the called functions and I've found this in
> drivers/media/v4l2-core/v4l2-device.c:
> 
>   /*
>* The reason to acquire the module here is to avoid unloading
>* a module of sub-device which is registered to a media
>* device. To make it possible to unload modules for media
>* devices that also register sub-devices, do not
>* try_module_get() such sub-device owners.
>*/
>   sd->owner_v4l2_dev = v4l2_dev->dev && v4l2_dev->dev->driver &&
>   sd->owner == v4l2_dev->dev->driver->owner;
> 
>   if (!sd->owner_v4l2_dev && !try_module_get(sd->owner))
>   return -ENODEV;
> 
> It basicaly checks if subdevice (=sensor) is a same module as the media
> device (=controller) and if they are different it acquires the module.
> 
> The acquired module is the one in sd->owner, which is the same module from
> which the function is called (-> sensor aquires itself). Is this
> functionality valid (should the subdevice really be unloadable)? When
> I've patched the module to aquire the controller instead the module, the
> removal worked as expected (sensor free to go, controller not).
> 
> If this is really a bug (= there isn't a sensor which cannot be unloaded from
> a controller?) then I send a new patch with reworded commentary.
> 
> Signed-off-by: Petr Cvek 
> ---
>  drivers/media/v4l2-core/v4l2-device.c | 7 ---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-device.c 
> b/drivers/media/v4l2-core/v4l2-device.c
> index 3940e55c72f1..1dec61cd560c 100644
> --- a/drivers/media/v4l2-core/v4l2-device.c
> +++ b/drivers/media/v4l2-core/v4l2-device.c
> @@ -173,7 +173,8 @@ int v4l2_device_register_subdev(struct v4l2_device 
> *v4l2_dev,
>   sd->owner_v4l2_dev = v4l2_dev->dev && v4l2_dev->dev->driver &&
>   sd->owner == v4l2_dev->dev->driver->owner;
>  
> - if (!sd->owner_v4l2_dev && !try_module_get(sd->owner))
> + if (!sd->owner_v4l2_dev &&
> + !try_module_get(v4l2_dev->dev->driver->owner))
>   return -ENODEV;
>  
>   sd->v4l2_dev = v4l2_dev;
> @@ -209,7 +210,7 @@ int v4l2_device_register_subdev(struct v4l2_device 
> *v4l2_dev,
>  #endif
>  error_module:
>   if (!sd->owner_v4l2_dev)
> - module_put(sd->owner);
> + module_put(v4l2_dev->dev->driver->owner);
>   sd->v4l2_dev = NULL;
>   return err;
>  }
> @@ -318,6 +319,6 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
>  #endif
>   video_unregister_device(sd->devnode);
>   if (!sd->owner_v4l2_dev)
> - module_put(sd->owner);
> + module_put(v4l2_dev->dev->driver->owner);
>  }
>  EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
> -- 
> 2.18.0
> 

-- 
Sakari Ailus
sakari.ai...@linux.intel.com


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

2018-08-14 Thread Mauro Carvalho Chehab
Em Fri, 10 Aug 2018 09:20:48 +0200
Hans Verkuil  escreveu:

> On 08/09/2018 07:43 PM, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:44:53 +0200
> > Hans Verkuil  escreveu:
> >   
> >> From: Alexandre Courbot 
> >>
> >> Document the request API for V4L2 devices, and amend the documentation
> >> of system calls influenced by it.  
> > 
> > It follows some comments. Most are nitpicks. There are just two ones
> > that aren't:
> > - a problem at the tables changes on Documentation/
> > - a question with regards to MEDIA_IOC_REQUEST_ALLOC ioctl.  
> 
> I'll fix all the smaller comments and in this reply only address these
> two topics.
> 
> > 
> > I'll keep reviewing this patch series.
> > 
> > PS.: I lost entirely my first review to this doc... I hope I didn't
> > forget anything when re-typing my comments.
> >   
> >>
> >> 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
> >>  
> 
> 
> 
> >> +.. 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.  
> > 
> > It should be mentioned that the struct should be zeroed before calling
> > the Kernel, but I is overkill to have a struct to pass just one value.
> > 
> > I mean, if this has just one value inside the struct, it is a way better
> > to declare it as:
> > 
> > .. c:function:: int ioctl( int fd, MEDIA_IOC_REQUEST_ALLOC, s32 &argp )
> > 
> > Even if we later need more stuff, the size of a new MEDIA_IOC_REQUEST_ALLOC
> > will be bigger, and then (and only then) we can add extra stuff.
> > 
> > Or are you foreseen any new fields there in short term?  
> 
> The first version just had a s32 argument, not a struct. The main reason for
> going back to a struct was indeed to make it easier to add new fields in the
> future. I don't foresee any, but then, you never do.
> 
> I don't have a particularly strong opinion on this one way or another, but
> if we change it back to a s32 argument, then I want the opinion of others as
> well.

I'll comment it on patch 02/34.

> 
> 
> 
> >> @@ -110,15 +130,13 @@ still cause this situation.
> >>  .. flat-table:: struct v4l2_ext_control
> >>  :header-rows:  0
> >>  :stub-columns: 0
> >> -:widths:   1 1 1 2
> >> +:widths:   1 1 3  
> > 
> > This is wrong: you can't change widths without changing the preceeding
> > .. tabularcolumns tag.
> > 
> > You probably didn't test PDF generation for this table.
> > 
> > Also, the change is this table doesn't belong to this patch. It is
> > a (doubtful) optimization at the table, not related to requests API.
> >   
> >>  
> >>  * - __u32
> >>- ``id``
> >> -  -
> >>- Identifies the control, set by the application.
> >>  * - __u32
> >>- ``size``
> >> -  -
> >>- The total size in bytes of the payload of this control. This is
> >>normally 0, but for pointer controls this should be set to the
> >>size of the memory containing the payload, or that will receive
> >> @@ -135,51 +153,43 @@ still cause this situation.
> >>   *length* of the string may well be much smaller.
> >>  * - __u32
> >>- ``reserved2``\ [1]
> >> -  -
> >>- Reserved for future extensions. Drivers and applications must set
> >>

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

2018-08-14 Thread Mauro Carvalho Chehab
Em Fri, 10 Aug 2018 09:39:20 +0200
Hans Verkuil  escreveu:

> On 08/09/2018 10:03 PM, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:45:00 +0200
> > Hans Verkuil  escreveu:
> >   
> >> 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(&vdev->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(&vdev->v4l2_dev->mdev->req_queue_mutex);
> >> +  
> > 
> > This will very likely generate sparse warnings. See my discussions
> > with that regards with Linus.
> > 
> > The only way to avoid it would be to do something like:
> > 
> > if (v4l2_device_supports_requests(vdev->v4l2_dev)) {
> > mutex_lock(&vdev->v4l2_dev->mdev->req_queue_mutex);
> > if (vdev->fops->release)
> > ret = vdev->fops->release(filp);
> > mutex_unlock(&vdev->v4l2_dev->mdev->req_queue_mutex);
> > } else {
> > if (vdev->fops->release)
> > ret = vdev->fops->release(filp);
> > }  
> 
> I'll check what sparse says and make this change if needed (I hate
> working around sparse warnings).

For reference, see the discussions I had with Linus and Christopher
about this at sparse ML:
https://www.spinics.net/lists/linux-sparse/msg08069.html

In particular, see this:
https://www.spinics.net/lists/linux-sparse/msg08071.html


(I thought I had c/c media, but it seems that only sparse ML was
c/c).

> 
> >   
> >>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, &vfd->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 = &vfd->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;
> >> +  }  
> > 
> > Same applies here.  
> 
> I'm not sure there is much that can be done here without ma

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

2018-08-14 Thread Hans Verkuil
On 09/08/18 19:43, Mauro Carvalho Chehab wrote:
>> diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst 
>> b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
>> index 9e448a4aa3aa..0e415f2551b2 100644
>> --- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
>> +++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
>> @@ -65,7 +65,7 @@ To enqueue a :ref:`memory mapped ` buffer 
>> applications set the
>>  with a pointer to this structure the driver sets the
>>  ``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_QUEUED`` flags and clears
>>  the ``V4L2_BUF_FLAG_DONE`` flag in the ``flags`` field, or it returns an
>> -EINVAL error code.
>> +``EINVAL`` error code.
> 
> Side note: we should likely do a similar replacement on all other places
> inside the media uAPI docs.
> 
>>  
>>  To enqueue a :ref:`user pointer ` buffer applications set the
>>  ``memory`` field to ``V4L2_MEMORY_USERPTR``, the ``m.userptr`` field to
>> @@ -98,6 +98,25 @@ dequeued, until the :ref:`VIDIOC_STREAMOFF 
>> ` or
>>  :ref:`VIDIOC_REQBUFS` ioctl is called, or until the
>>  device is closed.
>>  
>> +The ``request_fd`` field can be used with the ``VIDIOC_QBUF`` ioctl to 
>> specify
> 
> Please prefer using :ref: for QBUF too, e. g.: 
>   :ref:`ioctl VIDIOC_QBUF `

Does this make sense when you are in the QBUF documentation itself? Using :ref: 
will
just link back to the same page.

We need some guidelines here. I personally don't think this makes sense.

Regards,

Hans


[PATCH] cec-func-poll.rst/func-poll.rst: update EINVAL description

2018-08-14 Thread Hans Verkuil
nfds depends on RLIMIT_NOFILE, not OPEN_MAX. Update the description
for cec and v4l2.

Signed-off-by: Hans Verkuil 
---
diff --git a/Documentation/media/uapi/cec/cec-func-poll.rst 
b/Documentation/media/uapi/cec/cec-func-poll.rst
index d49f1ee0742d..c698c969635c 100644
--- a/Documentation/media/uapi/cec/cec-func-poll.rst
+++ b/Documentation/media/uapi/cec/cec-func-poll.rst
@@ -74,4 +74,5 @@ is returned, and the ``errno`` variable is set appropriately:
 The call was interrupted by a signal.

 ``EINVAL``
-The ``nfds`` argument is greater than ``OPEN_MAX``.
+The ``nfds`` value exceeds the ``RLIMIT_NOFILE`` value. Use
+``getrlimit()`` to obtain this value.
diff --git a/Documentation/media/uapi/v4l/func-poll.rst 
b/Documentation/media/uapi/v4l/func-poll.rst
index 360bc6523ae2..967fe8920729 100644
--- a/Documentation/media/uapi/v4l/func-poll.rst
+++ b/Documentation/media/uapi/v4l/func-poll.rst
@@ -113,4 +113,5 @@ EINTR
 The call was interrupted by a signal.

 EINVAL
-The ``nfds`` argument is greater than ``OPEN_MAX``.
+The ``nfds`` value exceeds the ``RLIMIT_NOFILE`` value. Use
+``getrlimit()`` to obtain this value.


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

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 09:19:08 +0200
Hans Verkuil  escreveu:

> On 13/08/18 16:53, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:45:18 +0200
> > Hans Verkuil  escreveu:
> >   
> >> 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;  
> > 
> > This holds the spinlock...  
> 
> The spinlock in vb2_request_has_buffers() is not needed if 
> vb2_request_has_buffers()
> is called from this validate function. While validating no new objects can be
> added to the request, and since nothing has been queued yet objects cannot be
> deleted either. That's true for this whole vb2_request_validate() function.
> 
> But should vb2_request_has_buffers() ever be called from a non-validate 
> context,
> then the spinlock would be needed.
> 
> I want to keep the spinlock in that function for now as it is more robust.

Now your comment to patch 25/34 makes sense, but please document it, as
it is confusing for anyone reviewing the code.

> 
> Regards,
> 
>   Hans
> 
> >   
> >> +
> >> +  list_for_each_entry(obj, &req->objects, list) {
> >> +  if (!obj->ops->prepare)
> >> +  continue;
> >> +
> >> +  ret = obj->ops->prepare(obj);
> >> +  if (ret)
> >> +  break;
> >> +  }
> >> +  
> > 
> > Shouldn't this logic hold it too?
> >   
> >> +  if (ret) {
> >> +  list_for_each_entry_continue_reverse(obj, &req->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, &req->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, &req->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 */  
> > 
> > 
> > 
> > Thanks,
> > Mauro
> >   
> 



Thanks,
Mauro


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

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 09:33:16 +0200
Hans Verkuil  escreveu:

> On 13/08/18 17:15, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:45:26 +0200
> > Hans Verkuil  escreveu:
> >   
> >> 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.

Ok. So, let's skip it on your next patchset. Debugfs can
be added any time after the requests API main patchset gets merged.

> >>
> >> 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  
> > 
> > Patch itself looks good. Yet, perhaps we could request both
> > CONFIG_DEBUG_FS and CONFIG_VIDEO_ADV_DEBUG.
> > 
> > Also, instead of ifdef, please use IS_ENABLED for DEBUG_FS. That tends
> > to be safer long term.
> > 
> > With that:
> > 
> > Reviewed-by: Mauro Carvalho Chehab   
> 
> I don't intend to merge this patch yet. I'm not happy with it: I would
> really like to count the objects per-request instead of globally, and
> provide some more information about requests and their objects.
> 
> It was really a quick hack so that I could verify that all requests and
> objects are properly freed.
> 
> Regards,
> 
>   Hans
> 
> >   
> >> +/*
> >> + * 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(&dev->num_requests));
> >> +  seq_printf(file, "number of request objects: %d\n",
> >> + atomic_read(&dev->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(&mdev->graph_mutex);
> >>ida_init(&mdev->entity_internal_idx);
> >>  
> >> +  atomic_set(&mdev->num_requests, 0);
> >> +  atomic_set(&mdev->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(&devnode->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(&devnode->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(&mdev->devnode->dev, &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)
> >>  {

Re: [PATCHv17 30/34] vim2m: use workqueue

2018-08-14 Thread Mauro Carvalho Chehab
Em Tue, 14 Aug 2018 09:28:42 +0200
Hans Verkuil  escreveu:

> On 13/08/18 17:05, Mauro Carvalho Chehab wrote:
> > Em Sat,  4 Aug 2018 14:45:22 +0200
> > Hans Verkuil  escreveu:
> >   
> >> 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   
> > 
> > Reviewed-by: Mauro Carvalho Chehab 
> > 
> > Shouldn't this come earlier at the series (before adding request API
> > support to m2m) in order to avoid regressions?  
> 
> ??? At this stage vim2m doesn't support the request API yet. It's the next
> patch that adds that (and that's when this patch is needed for it to work).

Ah, OK!
> 
> Regards,
> 
>   Hans
> 
> >   
> >> ---
> >>  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(&dev->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(&dev->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 = &dev->vfd;
> >>vfd->lock = &dev->dev_mutex;
> >>vfd->v4l2_dev = &dev->v4l2_dev;
> >> +  INIT_DELAYED_WORK(&dev->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(&dev->v4l2_dev,
> >>"Device registered as /dev/video%d\n", vfd->num);
> >>  
> >> -  timer_setup(&dev->timer, device_isr, 0);
> >>platform_set_drvdata(pdev, dev);
> >>  
> >>dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
> >> @@ -1083,7 +1079,6 @@ static int vim2m_remove(struct platform_device *pdev)
> >>media_device_cleanup(&dev->mdev);
> >>  #endif
> >>v4l2_m2m_release(dev->m2m_dev);
> >> -  del_timer_sync(&dev->timer);
> >>video_unregister_device(&dev->vfd);
> >>v4l2_device_unregister(&dev->v4l2_dev);
> >>
> > 
> > 
> > 
> > Thanks,
> > Mauro
> >   
> 



Thanks,
Mauro


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

2018-08-14 Thread Hans Verkuil
On 13/08/18 17:15, Mauro Carvalho Chehab wrote:
> Em Sat,  4 Aug 2018 14:45:26 +0200
> Hans Verkuil  escreveu:
> 
>> 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
> 
> Patch itself looks good. Yet, perhaps we could request both
> CONFIG_DEBUG_FS and CONFIG_VIDEO_ADV_DEBUG.
> 
> Also, instead of ifdef, please use IS_ENABLED for DEBUG_FS. That tends
> to be safer long term.
> 
> With that:
> 
> Reviewed-by: Mauro Carvalho Chehab 

I don't intend to merge this patch yet. I'm not happy with it: I would
really like to count the objects per-request instead of globally, and
provide some more information about requests and their objects.

It was really a quick hack so that I could verify that all requests and
objects are properly freed.

Regards,

Hans

> 
>> +/*
>> + * 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(&dev->num_requests));
>> +seq_printf(file, "number of request objects: %d\n",
>> +   atomic_read(&dev->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(&mdev->graph_mutex);
>>  ida_init(&mdev->entity_internal_idx);
>>  
>> +atomic_set(&mdev->num_requests, 0);
>> +atomic_set(&mdev->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(&devnode->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(&devnode->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(&mdev->devnode->dev, &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(&devnode->dev, mdev);
>> +
>>  /* Part 4: Activate this minor. The char device can now be used. */
>>  set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
>>  
>> @@ -310,6 +318,14 @@ static int __init media_devnode_init(void)

Re: why does aptina_pll_calculate insist on exact division?

2018-08-14 Thread Laurent Pinchart
Hi Helmut,

(CC'ing Sakari Ailus who is our current PLL expert after spending so much time 
on the SMIA PLL code)

On Tuesday, 14 August 2018 09:35:40 EEST Helmut Grohne wrote:
> Hi,
> 
> I tried using the aptina_pll_calculate for a "new" imager and ran into
> problems. After filling out aptina_pll_limits from the data sheet, I was
> having a hard time finding a valid pix_clock. Most of the ones I tried
> are rejected by aptina_pll_calculate for various reasons. In particular,
> no pix_clock close to pix_clock_max is allowed.

How do you mean ? The only place where pix_clock_max is used is in the 
following code:

if (pll->pix_clock == 0 || pll->pix_clock > limits->pix_clock_max) {
dev_err(dev, "pll: invalid pixel clock frequency.\n");
return -EINVAL;
}

aptina_pll_calculate() rejects a request pixel clock value higher than the 
pixel clock frequency higher limit, which is also given by the caller. That 
shouldn't happen, it would be a bug in the caller.

> Why does the calculation method insist on exact division and avoiding
> fractional numbers?

I'm not sure what you mean by avoiding fractional numbers. Could you please 
elaborate ? Please keep in mind that I last touched the code 6 years, so my 
memory isn't exactly fresh.

If you mean using floating point operations to calculate PLL parameters, 
remember that the code runs in the Linux kernel, where floating point isn't 
allowed. You would thus have to implement the algorithm using fixed-point 
calculation.

> I'm using an ext_clock of 50 MHz. This clock is derived from a 33 MHz
> clock and the 50 MHz is not attained exactly. Rather it ends up being
> more like 49.76 Hz. This raises the question, what value I should
> put into ext_clock (or the corresponding device tree property). Should I
> use the requested frequency or the actual frequency?

There's no such thing as an exact frequency anyway, as it's a physical value. 
I'd got for 50 MHz for simplicity.

> Worse, depending on the precise value of the ext_clock, aptina_pll_calculate
> may or may not be able to compute pll parameters.
> 
> On the other hand, the manufacturer provided configuration tool happily
> computes pll parameters that result in close, but not exactly, the
> requested pix_clock. In particular, the pll parameters do not
> necessarily result in a whole number. It appears to merely approximate
> the requested frequency.

aptina_pll_calculate() also approximates the requested frequency, but as it 
appears from your test, fails in some cases. That's certainly an issue in the 
code and should be fixed. Feel free to convince the manufacturer to release 
their PLL parameters computation code under the GPL ;-)

> Can you explain where the requirement to avoid fractional numbers comes
> from? Would it be reasonable to use a different algorithm that avoids
> this requirement?

Again, please elaborate on what you mean by avoiding fractional numbers. I 
would certainly be open to a different algorithm (or possibly fixes to the 
existing code), as long as it fulfills the requirements behind the current 
implementation. In particular the code should compute the optimum PLL 
parameters when multiple options are possible, and its complexity should be 
lower than O(n^2) (ideally O(1), if not possible O(n)).

-- 
Regards,

Laurent Pinchart





Re: [PATCHv17 30/34] vim2m: use workqueue

2018-08-14 Thread Hans Verkuil
On 13/08/18 17:05, Mauro Carvalho Chehab wrote:
> Em Sat,  4 Aug 2018 14:45:22 +0200
> Hans Verkuil  escreveu:
> 
>> 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 
> 
> Reviewed-by: Mauro Carvalho Chehab 
> 
> Shouldn't this come earlier at the series (before adding request API
> support to m2m) in order to avoid regressions?

??? At this stage vim2m doesn't support the request API yet. It's the next
patch that adds that (and that's when this patch is needed for it to work).

Regards,

Hans

> 
>> ---
>>  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(&dev->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(&dev->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 = &dev->vfd;
>>  vfd->lock = &dev->dev_mutex;
>>  vfd->v4l2_dev = &dev->v4l2_dev;
>> +INIT_DELAYED_WORK(&dev->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(&dev->v4l2_dev,
>>  "Device registered as /dev/video%d\n", vfd->num);
>>  
>> -timer_setup(&dev->timer, device_isr, 0);
>>  platform_set_drvdata(pdev, dev);
>>  
>>  dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
>> @@ -1083,7 +1079,6 @@ static int vim2m_remove(struct platform_device *pdev)
>>  media_device_cleanup(&dev->mdev);
>>  #endif
>>  v4l2_m2m_release(dev->m2m_dev);
>> -del_timer_sync(&dev->timer);
>>  video_unregister_device(&dev->vfd);
>>  v4l2_device_unregister(&dev->v4l2_dev);
>>  
> 
> 
> 
> Thanks,
> Mauro
> 



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

2018-08-14 Thread Hans Verkuil
On 13/08/18 17:02, Mauro Carvalho Chehab wrote:
> Em Sat,  4 Aug 2018 14:45:21 +0200
> Hans Verkuil  escreveu:
> 
>> 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 
> 
> Reviewed-by: Mauro Carvalho Chehab 
> 
> But please notice below that there's another change on patch 1/34 due
> to this patchset.
> 
>> ---
>>  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(&m2m_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__);
> 
> I had to double-check the documentation at patch 01/34. While on one
> part is says the same, saying that -EPERM is the error code, on
> another part, it says:
> 
>   +Note that there is typically no need to use the Request API for 
> CAPTURE buffers
>   +since there are no per-frame settings to report there.
> 
> "typically" means that the normal usecase is to now allow, but gives
> it open to implementations doing it.
> 
> Please fix that paragraph on patch 01/34 to reflect that no CAPTURE
> buffers should be used with request API for m2m, in order to
> reflect the code's implementation.

Good catch! That's a left-over from earlier versions of the documentation.
I'll update the doc text.

Regards,

Hans

> 
>> +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, &req->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, &req->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,
>> +   

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

2018-08-14 Thread Hans Verkuil
On 13/08/18 16:50, Mauro Carvalho Chehab wrote:
> Em Sat,  4 Aug 2018 14:45:17 +0200
> Hans Verkuil  escreveu:
> 
>> 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 == &vb2_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(&req->lock, flags);
>> +list_for_each_entry(obj, &req->objects, list) {
>> +if (vb2_request_object_is_buffer(obj)) {
>> +has_buffers = true;
>> +break;
>> +}
>> +}
>> +spin_unlock_irqrestore(&req->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.
> 
> It should be mentioned that it should be called with req->lock locked.

No, it doesn't.

All it does is:

bool vb2_request_object_is_buffer(struct media_request_object *obj)
{
return obj->ops == &vb2_core_req_ops;
}
EXPORT_SYMBOL_GPL(vb2_request_object_is_buffer);

That test doesn't require req->lock to be locked.

Regards,

Hans

> 
> With such change:
> 
> Reviewed-by: Mauro Carvalho Chehab 
> 
>> + */
>> +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 */
> 
> 
> 
> Thanks,
> Mauro
> 



  1   2   >