From 744f262401cc2e1f3827496c72a47e072d31a852 Mon Sep 17 00:00:00 2001 From: Xiao Lu Date: Sun, 20 Sep 2026 10:21:44 +0800 Subject: [PATCH] drm/dp/mst: reject DPCD read/write on ports with ddps=0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DP v2.1b specifies that REMOTE_DPCD_READ and REMOTE_DPCD_WRITE transactions should only be issued to downstream ports where ddps=1 (device plug status indicates a device is connected). Issuing these transactions to empty ports (ddps=0) is non-compliant and causes problems in practice: some MST hubs NAK the request, and all hubs introduce a delay waiting for the transaction to complete or fail before the driver can proceed, increasing link training latency. Guard drm_dp_mst_dpcd_read() and drm_dp_mst_dpcd_write() with a ddps check and return -EIO immediately for unoccupied ports. This avoids the spurious sideband transactions without changing connector lifetime semantics — connectors for all output ports are still created at enumeration time, regardless of ddps. Signed-off-by: Xiao Lu Changes in v2: - Instead of skipping connector creation for ddps=0 ports (v1), keep connectors around and guard DPCD transactions at the drm_dp_mst_dpcd_read/write level. This avoids changing connector lifetime semantics visible to userspace, per Lyude's review. Signed-off-by: Lyude Paul Link: https://patch.msgid.link/20260920022144.2209244-1-xiaolu.xie@intel.com --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 7ce9e212770a..b7fce0bf8acc 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -2161,6 +2161,9 @@ ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux, struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, aux); + if (!port->ddps) + return -EIO; + return drm_dp_send_dpcd_read(port->mgr, port, offset, size, buffer); } @@ -2184,6 +2187,9 @@ ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux, struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, aux); + if (!port->ddps) + return -EIO; + return drm_dp_send_dpcd_write(port->mgr, port, offset, size, buffer); }