[PATCH v6 24/26] drm/bridge: panel: use dynamic lifetime management

Luca Ceresoli
2025-02-06T18:15:43Z

Allow this bridge to be removable without dangling pointers and
use-after-free, together with proper use of drm_bridge_get() and _put() by
consumers.

Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>

---

Changed in v6:
- Update to use devm_drm_bridge_alloc(), remove .destroy
- Update the *_of_get_bridge() functions to put instead of kfree on
devm/drmm events

This patch was added in v5.
---
drivers/gpu/drm/bridge/panel.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
index 3c0e22e61c1092de1571d800ac440aad7b5c86bc..5950c752ff2469f7e5c28f9d5833141551b98227 100644
--- a/drivers/gpu/drm/bridge/panel.c
+++ b/drivers/gpu/drm/bridge/panel.c
@@ -912,15 +912,14 @@ struct drm_bridge *drm_panel_bridge_add_typed(struct drm_panel *panel,
if (!panel)
return ERR_PTR(-EINVAL);

- panel_bridge = devm_kzalloc(panel->dev, sizeof(*panel_bridge),
- GFP_KERNEL);
- if (!panel_bridge)
- return ERR_PTR(-ENOMEM);
+ panel_bridge = devm_drm_bridge_alloc(panel->dev, struct panel_bridge, bridge,
+ &panel_bridge_bridge_funcs);
+ if (IS_ERR(panel_bridge))
+ return (void *)panel_bridge;

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;
@@ -939,8 +938,6 @@ EXPORT_SYMBOL(drm_panel_bridge_add_typed);
*/
void drm_panel_bridge_remove(struct drm_bridge *bridge)
{
- struct panel_bridge *panel_bridge;
-
if (!bridge)
return;

@@ -949,10 +946,7 @@ void drm_panel_bridge_remove(struct drm_bridge *bridge)
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