Re: [PATCH v2 01/10] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection

[email protected] Tue, 04 Aug 2026 08:37:07 +0000
Newsgroups org.freedesktop.lists.dri-devel,org.kernel.vger.linux-devicetree
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

New issues:
- [High] The DP controller IRQ for native HPD mode is left enabled during system suspend, risking a kernel crash on hotplug events.
- [High] Component bind failure leaves HPD IRQ enabled and PM reference leaked, causing a Use-After-Free.

Pre-existing issues:
- [High] The return value of `pm_runtime_get_sync()` is ignored in `analogix_dp_set_bridge()`, potentially leading to hardware access on a suspended device.
- [High] Sleeping in atomic context via `usleep_range()` in bridge atomic enable callback.
- [High] Memory leak and list corruption due to `devm_drm_bridge_add` in component bind.
--

--- Patch [1]: [PATCH v2 01/10] drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection ---
commit c884a0bafddd9bc289fdebe294b1a5fb1f401308
Author: Damon Ding <[email protected]>

drm/bridge: analogix_dp: Manage pm runtime and IRQ for native HPD pin detection

This commit modifies the Analogix DP driver to keep the native HPD pin
IRQ active while the display is disabled on Rockchip platforms. It splits
the IRQ management paths so that native HPD pin mode holds a runtime PM
power reference and enables the IRQ during bind/unbind, rather than during
bridge enable/disable.

> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> index 30c0c0b41d5aa..9f8544d3c8870 100644
> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c

[ ... ]

> @@ -1018,7 +1024,8 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp)
>  		goto out_dp_init;
>  	}
>  
> -	enable_irq(dp->irq);
> +	if (!analogix_dp_require_pm_for_hpd_irq(dp))
> +		enable_irq(dp->irq);

[Severity: High]
This is a pre-existing issue, but does this code ignore the return value of
pm_runtime_get_sync()?

If pm_runtime_get_sync(dp->dev) fails earlier in analogix_dp_set_bridge()
and returns a negative error code, the device remains suspended. The driver
subsequently calls analogix_dp_init_analog_func(), which accesses hardware
registers on the unpowered device.

>  	return 0;
>  
>  out_dp_init:

[ ... ]

> @@ -1160,7 +1167,8 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
>  	if (dp->dpms_mode != DRM_MODE_DPMS_ON)
>  		return;
>  
> -	disable_irq(dp->irq);
> +	if (!analogix_dp_require_pm_for_hpd_irq(dp))
> +		disable_irq(dp->irq);

[Severity: High]
Does skipping disable_irq() here leave the DP controller IRQ enabled during
system suspend?

During dpm_suspend, pm_runtime_force_suspend() runs and calls
analogix_dp_suspend(), which disables the DP clock. Device IRQs are not
disabled by the IRQ core until dpm_suspend_noirq().

If a hotplug event occurs in this window, the active IRQ triggers the handler:

analogix_dp_hardirq() {
    irq_type = analogix_dp_get_irq_type(dp);
    ...
}

This reads MMIO registers while the DP clock is disabled, which can crash
the system.

>  
>  	analogix_dp_set_analog_power_down(dp, POWER_ALL, 1);

[ ... ]

> @@ -1508,6 +1516,14 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
>  		goto err_unregister_aux;
>  	}
>  

[Severity: High]
This is a pre-existing issue, but does using devm_drm_bridge_add() earlier
in this component bind callback cause a memory leak and list corruption
on failure?

If the component bind fails and is retried, the devm resources are tied to
the physical platform device and are not freed between attempts. The retry
will call devm_drm_bridge_add() on the same dp->bridge object again,
causing list_add() on a node that is already part of the global bridge list.

> +	if (analogix_dp_require_pm_for_hpd_irq(dp)) {
> +		ret = pm_runtime_resume_and_get(dp->dev);
> +		if (ret)
> +			goto err_unregister_aux;
> +
> +		enable_irq(dp->irq);

[Severity: High]
Does this code leak the PM reference and leave the IRQ enabled if a subsequent
setup step fails?

If the platform caller rockchip_dp_bind() fails at
drm_bridge_connector_init() after analogix_dp_bind() succeeds, its error
path is:

rockchip_dp_bind() {
    ...
err_cleanup_encoder:
    dp->encoder.encoder.funcs->destroy(&dp->encoder.encoder);
    return ret;
}

Because analogix_dp_unbind() is not called in this error path, the PM
reference is permanently leaked and the IRQ remains enabled. When the IRQ
fires later, analogix_dp_irq_thread() dereferences the stale dp->drm_dev
pointer.

> +	}
> +
>  	return 0;
>  
>  err_unregister_aux:

[ ... ]

[Severity: High]
This is a pre-existing issue, but does analogix_dp_bridge_atomic_enable()
sleep in atomic context?

analogix_dp_bridge_atomic_enable() is called during the atomic commit sequence
from drm_atomic_helper_commit_tail(). The driver explicitly calls
usleep_range(10, 11) in a loop:

analogix_dp_bridge_atomic_enable() {
    ...
    while (timeout_loop < MAX_PLL_LOCK_LOOP) {
        if (analogix_dp_set_bridge(dp) == 0) {
            ...
        }
        ...
        usleep_range(10, 11);
    }
}

Calling sleeping functions in this atomic context violates DRM subsystem rules.

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1