On 17/08/18 12:02, Tomasz Figa wrote:
> On Thu, Aug 16, 2018 at 8:15 PM Mauro Carvalho Chehab
> <[email protected]> wrote:
>>
>> Em Thu, 16 Aug 2018 12:25:25 +0200
>> Hans Verkuil <[email protected]> escreveu:
>>
>>> Laurent raised a few API issues/questions in his review of the
>>> documentation.
>>>
>>> I've consolidated those in this RFC. I would like to know what others think
>>> and if I should make changes.
>
> Thanks Hans for a nice summary and Mauro for initial input. :)
>
>>>
>>> 1) Should you be allowed to set controls directly if they are also used in
>>> requests? Right now this is allowed, although we warn in the spec that
>>> this can lead to undefined behavior.
>>>
>>> In my experience being able to do this is very useful while testing,
>>> and restricting this is not all that easy to implement. I also think it
>>> is
>>> not our job. It is not as if something will break when you do this.
>>>
>>> If there really is a good reason why you can't mix this for a specific
>>> control, then the driver can check this and return -EBUSY.
>>
>> IMHO, there's not much sense on preventing it. Just having a warning
>> at the spec is enough.
>>
>
> I tend to agree with Mauro on this.
>
> Besides testing, there are some legit use cases where a carefully
> programmed user space may want to choose between setting controls
> directly and via a request, depending on circumstances. For example,
> one may want to set focus position alone (potentially a big step,
> taking time), before even attempting to capture any frames and then,
> when the capture starts, move the position gradually (in small steps,
> not taking too much time) with subsequent requests, to obtain a set of
> frames with different focus position.
>
>> +.. caution::
>> +
>> + Setting the same control through a request and also directly can lead to
>> + undefined behavior!
>>
>> It is already warned with a caution. Anyone that decides to ignore a
>> warning like that will deserve his faith if things stop work.
>>
>>>
>>> 2) If request_fd in QBUF or the control ioctls is not a request fd, then we
>>> now return ENOENT. Laurent suggests using EBADR ('Invalid request
>>> descriptor')
>>> instead. This seems like a good idea to me. Should I change this?
>>
>> I don't have a strong opinion, but EBADR value seems to be arch-dependent:
>>
>> arch/alpha/include/uapi/asm/errno.h:#define EBADR 98 /*
>> Invalid request descriptor */
>> arch/mips/include/uapi/asm/errno.h:#define EBADR 51 /*
>> Invalid request descriptor */
>> arch/parisc/include/uapi/asm/errno.h:#define EBADR 161 /*
>> Invalid request descriptor */
>> arch/sparc/include/uapi/asm/errno.h:#define EBADR 103 /*
>> Invalid request descriptor */
>> include/uapi/asm-generic/errno.h:#define EBADR 53 /*
>> Invalid request descriptor */
>>
>> Also, just because its name says "invalid request", it doesn't mean that it
>> is the right error code. In this specific case, we're talking about a file
>> descriptor. Invalid file descriptors is something that the FS subsystem
>> has already a defined set of return codes. We should stick with whatever
>> FS uses when a file descriptor is invalid.
>>
>> Where the VFS code returns EBADR? Does it make sense for our use cases?
>>
>
> DMA-buf framework seems to return -EINVAL if a non-DMA-buf FD is
> passed to dma_buf_get():
> https://elixir.bootlin.com/linux/v4.18.1/source/drivers/dma-buf/dma-buf.c#L497
>
>>>
>>> 3) Calling VIDIOC_G_EXT_CTRLS for a request that has not been queued yet
>>> will
>>> return either the value of the control you set earlier in the request, or
>>> the current HW control value if it was never set in the request.
>>>
>>> I believe it makes sense to return what was set in the request previously
>>> (if you set it, you should be able to get it), but it is an idea to
>>> return
>>> ENOENT when calling this for controls that are NOT in the request.
>>>
>>> I'm inclined to implement that. Opinions?
>>
>> Return the request "cached" value, IMO, doesn't make sense. If the
>> application needs such cache, it can implement itself.
>
> Can we think about any specific use cases for a user space that first
> sets a control value to a request and then needs to ask the kernel to
> get the value back? After all, it was the user space which set the
> value, so I'm not sure if there is any need for the kernel to be an
> intermediary here.
>
>>
>> Return an error code if the request has not yet completed makes
>> sense. Not sure what would be the best error code here... if the
>> request is queued already (but not processed), EBUSY seems to be the
>> better choice, but, if it was not queued yet, I'm not sure. I guess
>> ENOENT would work.
>
> IMHO, as far as we assign unique error codes for different conditions
> and document them well, we should be okay with any not absurdly
> mismatched code. After all, most of those codes are defined for file
> system operations and don't really map directly to anything else.
>
> FYI, VIDIOC_G_(EXT_)CTRL returns EINVAL if an unsupported control is
> queried, so if we decided to keep the "cache" functionality after all,
> perhaps we should stay consistent with it?
> Reference:
> https://www.kernel.org/doc/html/latest/media/uapi/v4l/vidioc-g-ext-ctrls.html#return-value
>
> My suggestion would be:
> - EINVAL: the control was not in the request, (if we keep the cache
> functionality)
> - EPERM: the value is not ready, (we selected this code for Decoder
> Interface to mean that CAPTURE format is not ready, which is similar;
> perhaps that could be consistent?)
>
> Note that EINVAL would only apply to writable controls, while EPERM
> only to volatile controls, since the latter can only change due to
> request completion (non-volatile controls can only change as an effect
> of user space action).
>
I'm inclined to just always return EPERM when calling G_EXT_CTRLS for
a request. We can always relax this in the future.
So when a request is not yet queued G_EXT_CTRLS returns EPERM, when
queued but not completed it returns EBUSY and once completed it will
work as it does today.
Regards,
Hans
>>
>>>
>>> 4) When queueing a buffer to a request with VIDIOC_QBUF you set
>>> V4L2_BUF_FLAG_REQUEST_FD
>>> to indicate a valid request_fd. For other queue ioctls that take a
>>> struct v4l2_buffer
>>> this flag and the request_fd field are just ignored. Should we return
>>> EINVAL
>>> instead if the flag is set for those ioctls?
>>>
>>> The argument for just ignoring it is that older kernels that do not know
>>> about
>>> this flag will ignore it as well. There is no check against unknown
>>> flags.
>>
>> As I answered before, I don't see any need to add extra code for checking
>> invalid
>> flags.
>>
>> It might make sense to ask users to clean the flag if not QBUF, just at the
>> eventual remote case we might want to use it on other ioctls.
>
> Agreed with Mauro on this.
>
> Best regards,
> Tomasz
>