Bring in some DisplayPort MST changes from linux-4.4.y/4.4.79 --
commit 4ca0f3730e2734f67e648b2b4f12b66673e995e1 Author: Imre Deak <imre.d...@intel.com> Date: Wed Jul 19 16:46:32 2017 +0300 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 <airl...@redhat.com> Cc: Lyude <ly...@redhat.com> Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Signed-off-by: Imre Deak <imre.d...@intel.com> Reviewed-by: Lyude <ly...@redhat.com> Signed-off-by: Daniel Vetter <daniel.vet...@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20170719134632.13366-1-imre.d...@intel.com Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org> drivers/gpu/drm/drm_dp_mst_topology.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) commit 3d26e2ed7c8b4b1a0d9406fef7f3b5d6309fba49 Author: Imre Deak <imre.d...@intel.com> Date: Wed Jul 19 14:43:29 2017 +0300 drm/mst: Avoid dereferencing a NULL mstb in drm_dp_mst_handle_up_req() commit 7f8b3987da54cb4d41ad2545cd4d7958b9a36bdf upstream. In case of an unknown broadcast message is sent mstb will remain unset, so check for this. Cc: Dave Airlie <airl...@redhat.com> Cc: Lyude <ly...@redhat.com> Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Signed-off-by: Imre Deak <imre.d...@intel.com> Reviewed-by: Lyude <ly...@redhat.com> Signed-off-by: Daniel Vetter <daniel.vet...@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20170719114330.26540-3-imre.d...@intel.com Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org> drivers/gpu/drm/drm_dp_mst_topology.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 3383334a6cf38af6843793e343c95081b02773f1 Author: Imre Deak <imre.d...@intel.com> Date: Wed Jul 19 14:43:28 2017 +0300 drm/mst: Fix error handling during MST sideband message reception commit 448421b5e93b9177c5698f0cf6f5e72d2995eeca upstream. Handle any error due to partial reads, timeouts etc. to avoid parsing uninitialized data subsequently. Also bail out if the parsing itself fails. Cc: Dave Airlie <airl...@redhat.com> Cc: Lyude <ly...@redhat.com> Cc: Daniel Vetter <daniel.vet...@ffwll.ch> Signed-off-by: Imre Deak <imre.d...@intel.com> Reviewed-by: Lyude <ly...@redhat.com> Signed-off-by: Daniel Vetter <daniel.vet...@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20170719114330.26540-2-imre.d...@intel.com Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org> drivers/gpu/drm/drm_dp_mst_topology.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) Index: drm_dp_mst_topology.c =================================================================== RCS file: /cvs/src/sys/dev/pci/drm/drm_dp_mst_topology.c,v retrieving revision 1.2 diff -u -p -r1.2 drm_dp_mst_topology.c --- drm_dp_mst_topology.c 14 Jul 2017 11:18:04 -0000 1.2 +++ drm_dp_mst_topology.c 13 Aug 2017 12:04:47 -0000 @@ -334,6 +334,13 @@ static bool drm_dp_sideband_msg_build(st return false; } + /* + * ignore out-of-order messages or messages that are part of a + * failed transaction + */ + if (!recv_hdr.somt && !msg->have_somt) + return false; + /* get length contained in this portion */ msg->curchunk_len = recv_hdr.msg_len; msg->curchunk_hdrlen = hdrlen; @@ -2167,7 +2174,7 @@ out_unlock: } EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume); -static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) +static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) { int len; u8 replyblock[32]; @@ -2182,12 +2189,12 @@ static void drm_dp_get_one_sb_msg(struct replyblock, len); if (ret != len) { DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret); - return; + return false; } ret = drm_dp_sideband_msg_build(msg, replyblock, len, true); if (!ret) { DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]); - return; + return false; } replylen = msg->curchunk_len + msg->curchunk_hdrlen; @@ -2199,21 +2206,32 @@ static void drm_dp_get_one_sb_msg(struct ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply, replyblock, len); if (ret != len) { - DRM_DEBUG_KMS("failed to read a chunk\n"); + DRM_DEBUG_KMS("failed to read a chunk (len %d, ret %d)\n", + len, ret); + return false; } + ret = drm_dp_sideband_msg_build(msg, replyblock, len, false); - if (ret == false) + if (!ret) { DRM_DEBUG_KMS("failed to build sideband msg\n"); + return false; + } + curreply += len; replylen -= len; } + return true; } static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) { int ret = 0; - drm_dp_get_one_sb_msg(mgr, false); + if (!drm_dp_get_one_sb_msg(mgr, false)) { + memset(&mgr->down_rep_recv, 0, + sizeof(struct drm_dp_sideband_msg_rx)); + return 0; + } if (mgr->down_rep_recv.have_eomt) { struct drm_dp_sideband_msg_tx *txmsg; @@ -2269,7 +2287,12 @@ static int drm_dp_mst_handle_down_rep(st static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) { int ret = 0; - drm_dp_get_one_sb_msg(mgr, true); + + if (!drm_dp_get_one_sb_msg(mgr, true)) { + memset(&mgr->up_req_recv, 0, + sizeof(struct drm_dp_sideband_msg_rx)); + return 0; + } if (mgr->up_req_recv.have_eomt) { struct drm_dp_sideband_msg_req_body msg; @@ -2321,7 +2344,9 @@ static int drm_dp_mst_handle_up_req(stru DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn); } - drm_dp_put_mst_branch_device(mstb); + if (mstb) + drm_dp_put_mst_branch_device(mstb); + memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); } return ret;