[v9,32/61] drm/rockchip: dw_hdmi_qp: Use dw_hdmi_qp_hpd_notify() for HPD reports

Message ID 20260723-dw-hdmi-qp-scramb-v9-32-4fb12ea22ac9@collabora.com (mailing list archive)
State New
Headers
Series Add HDMI 2.0 support to DW HDMI QP TX |

Commit Message

Cristian Ciocaltea July 23, 2026, 1:35 a.m. UTC
Notify only the affected connector instead of polling all of them, and
ensure .detect_ctx() runs on reconnect to recover SCDC state.

Tested-by: Maud Spierings <maud_spierings@hotmail.com>
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
---
 drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)
  

Comments

sashiko-bot@kernel.org July 23, 2026, 1:58 a.m. UTC | #1
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] The `hdmi` and `hdmi->hdmi` pointers become dangling after a failed `component_bind` or a `component_unbind`, leading to a Use-After-Free in the platform suspend/resume callbacks.
--

--- Patch [32]: [PATCH v9 32/61] drm/rockchip: dw_hdmi_qp: Use dw_hdmi_qp_hpd_notify() for HPD reports ---
commit 47b04090e96cbf8915a6ccec52dc144345e77f41
Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>

drm/rockchip: dw_hdmi_qp: Use dw_hdmi_qp_hpd_notify() for HPD reports

This commit notifies only the affected connector instead of polling all
of them. It also ensures .detect_ctx() runs on reconnect to recover SCDC
state.

> diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
> index 534a2c8da2a0a..1311eb1cb4aa5 100644
> --- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
[ ... ]
> @@ -768,11 +761,10 @@ static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
>  	if (hdmi) {
>  		hdmi->ctrl_ops->io_init(hdmi);
>  
> -		if (hdmi->hdmi)
> +		if (hdmi->hdmi) {
>  			dw_hdmi_qp_resume(dev, hdmi->hdmi);
> -
> -		if (hdmi->encoder.encoder.dev)
> -			drm_helper_hpd_irq_event(hdmi->encoder.encoder.dev);
> +			dw_hdmi_qp_hpd_notify(hdmi->hdmi);
> +		}

[Severity: High]
This is a pre-existing issue, but does this addition expose us to a 
use-after-free during system resume if the driver is unbound?

If dw_hdmi_qp_rockchip_bind() fails late, such as at 
drm_bridge_connector_init(), or if dw_hdmi_qp_rockchip_unbind() is called, 
devres and drmm cleanups will free hdmi->hdmi and the hdmi struct itself.

However, platform_set_drvdata() is never cleared, leaving a dangling pointer
that dev_get_drvdata(dev) will retrieve in dw_hdmi_qp_rockchip_resume(). 

Since the patch adds a call to dw_hdmi_qp_hpd_notify(hdmi->hdmi) here,
could a system resume following an unbind (or a failed bind) dereference 
these freed pointers?

>  	}
>  
>  	return 0;
  

Patch

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index 534a2c8da2a0..1311eb1cb4aa 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -24,7 +24,6 @@ 
 #include <drm/drm_bridge_connector.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_of.h>
-#include <drm/drm_probe_helper.h>
 
 #include "rockchip_drm_drv.h"
 
@@ -382,14 +381,8 @@  static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work)
 	struct rockchip_hdmi_qp *hdmi = container_of(work,
 						     struct rockchip_hdmi_qp,
 						     hpd_work.work);
-	struct drm_device *drm = hdmi->encoder.encoder.dev;
-	bool changed;
 
-	if (drm) {
-		changed = drm_helper_hpd_irq_event(drm);
-		if (changed)
-			dev_dbg(hdmi->dev, "connector status changed\n");
-	}
+	dw_hdmi_qp_hpd_notify(hdmi->hdmi);
 }
 
 static irqreturn_t dw_hdmi_qp_rk3576_hardirq(int irq, void *dev_id)
@@ -768,11 +761,10 @@  static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
 	if (hdmi) {
 		hdmi->ctrl_ops->io_init(hdmi);
 
-		if (hdmi->hdmi)
+		if (hdmi->hdmi) {
 			dw_hdmi_qp_resume(dev, hdmi->hdmi);
-
-		if (hdmi->encoder.encoder.dev)
-			drm_helper_hpd_irq_event(hdmi->encoder.encoder.dev);
+			dw_hdmi_qp_hpd_notify(hdmi->hdmi);
+		}
 	}
 
 	return 0;