public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] drm/bridge: Fix handling of bridges with pre_enable_prev_first flag
@ 2023-07-07 19:00 Vladimir Lypak
  2023-07-10  7:46 ` Frieder Schrempf
  0 siblings, 1 reply; 4+ messages in thread
From: Vladimir Lypak @ 2023-07-07 19:00 UTC (permalink / raw)
  To: Vladimir Lypak
  Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, David Airlie, Daniel Vetter,
	Dave Stevenson, Frieder Schrempf, dri-devel, linux-kernel

In function drm_atomic_bridge_chain_post_disable handling of
pre_enable_prev_first flag is broken because "next" variable will always
end up set to value of "bridge". This breaks loop which should disable
bridges in reverse:

 next = list_next_entry(bridge, chain_node);

 if (next->pre_enable_prev_first) {
        /* next bridge had requested that prev
         * was enabled first, so disabled last
         */
        limit = next;

        /* Find the next bridge that has NOT requested
         * prev to be enabled first / disabled last
         */
        list_for_each_entry_from(next, &encoder->bridge_chain,
                                 chain_node) {
// Next condition is always true. It is likely meant to be inversed
// according to comment above. But doing this uncovers another problem:
// it won't work if there are few bridges with this flag set at the end.
                if (next->pre_enable_prev_first) {
                        next = list_prev_entry(next, chain_node);
                        limit = next;
// Here we always set next = limit = branch at first iteration.
                        break;
                }
        }

        /* Call these bridges in reverse order */
        list_for_each_entry_from_reverse(next, &encoder->bridge_chain,
                                         chain_node) {
// This loop never executes past this branch.
                if (next == bridge)
                        break;

                drm_atomic_bridge_call_post_disable(next, old_state);

In this patch logic for handling the flag is simplified. Temporary
"iter" variable is introduced instead of "next" which is used only
inside inner loops.

Fixes: 4fb912e5e190 ("drm/bridge: Introduce pre_enable_prev_first to alter bridge init order")
Signed-off-by: Vladimir Lypak <vladimir.lypak@gmail.com>
---
 drivers/gpu/drm/drm_bridge.c | 46 ++++++++++++++----------------------
 1 file changed, 18 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index c3d69af02e79..7a5b39a46325 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -660,7 +660,7 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
 					  struct drm_atomic_state *old_state)
 {
 	struct drm_encoder *encoder;
-	struct drm_bridge *next, *limit;
+	struct drm_bridge *iter, *limit;
 
 	if (!bridge)
 		return;
@@ -670,36 +670,26 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
 	list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
 		limit = NULL;
 
-		if (!list_is_last(&bridge->chain_node, &encoder->bridge_chain)) {
-			next = list_next_entry(bridge, chain_node);
-
-			if (next->pre_enable_prev_first) {
-				/* next bridge had requested that prev
-				 * was enabled first, so disabled last
-				 */
-				limit = next;
-
-				/* Find the next bridge that has NOT requested
-				 * prev to be enabled first / disabled last
-				 */
-				list_for_each_entry_from(next, &encoder->bridge_chain,
-							 chain_node) {
-					if (next->pre_enable_prev_first) {
-						next = list_prev_entry(next, chain_node);
-						limit = next;
-						break;
-					}
-				}
+		/* Find sequence of bridges (bridge, limit] which requested prev to
+		 * be enabled first and disabled last
+		 */
+		iter = list_next_entry(bridge, chain_node);
+		list_for_each_entry_from(iter, &encoder->bridge_chain, chain_node) {
+			if (!iter->pre_enable_prev_first)
+				break;
+
+			limit = iter;
+		}
 
-				/* Call these bridges in reverse order */
-				list_for_each_entry_from_reverse(next, &encoder->bridge_chain,
-								 chain_node) {
-					if (next == bridge)
-						break;
-
-					drm_atomic_bridge_call_post_disable(next,
-									    old_state);
-				}
+		if (limit) {
+			/* Call these bridges in reverse order */
+			iter = limit;
+			list_for_each_entry_from_reverse(iter,
+					&encoder->bridge_chain, chain_node) {
+				if (iter == bridge)
+					break;
+
+				drm_atomic_bridge_call_post_disable(iter, old_state);
 			}
 		}
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/1] drm/bridge: Fix handling of bridges with pre_enable_prev_first flag
  2023-07-07 19:00 [PATCH 1/1] drm/bridge: Fix handling of bridges with pre_enable_prev_first flag Vladimir Lypak
@ 2023-07-10  7:46 ` Frieder Schrempf
  2023-07-14 17:16   ` Dave Stevenson
  0 siblings, 1 reply; 4+ messages in thread
From: Frieder Schrempf @ 2023-07-10  7:46 UTC (permalink / raw)
  To: Vladimir Lypak, Dave Stevenson
  Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, David Airlie, Daniel Vetter,
	dri-devel, linux-kernel, Jagan Teki

On 07.07.23 21:00, Vladimir Lypak wrote:
> [Sie erhalten nicht häufig E-Mails von vladimir.lypak@gmail.com. Weitere Informationen, warum dies wichtig ist, finden Sie unter https://aka.ms/LearnAboutSenderIdentification ]
> 
> In function drm_atomic_bridge_chain_post_disable handling of
> pre_enable_prev_first flag is broken because "next" variable will always
> end up set to value of "bridge". This breaks loop which should disable
> bridges in reverse:
> 
>  next = list_next_entry(bridge, chain_node);
> 
>  if (next->pre_enable_prev_first) {
>         /* next bridge had requested that prev
>          * was enabled first, so disabled last
>          */
>         limit = next;
> 
>         /* Find the next bridge that has NOT requested
>          * prev to be enabled first / disabled last
>          */
>         list_for_each_entry_from(next, &encoder->bridge_chain,
>                                  chain_node) {
> // Next condition is always true. It is likely meant to be inversed
> // according to comment above. But doing this uncovers another problem:
> // it won't work if there are few bridges with this flag set at the end.
>                 if (next->pre_enable_prev_first) {
>                         next = list_prev_entry(next, chain_node);
>                         limit = next;
> // Here we always set next = limit = branch at first iteration.
>                         break;
>                 }
>         }
> 
>         /* Call these bridges in reverse order */
>         list_for_each_entry_from_reverse(next, &encoder->bridge_chain,
>                                          chain_node) {
> // This loop never executes past this branch.
>                 if (next == bridge)
>                         break;
> 
>                 drm_atomic_bridge_call_post_disable(next, old_state);
> 
> In this patch logic for handling the flag is simplified. Temporary
> "iter" variable is introduced instead of "next" which is used only
> inside inner loops.
> 
> Fixes: 4fb912e5e190 ("drm/bridge: Introduce pre_enable_prev_first to alter bridge init order")
> Signed-off-by: Vladimir Lypak <vladimir.lypak@gmail.com>

I haven't had a chance to look at this, but I still want to reference
another patch by Jagan that intends to fix some bug in this area:

https://patchwork.kernel.org/project/dri-devel/patch/20230328170752.1102347-1-jagan@amarulasolutions.com/

+Cc: Jagan

Dave, as you introduced this feature, did you have a chance to look at
Jagan's and Vladimir's patches?

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/1] drm/bridge: Fix handling of bridges with pre_enable_prev_first flag
  2023-07-10  7:46 ` Frieder Schrempf
