Currently, drm_helper_probe_single_connector_modes() holds
connection_mutex while it probes and prunes connector->modes, then drops
it before sorting the list and filling in the crtc_* fields of each
mode. The caller still holds mode_config.mutex at that point, but
drm_atomic_check_only() never takes it. The only lock it holds on the
connector is connection_mutex, which drm_atomic_get_connector_state()
takes for it
amdgpu walks connector->modes from its atomic_check, in
create_stream_for_sink() and amdgpu_dm_get_highest_refresh_rate_mode(),
holding only the locks of the atomic acquire context. list_sort()
NULL-terminates the list while it runs, so that walk can follow a NULL
next pointer or read a mode whose crtc_* fields are being rewritten
Sort the list and set crtcinfo before dropping the locks, as the
function already does when it probes and prunes the modes. As far as I
can tell, the unlock ended up in front of the sort when
commit 6c5ed5ae353c ("drm/atomic: Acquire connection_mutex lock in
drm_helper_probe_single_connector_modes, v4.")
first took connection_mutex here, and that commit gives no reason for
the order
Signed-off-by: Hugo Sales <[email protected]>
---
drivers/gpu/drm/drm_probe_helper.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/drm_probe_helper.c
b/drivers/gpu/drm/drm_probe_helper.c
index 856b40fdaac4a..2085d93651b21 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -703,11 +703,10 @@ int drm_helper_probe_single_connector_modes(struct
drm_connector *connector,
}
exit:
- drm_modeset_drop_locks(&ctx);
- drm_modeset_acquire_fini(&ctx);
-
- if (list_empty(&connector->modes))
- return 0;
+ if (list_empty(&connector->modes)) {
+ count = 0;
+ goto unlock;
+ }
drm_mode_sort(&connector->modes);
@@ -720,6 +719,10 @@ int drm_helper_probe_single_connector_modes(struct
drm_connector *connector,
DRM_MODE_ARG(mode));
}
+unlock:
+ drm_modeset_drop_locks(&ctx);
+ drm_modeset_acquire_fini(&ctx);
+
return count;
}
EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
--
2.56.0