--- a/sys/dev/drm/drm_dp_mst_topology.c 2026-09-16 21:03:55.846742995 +0000 +++ b/sys/dev/drm/drm_dp_mst_topology.c 2026-09-16 21:04:11.754541465 +0000 @@ -2320,6 +2355,7 @@ if (mgr->down_rep_recv.have_eomt) { struct drm_dp_sideband_msg_tx *txmsg; struct drm_dp_mst_branch *mstb; + struct drm_dp_sideband_msg_reply_body reply; int slot = -1; mstb = drm_dp_get_mst_branch_device(mgr, mgr->down_rep_recv.initial_hdr.lct, @@ -2350,19 +2386,33 @@ return 0; } - drm_dp_sideband_parse_reply(&mgr->down_rep_recv, &txmsg->reply); - if (txmsg->reply.reply_type == 1) { - DRM_DEBUG_KMS("Got NAK reply: req 0x%02x, reason 0x%02x, nak data 0x%02x\n", txmsg->reply.req_type, txmsg->reply.u.nak.reason, txmsg->reply.u.nak.nak_data); + /* + * Parse into a local body: the sender can time out in + * drm_dp_mst_wait_tx_reply() and kfree(txmsg) while we are + * outside qlock. txmsg is only written below, after slot + * ownership has been re-validated under qlock. + */ + drm_dp_sideband_parse_reply(&mgr->down_rep_recv, &reply); + if (reply.reply_type == 1) { + DRM_DEBUG_KMS("Got NAK reply: req 0x%02x, reason 0x%02x, nak data 0x%02x\n", reply.req_type, reply.u.nak.reason, reply.u.nak.nak_data); } memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); - drm_dp_put_mst_branch_device(mstb); mutex_lock(&mgr->qlock); - txmsg->state = DRM_DP_SIDEBAND_TX_RX; - mstb->tx_slots[slot] = NULL; + if (mstb->tx_slots[slot] == txmsg) { + /* sender has not taken the timeout path yet */ + txmsg->reply = reply; + txmsg->state = DRM_DP_SIDEBAND_TX_RX; + mstb->tx_slots[slot] = NULL; + } else { + DRM_DEBUG_KMS("reply raced with tx timeout, dropped\n"); + } mutex_unlock(&mgr->qlock); + /* mstb reference held until after its last use above */ + drm_dp_put_mst_branch_device(mstb); + wake_up_all(&mgr->tx_waitq); } return ret;