@ 2023-07-14 17:16   ` Dave Stevenson
  2023-07-17  7:09     ` Frieder Schrempf
  0 siblings, 1 reply; 4+ messages in thread
From: Dave Stevenson @ 2023-07-14 17:16 UTC (permalink / raw)
  To: Frieder Schrempf
  Cc: Vladimir Lypak, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec, David Airlie,
	Daniel Vetter, dri-devel, linux-kernel, Jagan Teki

Hi Frieder

On Mon, 10 Jul 2023 at 08:46, Frieder Schrempf
<frieder.schrempf@kontron.de> wrote:
>
> On 07.07.23 21:00, Vladimir Lypak wrote:
> > [Sie erhalten nicht häufig E-Mails von vladimir.lypak@gmail.com. Weitere Informationen, warum dies wichtig ist, finden Sie unter https://aka.ms/LearnAboutSenderIdentification ]
> >
> > In function drm_atomic_bridge_chain_post_disable handling of
> > pre_enable_prev_first flag is broken because "next" variable will always
> > end up set to value of "bridge". This breaks loop which should disable
> > bridges in reverse:
> >
> >  next = list_next_entry(bridge, chain_node);
> >
> >  if (next->pre_enable_prev_first) {
> >         /* next bridge had requested that prev
> >          * was enabled first, so disabled last
> >          */
> >         limit = next;
> >
> >         /* Find the next bridge that has NOT requested
> >          * prev to be enabled first / disabled last
> >          */
> >         list_for_each_entry_from(next, &encoder->bridge_chain,
> >                                  chain_node) {
> > // Next condition is always true. It is likely meant to be inversed
> > // according to comment above. But doing this uncovers another problem:
> > // it won't work if there are few bridges with this flag set at the end.
> >                 if (next->pre_enable_prev_first) {
> >                         next = list_prev_entry(next, chain_node);
> >                         limit = next;
> > // Here we always set next = limit = branch at first iteration.
> >                         break;
> >                 }
> >         }
> >
> >         /* Call these bridges in reverse order */
> >         list_for_each_entry_from_reverse(next, &encoder->bridge_chain,
> >                                          chain_node) {
> > // This loop never executes past this branch.
> >                 if (next == bridge)
> >                         break;
> >
> >                 drm_atomic_bridge_call_post_disable(next, old_state);
> >
> > In this patch logic for handling the flag is simplified. Temporary
> > "iter" variable is introduced instead of "next" which is used only
> > inside inner loops.
> >
> > Fixes: 4fb912e5e190 ("drm/bridge: Introduce pre_enable_prev_first to alter bridge init order")
> > Signed-off-by: Vladimir Lypak <vladimir.lypak@gmail.com>
>
> I haven't had a chance to look at this, but I still want to reference
> another patch by Jagan that intends to fix some bug in this area:
>
> https://patchwork.kernel.org/project/dri-devel/patch/20230328170752.1102347-1-jagan@amarulasolutions.com/
>
> +Cc: Jagan
>
> Dave, as you introduced this feature, did you have a chance to look at
> Jagan's and Vladimir's patches?

Sorry, they'd fallen off my radar.
I'm having a look at the moment, but will probably need to carry it
over to Monday.

  Dave

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/1] drm/bridge: Fix handling of bridges with pre_enable_prev_first flag
  2023-07-14 17:16   ` Dave Stevenson
@ 2023-07-17  7:09     ` Frieder Schrempf
  0 siblings, 0 replies; 4+ messages in thread
From: Frieder Schrempf @ 2023-07-17  7:09 UTC (permalink / raw)
  To: Dave Stevenson
  Cc: Vladimir Lypak, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec, David Airlie,
	Daniel Vetter, dri-devel, linux-kernel, Jagan Teki

On 14.07.23 19:16, Dave Stevenson wrote:
> Hi Frieder
> 
> On Mon, 10 Jul 2023 at 08:46, Frieder Schrempf
> <frieder.schrempf@kontron.de> wrote:
>>
>> On 07.07.23 21:00, Vladimir Lypak wrote:
>>> [Sie erhalten nicht häufig E-Mails von vladimir.lypak@gmail.com. Weitere Informationen, warum dies wichtig ist, finden Sie unter https://aka.ms/LearnAboutSenderIdentification ]
>>>
>>> In function drm_atomic_bridge_chain_post_disable handling of
>>> pre_enable_prev_first flag is broken because "next" variable will always
>>> end up set to value of "bridge". This breaks loop which should disable
>>> bridges in reverse:
>>>
>>>  next = list_next_entry(bridge, chain_node);
>>>
>>>  if (next->pre_enable_prev_first) {
>>>         /* next bridge had requested that prev
>>>          * was enabled first, so disabled last
>>>          */
>>>         limit = next;
>>>
>>>         /* Find the next bridge that has NOT requested
>>>          * prev to be enabled first / disabled last
>>>          */
>>>         list_for_each_entry_from(next, &encoder->bridge_chain,
>>>                                  chain_node) {
>>> // Next condition is always true. It is likely meant to be inversed
>>> // according to comment above. But doing this uncovers another problem:
>>> // it won't work if there are few bridges with this flag set at the end.
>>>                 if (next->pre_enable_prev_first) {
>>>                         next = list_prev_entry(next, chain_node);
>>>                         limit = next;
>>> // Here we always set next = limit = branch at first iteration.
>>>                         break;
>>>                 }
>>>         }
>>>
>>>         /* Call these bridges in reverse order */
>>>         list_for_each_entry_from_reverse(next, &encoder->bridge_chain,
>>>                                          chain_node) {
>>> // This loop never executes past this branch.
>>>                 if (next == bridge)
>>>                         break;
>>>
>>>                 drm_atomic_bridge_call_post_disable(next, old_state);
>>>
>>> In this patch logic for handling the flag is simplified. Temporary
>>> "iter" variable is introduced instead of "next" which is used only
>>> inside inner loops.
>>>
>>> Fixes: 4fb912e5e190 ("drm/bridge: Introduce pre_enable_prev_first to alter bridge init order")
>>> Signed-off-by: Vladimir Lypak <vladimir.lypak@gmail.com>
>>
>> I haven't had a chance to look at this, but I still want to reference
>> another patch by Jagan that intends to fix some bug in this area:
>>
>> https://patchwork.kernel.org/project/dri-devel/patch/20230328170752.1102347-1-jagan@amarulasolutions.com/
>>
>> +Cc: Jagan
>>
>> Dave, as you introduced this feature, did you have a chance to look at
>> Jagan's and Vladimir's patches?
> 
> Sorry, they'd fallen off my radar.
> I'm having a look at the moment, but will probably need to carry it
> over to Monday.

Sure, take your time. I just wanted to make sure that you are aware of
these patches and the existence of a bug in the code.

Thanks!

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-07-17  7:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-07 19:00 [PATCH 1/1] drm/bridge: Fix handling of bridges with pre_enable_prev_first flag Vladimir Lypak
2023-07-10  7:46 ` Frieder Schrempf
2023-07-14 17:16   ` Dave Stevenson
2023-07-17  7:09     ` Frieder Schrempf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox