mirror of https://lore.kernel.org/linux-amlogic/
 help / color / mirror / Atom feed
From: Xilin Wu <sophon@radxa.com>
To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	 Maxime Ripard <mripard@kernel.org>,
	Thomas Zimmermann <tzimmermann@suse.de>,
	 David Airlie <airlied@gmail.com>,
	Simona Vetter <simona@ffwll.ch>,
	 Rob Clark <robin.clark@oss.qualcomm.com>,
	 Dmitry Baryshkov <lumag@kernel.org>,
	 Abhinav Kumar <abhinav.kumar@linux.dev>,
	 Jessica Zhang <jesszhan0024@gmail.com>,
	Sean Paul <sean@poorly.run>,
	 Marijn Suijten <marijn.suijten@somainline.org>,
	 Andrzej Hajda <andrzej.hajda@intel.com>,
	 Neil Armstrong <neil.armstrong@linaro.org>,
	Robert Foss <rfoss@kernel.org>,
	 Laurent Pinchart <Laurent.pinchart@ideasonboard.com>,
	 Jonas Karlman <jonas@kwiboo.se>,
	Jernej Skrabec <jernej.skrabec@gmail.com>,
	 Luca Ceresoli <luca.ceresoli@bootlin.com>,
	 Kevin Hilman <khilman@baylibre.com>,
	Jerome Brunet <jbrunet@baylibre.com>,
	 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
	 linux-arm-msm@vger.kernel.org, freedreno@lists.freedesktop.org,
	 dragon@radxa.com, Xilin Wu <sophon@radxa.com>,
	 linux-amlogic@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 10/20] drm/msm/dp: Report stream enable failures through link status
Date: Fri, 09 Oct 2026 11:16:02 +0800	[thread overview]
Message-ID: <20261009-msm-dp-hdr10-v2-10-1835d4966da3@radxa.com> (raw)
In-Reply-To: <20261009-msm-dp-hdr10-v2-0-1835d4966da3@radxa.com>

Atomic bridge enable callbacks cannot return an error to userspace.
After a failed enable, leaving link-status unchanged gives userspace
no indication that it needs to retry the configuration.

Mark the connector link status bad from a work item after unwinding
the failed enable.

Send one connector hotplug notification per failure episode. The
notification also invokes the fbdev hotplug handler, which can retry
the modeset synchronously. Since atomic enable callbacks cannot
return errors, another stream enable failure can requeue this work
without reporting a failed commit to fbdev. Notifying on every
failure could therefore cause an unbounded retry loop.

Subsequent failures still restore BAD after a retry sets link-status
to GOOD, but suppress further notifications until a successful enable
or an external sink connection change. Do not reset the notification
latch during eDP's internal plug and unplug handling, which runs on
every retry.

Skip failures superseded by recovery or an external unplug before the
worker checks the failure state. Protect the failure state with
plugged_lock, then release it before calling
drm_connector_set_link_status_property(). The helper takes the
connection mutex, which precedes plugged_lock in atomic check's lock
order. Send the notification after the helper releases the mutex.
Recovery concurrent with the property update can cause an extra retry.

Initialize the work at probe and cancel it before unbinding the
display.

Assisted-by: LLM
Signed-off-by: Xilin Wu <sophon@radxa.com>
---
 drivers/gpu/drm/msm/dp/dp_display.c | 61 +++++++++++++++++++++++++++++++++++--
 1 file changed, 58 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index b076d44b5118..816f2dc11aea 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -12,9 +12,11 @@
 #include <linux/phy/phy.h>
 #include <linux/delay.h>
 #include <linux/string_choices.h>
+#include <linux/workqueue.h>
 #include <drm/display/drm_dp_aux_bus.h>
 #include <drm/display/drm_hdmi_audio_helper.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_probe_helper.h>
 
 #include "msm_drv.h"
 #include "msm_kms.h"
@@ -54,10 +56,14 @@ struct msm_dp_display_private {
 	bool audio_supported;
 	bool stream_pm_active;
 	bool stream_link_attempted;
+	struct work_struct link_status_work;
 
 	/* Serializes HPD, stream and PSR operations while runtime active. */
 	struct mutex plugged_lock;
 	bool plugged;
+	/* Protected by plugged_lock, including accesses from link_status_work. */
+	bool link_failed;
+	bool link_status_notified;
 
 	struct drm_device *drm_dev;
 
@@ -205,6 +211,39 @@ void msm_dp_display_signal_audio_complete(struct msm_dp *msm_dp_display)
 	complete_all(&dp->audio_comp);
 }
 
