Re: [PATCH v5 5/6] media: subdev: add v4l2_subdev_call_state_active()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 07/03/2022 15:00, Tomi Valkeinen wrote:
> On 07/03/2022 11:51, Hans Verkuil wrote:
>> Hi Tomi,
>>
>> On 3/7/22 10:16, Tomi Valkeinen wrote:
>>> Hi Hans,
>>>
>>> On 07/03/2022 10:36, Hans Verkuil wrote:
>>>>
>>>>
>>>> On 3/7/22 08:16, Tomi Valkeinen wrote:
>>>>> Hi Hans,
>>>>>
>>>>> On 04/03/2022 15:34, Hans Verkuil wrote:
>>>>>> Hi Tomi,
>>>>>>
>>>>>> On 3/1/22 11:55, Tomi Valkeinen wrote:
>>>>>>> Add v4l2_subdev_call_state_active() macro to help calling subdev ops
>>>>>>> that take a subdev state as a parameter. Normally the v4l2 framework
>>>>>>> will lock and pass the correct subdev state to the subdev ops, but there
>>>>>>> are legacy situations where this is not the case (e.g. non-MC video
>>>>>>> device driver calling set_fmt in a source subdev).
>>>>>>>
>>>>>>> As this macro is only needed for legacy use cases, the macro is added in
>>>>>>> a new header file, v4l2-subdev-legacy.h.
>>>>>>>
>>>>>>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@xxxxxxxxxxxxxxxx>
>>>>>>> ---
>>>>>>>     include/media/v4l2-subdev-legacy.h | 42 ++++++++++++++++++++++++++++++
>>>>>>>     1 file changed, 42 insertions(+)
>>>>>>>     create mode 100644 include/media/v4l2-subdev-legacy.h
>>>>>>>
>>>>>>> diff --git a/include/media/v4l2-subdev-legacy.h b/include/media/v4l2-subdev-legacy.h
>>>>>>> new file mode 100644
>>>>>>> index 000000000000..6a61e579b629
>>>>>>> --- /dev/null
>>>>>>> +++ b/include/media/v4l2-subdev-legacy.h
>>>>>>> @@ -0,0 +1,42 @@
>>>>>>> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>>>>>>> +/*
>>>>>>> + *  V4L2 sub-device legacy support header.
>>>>>>> + *
>>>>>>> + *  Copyright (C) 2022  Tomi Valkeinen <tomi.valkeinen@xxxxxxxxxxxxxxxx>
>>>>>>> + */
>>>>>>> +
>>>>>>> +#ifndef _V4L2_SUBDEV_LEGACY_H
>>>>>>> +#define _V4L2_SUBDEV_LEGACY_H
>>>>>>> +
>>>>>>> +/**
>>>>>>> + * v4l2_subdev_call_state_active - call an operation of a v4l2_subdev which
>>>>>>> + *                   takes state as a parameter, passing the
>>>>>>> + *                   subdev its active state.
>>>>>>> + *
>>>>>>> + * @sd: pointer to the &struct v4l2_subdev
>>>>>>> + * @o: name of the element at &struct v4l2_subdev_ops that contains @f.
>>>>>>> + *     Each element there groups a set of callbacks functions.
>>>>>>> + * @f: callback function to be called.
>>>>>>> + *     The callback functions are defined in groups, according to
>>>>>>> + *     each element at &struct v4l2_subdev_ops.
>>>>>>> + * @args: arguments for @f.
>>>>>>> + *
>>>>>>> + * This is similar to v4l2_subdev_call(), except that this version can only be
>>>>>>> + * used for ops that take a subdev state as a parameter. The macro will get the
>>>>>>> + * active state and lock it before calling the op, and unlock it after the
>>>>>>> + * call.
>>>>>>> + */
>>>>>>
>>>>>> You should explain why this is a legacy macro and, ideally, what would need to
>>>>>> be done to get rid of it. The first is in the commit log, but nobody reads that :-)
>>>>>>
>>>>>> But if just using it in a non-MC video device driver constitutes 'legacy' use,
>>>>>> then I disagree with that. There are many non-MC video device drivers, nothing
>>>>>> legacy about that.
>>>>>
>>>>> It's difficult to define all the scenarios where this can be used, but the ones I can imagine fall under legacy (depending on how you define that, though).
>>>>>
>>>>> I use this in CAL driver, which supports non-MC (legacy) and MC. CAL has a bunch of video devices (one for each DMA engine) and two CSI-2 PHY devices (v4l2 subdevs).
>>>>>
>>>>> When operating in MC mode, the userspace will call, e.g., set_fmt in the PHY subdev, and so forth.
>>>>>
>>>>> But in non-MC case the userspace calls VIDIOC_S_FMT in the video dev, and the video dev has to propagate that to the PHY subdev. I do this propagation using the v4l2_subdev_call_state_active macro.
>>>>>
>>>>> I don't know if there are other drivers that support both non-MC and MC modes. I could also just move this macro to the CAL driver, and we could add this to the v4l2 framework if we see other
>>>>> drivers using similar constructs.
>>>>
>>>> It is common to have non-MC drivers that call set_fmt of a subdev.
>>>> Wouldn't they all need to use this helper macro? If so, then this is NOT a
>>>> legacy use, it's just a non-MC driver use.
>>>
>>> These non-MC drivers that call set_fmt of a subdev, they're video device drivers, right? In other words, there are no subdev drivers that call set_fmt on other subdevs?
>>
>> Probably not, but I am not 100% certain. There are a few nested subdev cases, but I don't remember which.
>>
>>>
>>> This does get a bit complex, keeping the old and new code working together. In this context, I think we have three different "classes":
>>>
>>> 1. non-MC
>>> 2. MC, no state support
>>> 3. MC, state support
>>
>> Are you talking about subdev drivers or bridge drivers? It's a bit confusing. I'm assuming it can be either.
> 
> Yes, I mean either one.
> 
>>> We have classes 1 and 2 in upstream, and 3 will be enabled with this series (and expanded with the streams series).
>>>
>>> Classes 1 and 2 continue working as before. If you have a pipeline with only class 3 drivers, it works without any legacy "hacks". The problems come when you combine 1 or 2 with 3. Or possibly the
>>> problems appear only when combining class 1 and class 3, as class 2 drivers are not supposed to call subdev ops which take a state parameter on other subdevs.
>>>
>>> A class 3 driver expects to get either a try or an active state as a parameter, but class 1 drivers pass NULL for the active state. If you write a class 3 driver and want it to work with class 1
>>> (without any changes to those drivers), you must do extra plumbing in the ops functions, to catch the NULL state case and get & lock the state yourself. If you do that, this macro is not needed.
>>>
>>> Alternatively, class 1 drivers could be changed to use this macro, so that a possible class 3 driver in the pipeline would work without additional code. But there are a lot of class 1 drivers, and
>>> thus modifications, and I wasn't planning to go that way.
>>>
>>> The CAL driver I mentioned supports both class 1 and class 3 (via a module parameter) in the video dev driver, and the class 1 mode uses this macro as CAL's PHY subdev (part of the same driver) is
>>> a class 3 subdev. The class 1 support is legacy support in CAL's case.
>>>
>>> So... Depending on what kind of driver combinations we want to support, this may or may not be legacy, depending on how you define legacy =).
>>
>> Let me try to explain what my concerns are. Eventually I would really like all subdevs to be capable of working with MC bridge drivers, i.e. have state support. Bridge drivers can be either MC or
>> non-MC.
>>
>> So I would like to know:
>>
>> 1.1) How to convert a subdev driver to a MC state-aware subdev driver?
> 
> I presume you mean how to convert an MC subdev driver to state-aware MC driver. If you have a non-MC subdev driver, then that first needs to be converted to an MC driver, which is out of scope here.
> 
> Here's an example commit where I convert OV10635 to streams:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git/commit/?h=streams/work-v11&id=ffb08af15f04ef2ce0a00bb356e957c839d6bccb
> 
> However, the commit is on top of the streams series and I add support for multiple streams in addition to the active state, so 1) it's not as simple as it could be (e.g. get_frame_desc() and
> set_routing() ops could be left out), and 2) it's not using the old-style v4l2_subdev_pad_config (which is the only option on top of this series), but the new routes & streams.
> 
> So the example doesn't quite answer to your question... I haven't looked at implementing a driver which would be state-aware but not streams-aware, but I think it's essentially just:
> 
> - Use v4l2_subdev_init_finalize() to create the active state storage
> - Always use state->pads instead of something stored in the driver's private data for active case.

Can you make a patch that converts ov5648.c (or a similar driver) to use
sd->active_state? I'd like to see how that looks.

> 
>> 1.2) What is the legacy code that such a MC state-aware subdev driver has to keep in order to work with older bridge drivers that do not support such subdev drivers? (i.e. they pass NULL as the state)
> 
> I believe the only extra code needed is to handle the state == NULL case. This means adding code to each subdev op which has the state as a parameter, and doing, perhaps, something like this:
> 
> my_set_fmt(sd, _state, fmt)
> {
>     state = _state
> 
>     if (!_state)
>         state = v4l2_subdev_lock_and_get_active_state(sd);
> 
>     ... use 'state' here ...
> 
>     if (!_state)
>         v4l2_subdev_unlock_state(state);
> }
> 
> Maybe we can somehow macro-ify the above, which creates a wrapper for the op. Or, as I mentioned, we could try to change all the drivers that do those calls, so that they use the macro in this patch
> instead.

Right. So to confirm: the only reason a state-ware subdev set_fmt op is called
with a NULL state pointer is if it is called from non-MC bridge drivers? And if
we would update those bridge drivers to always pass a non-NULL state pointer,
then such subdevs no longer need to care about this and can just use the state.

If so, then that's the way forward.

> 
>> 2.1) How to convert a bridge driver (either non-MC or MC, but no state support) to properly support a fully converted subdev (MC state-aware) driver?
> 
> Converting non-MC driver to an MC driver is out of the context here, as it's not related to the active state. An MC bridge driver should work fine with state-aware subdev drivers, as the bridge driver
> should not call any of the subdev's state-related ops.
> 
> To make a non-MC bridge driver support state-aware subdev drivers, they can use the macro in this patch.

