It doesn't hurt to add the bridge in the global bridge list also for platform specific dw-hdmi drivers which are based on the component framework. This can be achieved by moving the drm_bridge_add() function call from dw_hdmi_probe() to __dw_hdmi_probe(). Moreover, putting the drm_bridge_add() function call prior to the interrupt registration and enablement ensures that the mutex hpd_mutex embedded in the structure drm_bridge can be initialized in drm_bridge_add() beforehand, which avoids accessing the uninitialized mutex in case people want to call function drm_bridge_hpd_notify() with the mutex locked internally to handle hot plug detection event in the interrupt handler dw_hdmi_irq().
Cc: Andrzej Hajda a.hajda@samsung.com Cc: Neil Armstrong narmstrong@baylibre.com Cc: Laurent Pinchart Laurent.pinchart@ideasonboard.com Cc: Jonas Karlman jonas@kwiboo.se Cc: Jernej Skrabec jernej.skrabec@siol.net Cc: David Airlie airlied@linux.ie Cc: Daniel Vetter daniel@ffwll.ch Cc: Boris Brezillon boris.brezillon@collabora.com Cc: Jerome Brunet jbrunet@baylibre.com Cc: Cheng-Yi Chiang cychiang@chromium.org Cc: Dariusz Marcinkiewicz darekm@google.com Cc: Archit Taneja architt@codeaurora.org Cc: Jose Abreu joabreu@synopsys.com Cc: dri-devel@lists.freedesktop.org Cc: NXP Linux Team linux-imx@nxp.com Signed-off-by: Liu Ying victor.liu@nxp.com --- Laurent,
I may see the uninitialized mutex accessing issue with i.MX dw-hdmi after applying your below patch set[1]. I think patch '[22/27] drm: bridge: dw-hdmi: Make connector creation optional' triggers the issue.
[1] https://patchwork.kernel.org/cover/11569709/
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 34 ++++++++++++++----------------- 1 file changed, 15 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index da84a91..4711700 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -3247,17 +3247,25 @@ __dw_hdmi_probe(struct platform_device *pdev,
dw_hdmi_init_hw(hdmi);
+ hdmi->bridge.driver_private = hdmi; + hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; +#ifdef CONFIG_OF + hdmi->bridge.of_node = pdev->dev.of_node; +#endif + + drm_bridge_add(&hdmi->bridge); + irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; - goto err_iahb; + goto err_irq; }
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq, dw_hdmi_irq, IRQF_SHARED, dev_name(dev), hdmi); if (ret) - goto err_iahb; + goto err_irq;
/* * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator @@ -3290,12 +3298,6 @@ __dw_hdmi_probe(struct platform_device *pdev, hdmi->ddc = NULL; }
- hdmi->bridge.driver_private = hdmi; - hdmi->bridge.funcs = &dw_hdmi_bridge_funcs; -#ifdef CONFIG_OF - hdmi->bridge.of_node = pdev->dev.of_node; -#endif - if (hdmi->version >= 0x200a) hdmi->connector.ycbcr_420_allowed = hdmi->plat_data->ycbcr_420_allowed; @@ -3357,6 +3359,8 @@ __dw_hdmi_probe(struct platform_device *pdev,
return hdmi;
+err_irq: + drm_bridge_remove(&hdmi->bridge); err_iahb: clk_disable_unprepare(hdmi->iahb_clk); if (hdmi->cec_clk) @@ -3371,6 +3375,8 @@ __dw_hdmi_probe(struct platform_device *pdev,
static void __dw_hdmi_remove(struct dw_hdmi *hdmi) { + drm_bridge_remove(&hdmi->bridge); + if (hdmi->audio && !IS_ERR(hdmi->audio)) platform_device_unregister(hdmi->audio); if (!IS_ERR(hdmi->cec)) @@ -3396,22 +3402,12 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi) struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, const struct dw_hdmi_plat_data *plat_data) { - struct dw_hdmi *hdmi; - - hdmi = __dw_hdmi_probe(pdev, plat_data); - if (IS_ERR(hdmi)) - return hdmi; - - drm_bridge_add(&hdmi->bridge); - - return hdmi; + return __dw_hdmi_probe(pdev, plat_data); } EXPORT_SYMBOL_GPL(dw_hdmi_probe);
void dw_hdmi_remove(struct dw_hdmi *hdmi) { - drm_bridge_remove(&hdmi->bridge); - __dw_hdmi_remove(hdmi); } EXPORT_SYMBOL_GPL(dw_hdmi_remove);