Skip to content

Commit 4ca0f37

Browse files
ideakgregkh
authored andcommitted
drm/mst: Avoid processing partially received up/down message transactions
commit 636c4c3e762b62aa93632c645ca65879285b16e3 upstream. Currently we may process up/down message transactions containing uninitialized data. This can happen if there was an error during the reception of any message in the transaction, but we happened to receive the last message correctly with the end-of-message flag set. To avoid this abort the reception of the transaction when the first error is detected, rejecting any messages until a message with the start-of-message flag is received (which will start a new transaction). This is also what the DP 1.4 spec 2.11.8.2 calls for in this case. In addtion this also prevents receiving bogus transactions without the first message with the the start-of-message flag set. v2: - unchanged v3: - git add the part that actually skips messages after an error in drm_dp_sideband_msg_build() Cc: Dave Airlie <airlied@redhat.com> Cc: Lyude <lyude@redhat.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Lyude <lyude@redhat.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20170719134632.13366-1-imre.deak@intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 3d26e2e commit 4ca0f37

1 file changed

Lines changed: 24 additions & 7 deletions

File tree

drivers/gpu/drm/drm_dp_mst_topology.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,13 @@ static bool drm_dp_sideband_msg_build(struct drm_dp_sideband_msg_rx *msg,
330330
return false;
331331
}
332332

333+
/*
334+
* ignore out-of-order messages or messages that are part of a
335+
* failed transaction
336+
*/
337+
if (!recv_hdr.somt && !msg->have_somt)
338+
return false;
339+
333340
/* get length contained in this portion */
334341
msg->curchunk_len = recv_hdr.msg_len;
335342
msg->curchunk_hdrlen = hdrlen;
@@ -2163,7 +2170,7 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr)
21632170
}
21642171
EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
21652172

2166-
static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
2173+
static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
21672174
{
21682175
int len;
21692176
u8 replyblock[32];
@@ -2178,12 +2185,12 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
21782185
replyblock, len);
21792186
if (ret != len) {
21802187
DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret);
2181-
return;
2188+
return false;
21822189
}
21832190
ret = drm_dp_sideband_msg_build(msg, replyblock, len, true);
21842191
if (!ret) {
21852192
DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]);
2186-
return;
2193+
return false;
21872194
}
21882195
replylen = msg->curchunk_len + msg->curchunk_hdrlen;
21892196

@@ -2197,25 +2204,30 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
21972204
if (ret != len) {
21982205
DRM_DEBUG_KMS("failed to read a chunk (len %d, ret %d)\n",
21992206
len, ret);
2200-
return;
2207+
return false;
22012208
}
22022209

22032210
ret = drm_dp_sideband_msg_build(msg, replyblock, len, false);
22042211
if (!ret) {
22052212
DRM_DEBUG_KMS("failed to build sideband msg\n");
2206-
return;
2213+
return false;
22072214
}
22082215

22092216
curreply += len;
22102217
replylen -= len;
22112218
}
2219+
return true;
22122220
}
22132221

22142222
static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
22152223
{
22162224
int ret = 0;
22172225

2218-
drm_dp_get_one_sb_msg(mgr, false);
2226+
if (!drm_dp_get_one_sb_msg(mgr, false)) {
2227+
memset(&mgr->down_rep_recv, 0,
2228+
sizeof(struct drm_dp_sideband_msg_rx));
2229+
return 0;
2230+
}
22192231

22202232
if (mgr->down_rep_recv.have_eomt) {
22212233
struct drm_dp_sideband_msg_tx *txmsg;
@@ -2271,7 +2283,12 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
22712283
static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
22722284
{
22732285
int ret = 0;
2274-
drm_dp_get_one_sb_msg(mgr, true);
2286+
2287+
if (!drm_dp_get_one_sb_msg(mgr, true)) {
2288+
memset(&mgr->up_req_recv, 0,
2289+
sizeof(struct drm_dp_sideband_msg_rx));
2290+
return 0;
2291+
}
22752292

22762293
if (mgr->up_req_recv.have_eomt) {
22772294
struct drm_dp_sideband_msg_req_body msg;

0 commit comments

Comments
 (0)