[v4,20/20] drm/bridge_connector: Convert to atomic_create_state
Commit Message
The connector created by drm_bridge_connector only initializes a
pristine state in reset, which is equivalent to what
atomic_create_state would expect. Convert to it.
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
drivers/gpu/drm/display/drm_bridge_connector.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
Comments
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Removing the `.reset` hook from `drm_bridge_connector_funcs` causes a guaranteed NULL pointer dereference and kernel panic during HDMI bridge initialization in `drmm_connector_hdmi_init()`.
--
commit 4d1b1d55e3ba2c5d7992c514db2a00581120fa32
Author: Maxime Ripard <mripard@kernel.org>
drm/bridge_connector: Convert to atomic_create_state
This commit converts the drm_bridge_connector to use atomic_create_state
instead of reset to initialize its state. It removes the reset hook from
drm_bridge_connector_funcs and replaces it with atomic_create_state.
> diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c
> index 50408af746d84..cafa498c38482 100644
> --- a/drivers/gpu/drm/display/drm_bridge_connector.c
> +++ b/drivers/gpu/drm/display/drm_bridge_connector.c
[ ... ]
> @@ -265,22 +265,29 @@ static void drm_bridge_connector_debugfs_init(struct drm_connector *connector,
> static const struct drm_connector_funcs drm_bridge_connector_funcs = {
> - .reset = drm_bridge_connector_reset,
Does removing the reset hook cause a null pointer dereference regression
during HDMI bridge initialization?
When an HDMI bridge is present, drm_bridge_connector_init() delegates setup
to drmm_connector_hdmi_init(). Looking at drmm_connector_hdmi_init(), it
expects to allocate and initialize the connector's state by calling its
reset hook:
drmm_connector_hdmi_init() {
...
if (connector->funcs->reset)
connector->funcs->reset(connector);
...
}
Since the reset hook is removed here, the state allocation is skipped,
leaving connector->state as null.
Immediately after this, drmm_connector_hdmi_init() calls
drm_connector_attach_max_bpc_property(), which unconditionally dereferences
connector->state:
drm_connector_attach_max_bpc_property() {
...
connector->state->max_requested_bpc = max;
connector->state->max_bpc = max;
...
}
Could this lead to a crash when an HDMI bridge connector is initialized?
> .detect = drm_bridge_connector_detect,
> .force = drm_bridge_connector_force,
> .fill_modes = drm_helper_probe_single_connector_modes,
> + .atomic_create_state = drm_bridge_connector_create_state,
> .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> .debugfs_init = drm_bridge_connector_debugfs_init,
@@ -263,26 +263,33 @@ static void drm_bridge_connector_debugfs_init(struct drm_connector *connector,
if (bridge->funcs->debugfs_init)
bridge->funcs->debugfs_init(bridge, root);
}
}
-static void drm_bridge_connector_reset(struct drm_connector *connector)
+static struct drm_connector_state *
+drm_bridge_connector_create_state(struct drm_connector *connector)
{
struct drm_bridge_connector *bridge_connector =
to_drm_bridge_connector(connector);
+ struct drm_connector_state *conn_state;
+
+ conn_state = drm_atomic_helper_connector_create_state(connector);
+ if (IS_ERR(conn_state))
+ return conn_state;
- drm_atomic_helper_connector_reset(connector);
if (bridge_connector->bridge_hdmi)
__drm_atomic_helper_connector_hdmi_state_init(connector,
- connector->state);
+ conn_state);
+
+ return conn_state;
}
static const struct drm_connector_funcs drm_bridge_connector_funcs = {
- .reset = drm_bridge_connector_reset,
.detect = drm_bridge_connector_detect,
.force = drm_bridge_connector_force,
.fill_modes = drm_helper_probe_single_connector_modes,
+ .atomic_create_state = drm_bridge_connector_create_state,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
.debugfs_init = drm_bridge_connector_debugfs_init,
.oob_hotplug_event = drm_bridge_connector_oob_hotplug_event,
};