Enable lifetime management of panel-bridge, so that other modules taking a pointer to a panel bridge can refcount it and avoid use-after-free in case the panel bridge is hot-unplugged. Signed-off-by: Luca Ceresoli <luca.ceresoli@xxxxxxxxxxx> --- This patch was added in v5. --- drivers/gpu/drm/bridge/panel.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 6e88339dec0f5faee690b7c53e8dcd0f1ee2281c..805809778f79f4519d9e31214cc5407357264da3 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -108,6 +108,11 @@ static void panel_bridge_detach(struct drm_bridge *bridge) drm_connector_cleanup(connector); } +static void panel_bridge_destroy(struct drm_bridge *bridge) +{ + kfree(drm_bridge_to_panel_bridge(bridge)); +} + static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { @@ -210,6 +215,7 @@ static void panel_bridge_debugfs_init(struct drm_bridge *bridge, static const struct drm_bridge_funcs panel_bridge_bridge_funcs = { .attach = panel_bridge_attach, .detach = panel_bridge_detach, + .destroy = panel_bridge_destroy, .atomic_pre_enable = panel_bridge_atomic_pre_enable, .atomic_enable = panel_bridge_atomic_enable, .atomic_disable = panel_bridge_atomic_disable, @@ -286,19 +292,22 @@ struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel, u32 connector_type) { struct panel_bridge *panel_bridge; + int err; if (!panel) return ERR_PTR(-EINVAL); - panel_bridge = devm_kzalloc(panel->dev, sizeof(*panel_bridge), - GFP_KERNEL); + panel_bridge = kzalloc(sizeof(*panel_bridge), GFP_KERNEL); if (!panel_bridge) return ERR_PTR(-ENOMEM); + err = drm_bridge_init(panel->dev, &panel_bridge->bridge, &panel_bridge_bridge_funcs); + if (err) + return ERR_PTR(err); + panel_bridge->connector_type = connector_type; panel_bridge->panel = panel; - panel_bridge->bridge.funcs = &panel_bridge_bridge_funcs; panel_bridge->bridge.of_node = panel->dev->of_node; panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES; panel_bridge->bridge.type = connector_type; @@ -317,18 +326,13 @@ EXPORT_SYMBOL(drm_panel_bridge_add_typed); */ void drm_panel_bridge_remove(struct drm_bridge *bridge) { - struct panel_bridge *panel_bridge; - if (!bridge) return; if (bridge->funcs != &panel_bridge_bridge_funcs) return; - panel_bridge = drm_bridge_to_panel_bridge(bridge); - drm_bridge_remove(bridge); - devm_kfree(panel_bridge->panel->dev, bridge); } EXPORT_SYMBOL(drm_panel_bridge_remove); -- 2.34.1