diff options
Diffstat (limited to 'drivers/gpu/drm/drm_dp_mst_topology.c')
-rw-r--r-- | drivers/gpu/drm/drm_dp_mst_topology.c | 41 |
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 | } |
2165 | EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume); | 2172 | EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume); |
2166 | 2173 | ||
2167 | static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up) | 2174 | static 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 | ||
2209 | static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr) | 2223 | static 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) | |||
2266 | static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) | 2284 | static 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; |