aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_dp_mst_topology.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_dp_mst_topology.c')
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index bfd237c15e76..ae5f06895562 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -330,6 +330,13 @@ static bool drm_dp_sideband_msg_build(struct drm_dp_sideband_msg_rx *msg,
330 return false; 330 return false;
331 } 331 }
332 332
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
333 /* get length contained in this portion */ 340 /* get length contained in this portion */
334 msg->curchunk_len = recv_hdr.msg_len; 341 msg->curchunk_len = recv_hdr.msg_len;
335 msg->curchunk_hdrlen = hdrlen; 342 msg->curchunk_hdrlen = hdrlen;
@@ -2164,7 +2171,7 @@ out_unlock:
2164} 2171}
2165EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume); 2172EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
2166 2173
2167static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) 2174static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
2168{ 2175{
2169 int len; 2176 int len;
2170 u8 replyblock[32]; 2177 u8 replyblock[32];
@@ -2179,12 +2186,12 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
2179 replyblock, len); 2186 replyblock, len);
2180 if (ret != len) { 2187 if (ret != len) {
2181 DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret); 2188 DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret);
2182 return; 2189 return false;
2183 } 2190 }
2184 ret = drm_dp_sideband_msg_build(msg, replyblock, len, true); 2191 ret = drm_dp_sideband_msg_build(msg, replyblock, len, true);
2185 if (!ret) { 2192 if (!ret) {
2186 DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]); 2193 DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]);
2187 return; 2194 return false;
2188 } 2195 }
2189 replylen = msg->curchunk_len + msg->curchunk_hdrlen; 2196 replylen = msg->curchunk_len + msg->curchunk_hdrlen;
2190 2197
@@ -2196,21 +2203,32 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
2196 ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply, 2203 ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply,
2197 replyblock, len); 2204 replyblock, len);
2198 if (ret != len) { 2205 if (ret != len) {
2199 DRM_DEBUG_KMS("failed to read a chunk\n"); 2206 DRM_DEBUG_KMS("failed to read a chunk (len %d, ret %d)\n",
2207 len, ret);
2208 return false;
2200 } 2209 }
2210
2201 ret = drm_dp_sideband_msg_build(msg, replyblock, len, false); 2211 ret = drm_dp_sideband_msg_build(msg, replyblock, len, false);
2202 if (ret == false) 2212 if (!ret) {
2203 DRM_DEBUG_KMS("failed to build sideband msg\n"); 2213 DRM_DEBUG_KMS("failed to build sideband msg\n");
2214 return false;
2215 }
2216
2204 curreply += len; 2217 curreply += len;
2205 replylen -= len; 2218 replylen -= len;
2206 } 2219 }
2220 return true;
2207} 2221}
2208 2222
2209static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) 2223static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
2210{ 2224{
2211 int ret = 0; 2225 int ret = 0;
2212 2226
2213 drm_dp_get_one_sb_msg(mgr, false); 2227 if (!drm_dp_get_one_sb_msg(mgr, false)) {
2228 memset(&mgr->down_rep_recv, 0,
2229 sizeof(struct drm_dp_sideband_msg_rx));
2230 return 0;
2231 }
2214 2232
2215 if (mgr->down_rep_recv.have_eomt) { 2233 if (mgr->down_rep_recv.have_eomt) {
2216 struct drm_dp_sideband_msg_tx *txmsg; 2234 struct drm_dp_sideband_msg_tx *txmsg;
@@ -2266,7 +2284,12 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
2266static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) 2284static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
2267{ 2285{
2268 int ret = 0; 2286 int ret = 0;
2269 drm_dp_get_one_sb_msg(mgr, true); 2287
2288 if (!drm_dp_get_one_sb_msg(mgr, true)) {
2289 memset(&mgr->up_req_recv, 0,
2290 sizeof(struct drm_dp_sideband_msg_rx));
2291 return 0;
2292 }
2270 2293
2271 if (mgr->up_req_recv.have_eomt) { 2294 if (mgr->up_req_recv.have_eomt) {
2272 struct drm_dp_sideband_msg_req_body msg; 2295 struct drm_dp_sideband_msg_req_body msg;
@@ -2318,7 +2341,9 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
2318 DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn); 2341 DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
2319 } 2342 }
2320 2343
2321 drm_dp_put_mst_branch_device(mstb); 2344 if (mstb)
2345 drm_dp_put_mst_branch_device(mstb);
2346
2322 memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx)); 2347 memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
2323 } 2348 }
2324 return ret; 2349 return ret;