+static void msm_dp_display_reset_link_status(struct msm_dp_display_private *dp)
+{
+	lockdep_assert_held(&dp->plugged_lock);
+
+	dp->link_failed = false;
+	dp->link_status_notified = false;
+}
+
+static void msm_dp_display_link_status_work(struct work_struct *work)
+{
+	struct msm_dp_display_private *dp = container_of(work,
+			struct msm_dp_display_private, link_status_work);
+	struct drm_connector *connector = dp->msm_dp_display.connector;
+	bool notify;
+
+	scoped_guard(mutex, &dp->plugged_lock) {
+		/* Skip failures superseded before this work starts. */
+		if (!dp->link_failed)
+			return;
+
+		notify = !dp->link_status_notified;
+		dp->link_status_notified = true;
+	}
+
+	/* The helper takes connection_mutex, so drop plugged_lock first. */
+	drm_connector_set_link_status_property(connector,
+					       DRM_MODE_LINK_STATUS_BAD);
+
+	/* fbdev can retry the modeset synchronously from this notification. */
+	if (notify)
+		drm_kms_helper_connector_hotplug_event(connector);
+}
+
 static int msm_dp_display_bind(struct device *dev, struct device *master,
 			   void *data)
 {
@@ -235,6 +274,7 @@ static void msm_dp_display_unbind(struct device *dev, struct device *master,
 	struct msm_dp_display_private *dp = dev_get_dp_display_private(dev);
 	struct msm_drm_private *priv = dev_get_drvdata(master);
 
+	cancel_work_sync(&dp->link_status_work);
 	of_dp_aux_depopulate_bus(dp->aux);
 
 	msm_dp_aux_unregister(dp->aux);
@@ -424,6 +464,10 @@ static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp)
 
 	mutex_lock(&dp->plugged_lock);
 
+	/* eDP calls this for every enable, including automatic retries. */
+	if (!dp->msm_dp_display.is_edp && !dp->plugged)
+		msm_dp_display_reset_link_status(dp);
+
 	msm_dp_aux_enable_xfers(dp->aux, true);
 
 	ret = msm_dp_display_host_phy_init(dp);
@@ -466,6 +510,9 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp)
 
 	mutex_lock(&dp->plugged_lock);
 
+	if (!dp->msm_dp_display.is_edp)
+		msm_dp_display_reset_link_status(dp);
+
 	dp->panel->video_test = false;
 
 	msm_dp_aux_enable_xfers(dp->aux, false);
@@ -529,10 +576,12 @@ static int msm_dp_irq_hpd_handle(struct msm_dp_display_private *dp)
 	if (!rc) {
 		sink_request = dp->link->sink_request;
 		drm_dbg_dp(dp->drm_dev, "sink_request=%d\n", sink_request);
-		if (sink_request & DS_PORT_STATUS_CHANGED)
+		if (sink_request & DS_PORT_STATUS_CHANGED) {
+			msm_dp_display_reset_link_status(dp);
 			rc = msm_dp_display_process_hpd_high(dp);
-		else
+		} else {
 			rc = msm_dp_display_handle_irq_hpd(dp);
+		}
 	}
 
 	drm_dbg_dp(dp->drm_dev, "After, type=%d, sink_count=%d\n",
@@ -682,7 +731,6 @@ static int msm_dp_display_prepare_link_locked(struct msm_dp_display_private *dp)
 	rc = msm_dp_ctrl_on_link(dp->ctrl, dp->panel);
 	if (rc) {
 		DRM_ERROR("Failed link training (rc=%d)\n", rc);
-		// TODO: schedule drm_connector_set_link_status_property()
 		return rc;
 	}
 
@@ -1278,6 +1326,7 @@ static int msm_dp_display_probe(struct platform_device *pdev)
 	dp->hpd_isr_status = 0;
 
 	mutex_init(&dp->plugged_lock);
+	INIT_WORK(&dp->link_status_work, msm_dp_display_link_status_work);
 
 	rc = msm_dp_display_get_io(dp);
 	if (rc)
@@ -1571,6 +1620,7 @@ void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display,
 		goto err;
 	}
 
+	msm_dp_display_reset_link_status(dp);
 	mutex_unlock(&dp->plugged_lock);
 
 	drm_dbg_dp(msm_dp_display->drm_dev, "type=%d Done\n", msm_dp_display->connector_type);
@@ -1583,6 +1633,11 @@ void msm_dp_display_atomic_enable(struct msm_dp *msm_dp_display,
 	if (msm_dp_display->is_edp)
 		msm_dp_hpd_unplug_handle(dp);
 	msm_dp_display_unprepare(dp);
+	scoped_guard(mutex, &dp->plugged_lock) {
+		dp->link_failed = true;
+		/* Keep reporting BAD, but notify only once until recovery. */
+		schedule_work(&dp->link_status_work);
+	}
 }
 
 void msm_dp_display_atomic_disable(struct msm_dp *dp)

