From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Douglas Anderson <dianders@chromium.org>
Cc: dri-devel@lists.freedesktop.org,
Philip Chen <philipchen@chromium.org>,
Boris Brezillon <boris.brezillon@collabora.com>,
Daniel Vetter <daniel@ffwll.ch>, David Airlie <airlied@linux.ie>,
Jagan Teki <jagan@amarulasolutions.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Neil Armstrong <narmstrong@baylibre.com>,
Robert Foss <robert.foss@linaro.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] drm/bridge: Fix the bridge chain order for pre_enable / post_disable
Date: Fri, 22 Oct 2021 07:43:44 +0300 [thread overview]
Message-ID: <YXJBgNvkZb14AJDQ@pendragon.ideasonboard.com> (raw)
In-Reply-To: <20211021122719.1.I56d382006dea67ed8f30729a751fbc75434315b2@changeid>
Hi Doug,
Thank you for the patch.
On Thu, Oct 21, 2021 at 12:29:01PM -0700, Douglas Anderson wrote:
> Right now, the chaining order of
> pre_enable/enable/disable/post_disable looks like this:
>
> pre_enable: start from connector and move to encoder
> enable: start from encoder and move to connector
> disable: start from connector and move to encoder
> post_disable: start from encoder and move to connector
>
> In the above, it can be seen that at least pre_enable() and
> post_disable() are opposites of each other and enable() and disable()
> are opposites. However, it seems broken that pre_enable() and enable()
> would not move in the same direction. In other parts of Linux you can
> see that various stages move in the same order. For instance, during
> system suspend the "early" calls run in the same order as the normal
> calls run in the same order as the "late" calls run in the same order
> as the "noirq" calls.
>
> Let fix the above so that it makes more sense. Now we'll have:
>
> pre_enable: start from encoder and move to connector
> enable: start from encoder and move to connector
> disable: start from connector and move to encoder
> post_disable: start from connector and move to encoder
>
> This order is chosen because if there are parent-child relationships
> anywhere I would expect that the encoder would be a parent and the
> connector a child--not the other way around.
>
> This can be important when using the DP AUX bus to instantiate a
> panel. The DP AUX bus is likely part of a bridge driver and is a
> parent of the panel. We'd like the bridge to be pre_enabled before the
> panel and the panel to be post_disabled before the
> bridge. Specifically, this allows pm_runtime_put_sync_suspend() in a
> bridge driver's post_suspend to work properly even a panel is under
> it.
>
> NOTE: it's entirely possible that this change could break someone who
> was relying on the old order. Hopefully this isn't the case, but if
> this does break someone it seems like it's better to do it sonner
> rather than later so we can fix everyone to handle the order that
> makes the most sense.
I'm less hopeful than you are on this, changing the order of operations
is very risky. I'm also concerned about hardware damage, the pre-enable
operation is often used to power up devices, and powering up a source
before a sink is dangerous as many devices don't like having I/O voltage
applied to their pins before they get powered up. If you really want to
land this, the patch needs very very broad testing, as well as a plan to
address the power up issue.
> A FURTHER NOTE: Looking closer at commit 4e5763f03e10 ("drm/bridge:
> ti-sn65dsi86: Wrap panel with panel-bridge") you can see that patch
> inadvertently changed the order of things. The order used to be
> correct (panel prepare was at the tail of the bridge enable) but it
> became backwards. We'll restore the original order with this patch.
>
> Fixes: 4e5763f03e10 ("drm/bridge: ti-sn65dsi86: Wrap panel with panel-bridge")
> Fixes: 05193dc38197 ("drm/bridge: Make the bridge chain a double-linked list")
> Signed-off-by: Douglas Anderson <dianders@chromium.org>
> ---
>
> drivers/gpu/drm/drm_bridge.c | 28 ++++++++++++++--------------
> 1 file changed, 14 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
> index c96847fc0ebc..98808af59afd 100644
> --- a/drivers/gpu/drm/drm_bridge.c
> +++ b/drivers/gpu/drm/drm_bridge.c
> @@ -583,18 +583,14 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_set);
> void drm_bridge_chain_pre_enable(struct drm_bridge *bridge)
> {
> struct drm_encoder *encoder;
> - struct drm_bridge *iter;
>
> if (!bridge)
> return;
>
> encoder = bridge->encoder;
> - list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
> - if (iter->funcs->pre_enable)
> - iter->funcs->pre_enable(iter);
> -
> - if (iter == bridge)
> - break;
> + list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
> + if (bridge->funcs->pre_enable)
> + bridge->funcs->pre_enable(bridge);
> }
> }
> EXPORT_SYMBOL(drm_bridge_chain_pre_enable);
> @@ -684,26 +680,30 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
> struct drm_atomic_state *old_state)
> {
> struct drm_encoder *encoder;
> + struct drm_bridge *iter;
>
> if (!bridge)
> return;
>
> encoder = bridge->encoder;
> - list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
> - if (bridge->funcs->atomic_post_disable) {
> + list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
> + if (iter->funcs->atomic_post_disable) {
> struct drm_bridge_state *old_bridge_state;
>
> old_bridge_state =
> drm_atomic_get_old_bridge_state(old_state,
> - bridge);
> + iter);
> if (WARN_ON(!old_bridge_state))
> return;
>
> - bridge->funcs->atomic_post_disable(bridge,
> - old_bridge_state);
> - } else if (bridge->funcs->post_disable) {
> - bridge->funcs->post_disable(bridge);
> + iter->funcs->atomic_post_disable(iter,
> + old_bridge_state);
> + } else if (iter->funcs->post_disable) {
> + iter->funcs->post_disable(iter);
> }
> +
> + if (iter == bridge)
> + break;
> }
> }
> EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
--
Regards,
Laurent Pinchart
prev parent reply other threads:[~2021-10-22 4:44 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-21 19:29 [PATCH] drm/bridge: Fix the bridge chain order for pre_enable / post_disable Douglas Anderson
2021-10-21 20:21 ` Sam Ravnborg
2021-10-21 20:33 ` Doug Anderson
2021-10-21 20:41 ` Sam Ravnborg
2021-10-21 22:13 ` Philip Chen
2021-10-25 11:00 ` Andrzej Hajda
2021-10-25 11:21 ` Laurent Pinchart
2021-10-25 20:11 ` Andrzej Hajda
2021-10-26 0:37 ` Doug Anderson
2021-10-26 23:25 ` Laurent Pinchart
2021-10-29 15:57 ` Andrzej Hajda
2021-10-22 4:43 ` Laurent Pinchart [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YXJBgNvkZb14AJDQ@pendragon.ideasonboard.com \
--to=laurent.pinchart@ideasonboard.com \
--cc=airlied@linux.ie \
--cc=boris.brezillon@collabora.com \
--cc=daniel@ffwll.ch \
--cc=dianders@chromium.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=jagan@amarulasolutions.com \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=narmstrong@baylibre.com \
--cc=philipchen@chromium.org \
--cc=robert.foss@linaro.org \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.