That sounds good to me.

The only legacy bit about the macro, though, is the fact that v4l2_subdev_get_active_state()
can return NULL: that indicates that the subdev driver isn't properly state-aware.

So I think this should be a regular macro in v4l2-subdev.h.

Perhaps with a comment mentioning that v4l2_subdev_get_active_state() can be replaced by
v4l2_subdev_lock_and_get_active_state() once all subdevs are state-aware.

> 
>> 2.2) What is the legacy code that such a bridge driver has to keep in order to work with older subdev drivers that are not yet MC state-aware?
> 
> The older subdev drivers should keep working without any extra code.
> 
>> The code needed for 1.2 and 2.2 (helper functions/macros) is legacy code, and can be marked as such.
>> > If this is clear, then we can work towards converting both subdev and 
> bridge drivers and eventually (might take years!) get rid of the legacy code.
>>
>> Removing support for case 2 is probably something that we want to do sooner than later.
>>
>> For the CAL driver I do not consider non-MC support as legacy. It's legacy in the context of the CAL driver only, but API-wise it is not since there are many non-MC bridge drivers.
> 
> That's true, but also, non-MC bridge drivers do not need to use this function if the subdev drivers use the method shown in 1.2. I think this is the question here:
> 
> - Change all the callers and use the macro in this patch. Then the macro is not legacy.
> - Change the callees, in which case this macro is needed only in some cases where, for whatever reason, a specific callee has not been changed (yet?). In this case it's legacy.
> 
> Changing the callers would be a nicer option, I think, but I also fear that it's very difficult and easily brings in bugs. I haven't looked closely, but I think it would be a big patch.

I believe changing the callers is the correct approach. Next to that I want to slowly
convert all subdevs to be state-aware (i.e. use sd->active_state etc). Based on past
experience it is a really bad idea to have all these variations in how subdevs work.
That should be minimized.

I suspect that modifying the callers isn't as bad as you might think. It is also the
sane approach: passing the active_state to the subdev really *is* what you want to do.
It is not a hack, it is the right thing. Adding a workaround in a subdev where a
NULL state is handled separately is, however, a hack, and a hack that is all to easy
to forget to implement in new drivers.

> 
> And it's not clear to me if there's a benefit: do all those drivers ever need to interact a state-aware subdev driver? If they do, maybe there are only a few such subdev drivers, and it's not a big
> issue to have the lock/unlock code in those state-aware subdev drivers. All the other state-aware subdev drivers would not need the legacy support code as they're used only in more modern pipelines.

You never know that: anyone can hook any sensor to a non-MC driver in a product.
Just because there are no such boards in the mainline kernel doesn't mean that
such boards don't exist.

I hope this helps, and apologies for the delay in replying.

Regards,

	Hans



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux