Re: [RFC PATCH] media: rcar-vin: Allow independent VIN link enablement

Steve Longerbeam
2019-01-05T00:49:05Z

Hi Niklas,

How about a patch that simply replaces the entity use_count check with a
stream_count check?

As in:

diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
b/drivers/media/platform/rcar-vin/rcar-core.c
index f0719ce24b97..aef8d8dab6ab 100644
--- a/drivers/media/platform/rcar-vin/rcar-core.c
+++ b/drivers/media/platform/rcar-vin/rcar-core.c
@@ -131,9 +131,13 @@ static int rvin_group_link_notify(struct media_link
*link, u32 flags,
!is_media_entity_v4l2_video_device(link->sink->entity))
return 0;

-    /* If any entity is in use don't allow link changes. */
+    /*
+     * Don't allow link changes if any entity in the graph is
+     * streaming, modifying the CHSEL register fields can disrupt
+     * running streams.
+     */
media_device_for_each_entity(entity, &group->mdev)
-        if (entity->use_count)
+        if (entity->stream_count)
return -EBUSY;

mutex_lock(&group->lock);

And that might be overkilll, maybe only the stream_count's of the VIN
entities need to be checked.

Steve

On 12/29/18 3:37 PM, Steve Longerbeam wrote:
> Hi Niklas,
>
> On 12/26/18 4:51 PM, Niklas Söderlund wrote:
>> Hi Steve,
>>
>> Thanks for your patch.
>>
>> On 2018-12-25 15:27:25 -0800, Steve Longerbeam wrote:
>>> There is a block of code in rvin_group_link_notify() that prevents
>>> enabling a link to a VIN node if any entity in the media graph is
>>> in use. This prevents enabling a VIN link even if there is an in-use
>>> entity somewhere in the graph that is independent of the link's
>>> pipeline.
>>>
>>> For example, the code block will prevent enabling a link from
>>> the first rcar-csi2 receiver to a VIN node even if there is an
>>> enabled link somewhere far upstream on the second independent
>>> rcar-csi2 receiver pipeline.
>> Unfortunately this is by design and needed due to the hardware design.
>> The different VIN endpoints shares a configuration register which
>> controls the routing from the CSI-2 receivers to the VIN (register name
>> CHSEL). Modifying the CHSEL register which is what happens when a link
>> is enabled/disabled can have side effects on running streams even if
>> they are not shown to be dependent in the media graph.
>
> Ok, understood, modifying CHSEL register can adversely affect running
> streams.
>
>>
>> There is a CHSEL register in VIN0 which controls the routing from all
>> CSI-2 receivers to VIN0-3 and a CHSEL register in VIN4 which controls
>> the same for VIN4-7.
>>
>>> If this code block is meant to prevent modifying a link if the
>>> link is actively involved in streaming, there is already such a
>>> check in __media_entity_setup_link() that verifies the stream_count
>>> of the link's source and sink entities are both zero.
>> For the reason above the check in __media_entity_setup_link() is not
>> enough :-( This register sharing is my least favorite thing about the
>> VIN on Gen3 and forces the driver to become more complex as all VIN
>> instances needs to know about each other and interact.
>>
>
> Given above I understand why the stream count checks in
> __media_entity_setup_link() are insufficient, because only the
> requested link's source stream count is checked, and not the other
> CSI-2 receiver for example.
>
> But why check the use counts of every entity upstream from the VIN
> sources? Why not check only the VIN source entities stream counts
> (both CSI-2 receivers and/or parallel devices), and ignore entities
> upstream from those?
>
> And why are the use counts checked, it seems it should be the stream
> counts that should be checked.
>
>>> Remove the code block so that VIN node links can be enabled even if
>>> there are other independent in-use entities.
>> There is room for some improvement in this area disregarding the odd
>> hardware design. It *could* be allowed to change a link terminating in
>> VIN4-7 even if there is a stream running for one or more in VIN0-3.
>>
>> I would be interested to test such a patch but to allow any link change
>> which is allowed by __media_entity_setup_link() is unfortunately not
>> possible, as I understand it. Maybe someone more clever then me can find
>> ways to unlock even more then just the split between VIN0-3 and VIn4-7.
>>
>> In essence the CHSEL register can not be changed if it's involved in a
>> running pipeline even if the end result would be that the running
>> pipeline would look the same. This is possible as there are multiple
>> CHSEL settings where the same source is connected to a specific VIN
>> while other members of the "subgroup of VINs" (e.g. VIN0-3) is routed to
>> something else for the two CHSEL settings.
>
> Right, so rvin_group_link_notify() determines whether the requested
> VIN link enable will result in a valid set of CSI2->VIN links for the
> given hardware, using the CHSEL bitmask tables. Which is why it seems
> it is the stream counts that should be checked as mentioned above,
> rather than the use counts, because the CHSEL bitmask checks are
> validating the set of enabled links, and the only remaining checks are
> to verify no streams are running on either CSI-2 receiver.
>
> Steve
>
>
>>> Fixes: c0cc5aef31 ("media: rcar-vin: add link notify for Gen3")
>>>
>>> Signed-off-by: Steve Longerbeam <slongerbeam@gmail.com>
>>> ---
>>>   drivers/media/platform/rcar-vin/rcar-core.c | 6 ------
>>>   1 file changed, 6 deletions(-)
>>>
>>> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
>>> b/drivers/media/platform/rcar-vin/rcar-core.c
>>> index f0719ce24b97..b2c9a876969e 100644
>>> --- a/drivers/media/platform/rcar-vin/rcar-core.c
>>> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
>>> @@ -116,7 +116,6 @@ static int rvin_group_link_notify(struct
>>> media_link *link, u32 flags,
>>>                           struct rvin_group, mdev);
>>>       unsigned int master_id, channel, mask_new, i;
>>>       unsigned int mask = ~0;
>>> -    struct media_entity *entity;
>>>       struct video_device *vdev;
>>>       struct media_pad *csi_pad;
>>>       struct rvin_dev *vin = NULL;
>>> @@ -131,11 +130,6 @@ static int rvin_group_link_notify(struct
>>> media_link *link, u32 flags,
>>> !is_media_entity_v4l2_video_device(link->sink->entity))
>>>           return 0;
>>>   -    /* If any entity is in use don't allow link changes. */
>>> -    media_device_for_each_entity(entity, &group->mdev)
>>> -        if (entity->use_count)
>>> -            return -EBUSY;
>>> -
>>>       mutex_lock(&group->lock);
>>>         /* Find the master VIN that controls the routes. */
>>> --
>>> 2.17.1
>>>
>