From ac236eb081e1050eace56685404cbcebd3525048 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Fri, 3 Mar 2023 03:46:57 -0500 Subject: [PATCH] Fix null pointer dereference in drm_dp_atomic_find_time_slots() The pointer returned by drm_atomic_get_old_connector_state() or drm_atomic_get_new_connector_state() may be NULL. Add checks to avoid crashing when it is. This patch makes it possible to use displays connected to a USB-C dock again with the amdgpu driver (broken since Linux 6.1). Signed-off-by: John Lindgren Fixes: a5c2c0d164e9 ("drm/display/dp_mst: Add nonblocking helpers for DP MST") Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2314 --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index ed96cfcfa30401..adf26776906bc2 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -4289,7 +4289,8 @@ int drm_dp_atomic_find_time_slots(struct drm_atomic_state *state, return PTR_ERR(topology_state); conn_state = drm_atomic_get_new_connector_state(state, port->connector); - topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc); + if (conn_state) + topology_state->pending_crtc_mask |= drm_crtc_mask(conn_state->crtc); /* Find the current allocation for this port, if any */ payload = drm_atomic_get_mst_payload_state(topology_state, port); @@ -4374,12 +4375,12 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, bool update_payload = true; old_conn_state = drm_atomic_get_old_connector_state(state, port->connector); - if (!old_conn_state->crtc) + if (old_conn_state && !old_conn_state->crtc) return 0; /* If the CRTC isn't disabled by this state, don't release it's payload */ new_conn_state = drm_atomic_get_new_connector_state(state, port->connector); - if (new_conn_state->crtc) { + if (new_conn_state && new_conn_state->crtc) { struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); @@ -4395,7 +4396,8 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, if (IS_ERR(topology_state)) return PTR_ERR(topology_state); - topology_state->pending_crtc_mask |= drm_crtc_mask(old_conn_state->crtc); + if (old_conn_state) + topology_state->pending_crtc_mask |= drm_crtc_mask(old_conn_state->crtc); if (!update_payload) return 0; @@ -4406,7 +4408,7 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, return -EINVAL; } - if (new_conn_state->crtc) + if (new_conn_state && new_conn_state->crtc) return 0; drm_dbg_atomic(mgr->dev, "[MST PORT:%p] TU %d -> 0\n", port, payload->time_slots);