Commit 16194958 authored by Johan Hovold's avatar Johan Hovold Committed by Abhinav Kumar

drm/msm/dp: fix bridge lifetime

Device-managed resources allocated post component bind must be tied to
the lifetime of the aggregate DRM device or they will not necessarily be
released when binding of the aggregate device is deferred.

This can lead resource leaks or failure to bind the aggregate device
when binding is later retried and a second attempt to allocate the
resources is made.

For the DP bridges, previously allocated bridges will leak on probe
deferral.

Fix this by amending the DP parser interface and tying the lifetime of
the bridge device to the DRM device rather than DP platform device.

Fixes: c3bf8e21 ("drm/msm/dp: Add eDP support via aux_bus")
Cc: stable@vger.kernel.org      # 5.19
Reviewed-by: default avatarDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: default avatarJohan Hovold <johan+linaro@kernel.org>
Tested-by: default avatarKuogee Hsieh <quic_khsieh@quicinc.com>
Reviewed-by: default avatarKuogee Hsieh <quic_khsieh@quicinc.com>
Patchwork: https://patchwork.freedesktop.org/patch/502667/
Link: https://lore.kernel.org/r/20220913085320.8577-8-johan+linaro@kernel.orgSigned-off-by: default avatarAbhinav Kumar <quic_abhinavk@quicinc.com>
parent 2b57f726
...@@ -1579,7 +1579,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp) ...@@ -1579,7 +1579,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
* For DisplayPort interfaces external bridges are optional, so * For DisplayPort interfaces external bridges are optional, so
* silently ignore an error if one is not present (-ENODEV). * silently ignore an error if one is not present (-ENODEV).
*/ */
rc = dp_parser_find_next_bridge(dp_priv->parser); rc = devm_dp_parser_find_next_bridge(dp->drm_dev->dev, dp_priv->parser);
if (!dp->is_edp && rc == -ENODEV) if (!dp->is_edp && rc == -ENODEV)
return 0; return 0;
......
...@@ -240,12 +240,12 @@ static int dp_parser_clock(struct dp_parser *parser) ...@@ -240,12 +240,12 @@ static int dp_parser_clock(struct dp_parser *parser)
return 0; return 0;
} }
int dp_parser_find_next_bridge(struct dp_parser *parser) int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser)
{ {
struct device *dev = &parser->pdev->dev; struct platform_device *pdev = parser->pdev;
struct drm_bridge *bridge; struct drm_bridge *bridge;
bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); bridge = devm_drm_of_get_bridge(dev, pdev->dev.of_node, 1, 0);
if (IS_ERR(bridge)) if (IS_ERR(bridge))
return PTR_ERR(bridge); return PTR_ERR(bridge);
......
...@@ -138,8 +138,9 @@ struct dp_parser { ...@@ -138,8 +138,9 @@ struct dp_parser {
struct dp_parser *dp_parser_get(struct platform_device *pdev); struct dp_parser *dp_parser_get(struct platform_device *pdev);
/** /**
* dp_parser_find_next_bridge() - find an additional bridge to DP * devm_dp_parser_find_next_bridge() - find an additional bridge to DP
* *
* @dev: device to tie bridge lifetime to
* @parser: dp_parser data from client * @parser: dp_parser data from client
* *
* This function is used to find any additional bridge attached to * This function is used to find any additional bridge attached to
...@@ -147,6 +148,6 @@ struct dp_parser *dp_parser_get(struct platform_device *pdev); ...@@ -147,6 +148,6 @@ struct dp_parser *dp_parser_get(struct platform_device *pdev);
* *
* Return: 0 if able to get the bridge, otherwise negative errno for failure. * Return: 0 if able to get the bridge, otherwise negative errno for failure.
*/ */
int dp_parser_find_next_bridge(struct dp_parser *parser); int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment