]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/dp_mst: Verify request type in the corresponding down message reply
authorImre Deak <imre.deak@intel.com>
Tue, 3 Dec 2024 16:02:18 +0000 (18:02 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jan 2025 12:28:41 +0000 (13:28 +0100)
[ Upstream commit 4d49e77a973d3b5d1881663c3f122906a0702940 ]

After receiving the response for an MST down request message, the
response should be accepted/parsed only if the response type matches
that of the request. Ensure this by checking if the request type code
stored both in the request and the reply match, dropping the reply in
case of a mismatch.

This fixes the topology detection for an MST hub, as described in the
Closes link below, where the hub sends an incorrect reply message after
a CLEAR_PAYLOAD_TABLE -> LINK_ADDRESS down request message sequence.

Cc: Lyude Paul <lyude@redhat.com>
Cc: <stable@vger.kernel.org>
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/12804
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241203160223.2926014-3-imre.deak@intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/drm_dp_mst_topology.c

index f72b4ff169a8de0d6659e33f8cb6ff1bab1dde36..86e1a61b6b6df3380520f654c233eb501e561c8d 100644 (file)
@@ -3993,6 +3993,34 @@ drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
        return true;
 }
 
+static int get_msg_request_type(u8 data)
+{
+       return data & 0x7f;
+}
+
+static bool verify_rx_request_type(struct drm_dp_mst_topology_mgr *mgr,
+                                  const struct drm_dp_sideband_msg_tx *txmsg,
+                                  const struct drm_dp_sideband_msg_rx *rxmsg)
+{
+       const struct drm_dp_sideband_msg_hdr *hdr = &rxmsg->initial_hdr;
+       const struct drm_dp_mst_branch *mstb = txmsg->dst;
+       int tx_req_type = get_msg_request_type(txmsg->msg[0]);
+       int rx_req_type = get_msg_request_type(rxmsg->msg[0]);
+       char rad_str[64];
+
+       if (tx_req_type == rx_req_type)
+               return true;
+
+       drm_dp_mst_rad_to_str(mstb->rad, mstb->lct, rad_str, sizeof(rad_str));
+       drm_dbg_kms(mgr->dev,
+                   "Got unexpected MST reply, mstb: %p seqno: %d lct: %d rad: %s rx_req_type: %s (%02x) != tx_req_type: %s (%02x)\n",
+                   mstb, hdr->seqno, mstb->lct, rad_str,
+                   drm_dp_mst_req_type_str(rx_req_type), rx_req_type,
+                   drm_dp_mst_req_type_str(tx_req_type), tx_req_type);
+
+       return false;
+}
+
 static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
 {
        struct drm_dp_sideband_msg_tx *txmsg;
@@ -4022,6 +4050,9 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
                goto out_clear_reply;
        }
 
+       if (!verify_rx_request_type(mgr, txmsg, msg))
+               goto out_clear_reply;
+
        drm_dp_sideband_parse_reply(mgr, msg, &txmsg->reply);
 
        if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) {