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.ceres...@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

Reply via email to