Skip to content

Commit 12d8f31

Browse files
committed
drm/dp_mst: Fix locking when skipping CSN before topology probing
The handling of the MST Connection Status Notify message is skipped if the probing of the topology is still pending. Acquiring the drm_dp_mst_topology_mgr::probe_lock for this in drm_dp_mst_handle_up_req() is problematic: the task/work this function is called from is also responsible for handling MST down-request replies (in drm_dp_mst_handle_down_rep()). Thus drm_dp_mst_link_probe_work() - holding already probe_lock - could be blocked waiting for an MST down-request reply while drm_dp_mst_handle_up_req() is waiting for probe_lock while processing a CSN message. This leads to the probe work's down-request message timing out. A scenario similar to the above leading to a down-request timeout is handling a CSN message in drm_dp_mst_handle_conn_stat(), holding the probe_lock and sending down-request messages while a second CSN message sent by the sink subsequently is handled by drm_dp_mst_handle_up_req(). Fix the above by moving the logic to skip the CSN handling to drm_dp_mst_process_up_req(). This function is called from a work (separate from the task/work handling new up/down messages), already holding probe_lock. This solves the above timeout issue, since handling of down-request replies won't be blocked by probe_lock. Fixes: ddf9834 ("drm/dp_mst: Skip CSN if topology probing is not done yet") Cc: Wayne Lin <Wayne.Lin@amd.com> Cc: Lyude Paul <lyude@redhat.com> Cc: stable@vger.kernel.org # v6.6+ Reviewed-by: Wayne Lin <Wayne.Lin@amd.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20250307183152.3822170-1-imre.deak@intel.com
1 parent de93ddf commit 12d8f31

File tree

1 file changed

+24
-16
lines changed

1 file changed

+24
-16
lines changed

drivers/gpu/drm/display/drm_dp_mst_topology.c

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4025,6 +4025,22 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
40254025
return 0;
40264026
}
40274027

4028+
static bool primary_mstb_probing_is_done(struct drm_dp_mst_topology_mgr *mgr)
4029+
{
4030+
bool probing_done = false;
4031+
4032+
mutex_lock(&mgr->lock);
4033+
4034+
if (mgr->mst_primary && drm_dp_mst_topology_try_get_mstb(mgr->mst_primary)) {
4035+
probing_done = mgr->mst_primary->link_address_sent;
4036+
drm_dp_mst_topology_put_mstb(mgr->mst_primary);
4037+
}
4038+
4039+
mutex_unlock(&mgr->lock);
4040+
4041+
return probing_done;
4042+
}
4043+
40284044
static inline bool
40294045
drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr,
40304046
struct drm_dp_pending_up_req *up_req)
@@ -4055,8 +4071,12 @@ drm_dp_mst_process_up_req(struct drm_dp_mst_topology_mgr *mgr,
40554071

40564072
/* TODO: Add missing handler for DP_RESOURCE_STATUS_NOTIFY events */
40574073
if (msg->req_type == DP_CONNECTION_STATUS_NOTIFY) {
4058-
dowork = drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat);
4059-
hotplug = true;
4074+
if (!primary_mstb_probing_is_done(mgr)) {
4075+
drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.\n");
4076+
} else {
4077+
dowork = drm_dp_mst_handle_conn_stat(mstb, &msg->u.conn_stat);
4078+
hotplug = true;
4079+
}
40604080
}
40614081

40624082
drm_dp_mst_topology_put_mstb(mstb);
@@ -4138,10 +4158,11 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
41384158
drm_dp_send_up_ack_reply(mgr, mst_primary, up_req->msg.req_type,
41394159
false);
41404160

4161+
drm_dp_mst_topology_put_mstb(mst_primary);
4162+
41414163
if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
41424164
const struct drm_dp_connection_status_notify *conn_stat =
41434165
&up_req->msg.u.conn_stat;
4144-
bool handle_csn;
41454166

41464167
drm_dbg_kms(mgr->dev, "Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n",
41474168
conn_stat->port_number,
@@ -4150,16 +4171,6 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
41504171
conn_stat->message_capability_status,
41514172
conn_stat->input_port,
41524173
conn_stat->peer_device_type);
4153-
4154-
mutex_lock(&mgr->probe_lock);
4155-
handle_csn = mst_primary->link_address_sent;
4156-
mutex_unlock(&mgr->probe_lock);
4157-
4158-
if (!handle_csn) {
4159-
drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.");
4160-
kfree(up_req);
4161-
goto out_put_primary;
4162-
}
41634174
} else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
41644175
const struct drm_dp_resource_status_notify *res_stat =
41654176
&up_req->msg.u.resource_stat;
@@ -4174,9 +4185,6 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
41744185
list_add_tail(&up_req->next, &mgr->up_req_list);
41754186
mutex_unlock(&mgr->up_req_lock);
41764187
queue_work(system_long_wq, &mgr->up_req_work);
4177-
4178-
out_put_primary:
4179-
drm_dp_mst_topology_put_mstb(mst_primary);
41804188
out_clear_reply:
41814189
reset_msg_rx_state(&mgr->up_req_recv);
41824190
return ret;

0 commit comments

Comments
 (0)