From 1d985ddabbe0ab73e34d128fdcc26b8ed05a9328 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 12 Dec 2024 01:03:18 +0200 Subject: drm/connector: Add a way to init/add a connector in separate steps Atm when the connector is added to the drm_mode_config::connector_list, the connector may not be fully initialized yet. This is not a problem for static connectors initialized/added during driver loading, for which the driver ensures that look-ups via the above list are not possible until all the connector and other required state is fully initialized already. It's also not a problem for user space looking up either a static or dynamic (see what this is below) connector, since this will be only possible once the connector is registered. A dynamic - atm only a DP MST - connector can be initialized and added after the load time initialization is done. Such a connector may be looked up by in-kernel users once it's added to the connector list. In particular a hotplug handler could perform a detection on all the connectors on the list and hence find a connector there which isn't yet initialized. For instance the connector's helper hooks may be unset, leading to a NULL dereference while the detect helper calls the connector's drm_connector_helper_funcs::detect() or detect_ctx() handler. To resolve the above issue, add a way for dynamic connectors to separately initialize the DRM core specific parts of the connector without adding it to the connector list - by calling the new drm_connector_dynamic_init() - and to add the connector to the list later once all the initialization is complete and the connector is registered - by calling the new drm_connector_dynamic_register(). Adding the above 2 functions was also motivated to make the distinction of the interface between static and dynamic connectors clearer: Drivers should manually initialize and register only dynamic connectors (with the above 2 functions). A driver should only initialize a static connector (with one of the drm_connector_init*, drmm_connector_init* functions) while the registration of the connector will be done automatically by DRM core. v2: (Jani) - Let initing DDC as well via drm_connector_init_core(). - Rename __drm_connector_init to drm_connector_init_core_and_add(). v3: - Rename drm_connector_init_core() to drm_connector_dynamic_init(). (Sima) - Instead of exporting drm_connector_add(), move adding the connector to the registration step via a new drm_connector_dynamic_register(). (Sima) - Update drm_connector_dynamic_init()'s function documentation and the commit log according to the above changes. - Update the commit log describing the problematic scenario during connector detection. (Maxime) Cc: Jani Nikula Cc: Simona Vetter Cc: Maxime Ripard Reviewed-by: Rodrigo Vivi (v1) Reviewed-by: Lyude Paul Reviewed-by: Jani Nikula Reviewed-by: Maxime Ripard Acked-by: Alex Deucher Acked-by: Wayne Lin Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20241211230328.4012496-2-imre.deak@intel.com --- include/drm/drm_connector.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 1e2b25e204cb..d1be19242a5c 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -2129,6 +2129,11 @@ int drm_connector_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type); +int drm_connector_dynamic_init(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type, + struct i2c_adapter *ddc); int drm_connector_init_with_ddc(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, @@ -2150,6 +2155,7 @@ int drmm_connector_hdmi_init(struct drm_device *dev, unsigned int max_bpc); void drm_connector_attach_edid_property(struct drm_connector *connector); int drm_connector_register(struct drm_connector *connector); +int drm_connector_dynamic_register(struct drm_connector *connector); void drm_connector_unregister(struct drm_connector *connector); int drm_connector_attach_encoder(struct drm_connector *connector, struct drm_encoder *encoder); -- cgit v1.2.3