-- 
2.56.0


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

  parent reply	other threads:[~2026-10-09  3:18 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-09  3:15 [PATCH v2 00/20] drm/msm/dp: Add static HDR support for DP and eDP Xilin Wu
2026-10-09  3:15 ` [PATCH v2 01/20] drm/atomic: Handle max bpc properties before connector state allocation Xilin Wu
2026-10-10  2:48   ` Chaoyi Chen
2026-10-12 12:33   ` Dmitry Baryshkov
2026-10-09  3:15 ` [PATCH v2 02/20] drm/connector: Drop early state allocation for max bpc registration Xilin Wu
2026-10-10 22:44   ` Martin Blumenstingl
2026-10-09  3:15 ` [PATCH v2 03/20] drm/bridge-connector: Attach max bpc for non-HDMI bridges Xilin Wu
2026-10-10  2:39   ` Chaoyi Chen
2026-10-12 12:40   ` Dmitry Baryshkov
2026-10-09  3:15 ` [PATCH v2 04/20] drm/msm/dp: Accept a const SDP header when packing Xilin Wu
2026-10-09  3:15 ` [PATCH v2 05/20] drm/msm/dp: Support multiple generic SDP slots Xilin Wu
2026-10-09  3:15 ` [PATCH v2 06/20] drm/msm/dp: Keep runtime PM calls outside the connection lock Xilin Wu
2026-10-09  3:37   ` sashiko-bot
2026-10-09  3:15 ` [PATCH v2 07/20] drm/msm/dp: Serialize stream operations with HPD processing Xilin Wu
2026-10-09  3:30   ` sashiko-bot
2026-10-12 12:48   ` Dmitry Baryshkov
2026-10-09  3:16 ` [PATCH v2 08/20] drm/msm/dp: Track PHY power ownership Xilin Wu
2026-10-09  3:16 ` [PATCH v2 09/20] drm/msm/dp: Unwind resources when enabling a stream fails Xilin Wu
2026-10-09  3:35   ` sashiko-bot
2026-10-09  3:16 ` Xilin Wu [this message]
2026-10-09  3:28   ` [PATCH v2 10/20] drm/msm/dp: Report stream enable failures through link status sashiko-bot
2026-10-09  3:16 ` [PATCH v2 11/20] drm/msm/dp: Cache eDP link capabilities after successful discovery Xilin Wu
2026-10-09  3:34   ` sashiko-bot
2026-10-30  4:29   ` Burke Cates
2026-10-09  3:16 ` [PATCH v2 12/20] drm/msm/dp: Rebuild the eDP stream on modesets leaving self refresh Xilin Wu
2026-10-09  3:16 ` [PATCH v2 13/20] drm/msm/dp: Track output bit depth in bridge atomic state Xilin Wu
2026-10-09  3:16 ` [PATCH v2 14/20] drm/msm/dp: Clear stale MSA colorimetry bits Xilin Wu
2026-10-12  8:00   ` Konrad Dybcio
2026-10-09  3:16 ` [PATCH v2 15/20] drm/msm/dp: Flush VSC updates when leaving YUV420 Xilin Wu
2026-10-12 14:09   ` Dmitry Baryshkov
2026-10-09  3:16 ` [PATCH v2 16/20] drm/msm/dp: Disable PSR for YUV420 streams Xilin Wu
2026-10-09  3:34   ` sashiko-bot
2026-10-12 14:36   ` Dmitry Baryshkov
2026-10-09  3:16 ` [PATCH v2 17/20] drm/msm/dp: Track VSC packets in bridge atomic state Xilin Wu
2026-10-09  3:34   ` sashiko-bot
2026-10-09  3:16 ` [PATCH v2 18/20] drm/msm/dp: Signal BT.2020 RGB on DP and eDP Xilin Wu
2026-10-12 14:48   ` Dmitry Baryshkov
2026-10-09  3:16 ` [PATCH v2 19/20] drm/msm/dp: Serialize video test state changes Xilin Wu
2026-10-09  3:44   ` sashiko-bot
2026-10-12 21:52   ` Dmitry Baryshkov
2026-10-09  3:16 ` [PATCH v2 20/20] drm/msm/dp: Add static HDR metadata support for DP and eDP Xilin Wu
2026-10-09  3:40   ` sashiko-bot

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=20261009-msm-dp-hdr10-v2-10-1835d4966da3@radxa.com \
    --to=sophon@radxa.com \
    --cc=Laurent.pinchart@ideasonboard.com \
    --cc=abhinav.kumar@linux.dev \
    --cc=airlied@gmail.com \
    --cc=andrzej.hajda@intel.com \
    --cc=dragon@radxa.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=freedreno@lists.freedesktop.org \
    --cc=jbrunet@baylibre.com \
    --cc=jernej.skrabec@gmail.com \
    --cc=jesszhan0024@gmail.com \
    --cc=jonas@kwiboo.se \
    --cc=khilman@baylibre.com \
    --cc=linux-amlogic@lists.infradead.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luca.ceresoli@bootlin.com \
    --cc=lumag@kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=marijn.suijten@somainline.org \
    --cc=martin.blumenstingl@googlemail.com \
    --cc=mripard@kernel.org \
    --cc=neil.armstrong@linaro.org \
    --cc=rfoss@kernel.org \
    --cc=robin.clark@oss.qualcomm.com \
    --cc=sean@poorly.run \
    --cc=simona@ffwll.ch \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®