* [PATCH v7 19/23] drm: bridge: dw_hdmi: Use delayed_work to debounce hotplug event
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
HDMI Specification Version 1.4b chapter 8.5 mentions:
An HDMI Sink shall not assert high voltage level on its Hot Plug
Detect pin when the E-EDID is not available for reading.
A Source may use a high voltage level Hot Plug Detect signal to
initiate the reading of E-EDID data.
An HDMI Sink shall indicate any change to the contents of the E-EDID
by driving a low voltage level pulse on the Hot Plug Detect pin. This
pulse shall be at least 100 msec.
Use a delayed work to debounce reacting on HPD events to improve
handling of a HPD low voltage level pulse when a sink changes the EDID.
The delayed work is only enabled between enable_hpd()/hpd_enable() and
disable_hpd()/hpd_disable() calls from core, i.e. enabled after
attach/bind/resume and disabled before detach/unbind/suspend.
The 1100 msec hotplug debounce timeout was arbitrarily picked to match
other drivers using same const, and testing using a Raspberry Pi Monitor
seem to use a 200-300 msec pulse when going from standby to power on
state.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: Change to free irq before mute and clear using IH regs, also include
clear of STAT0_RX_SENSE
v6: Change back to disable_delayed_work_sync() in hpd disable ops,
Ensure HPD interrupt is masked and IRQ handler is disabled early
in dw_hdmi_remove() to prevent any irq re-arming of delayed work,
Drop use of suspend helper
v5: Change to none-sync disable_delayed_work() in hpd disable ops,
Change to cancel_delayed_work_sync() in remove,
Add cancel_delayed_work_sync() to new suspend helper
v4: Disable/mask delayed_work until enable_hpd()/hpd_enable(),
Read connector status directly from HW regs in hpd_work
v3: New patch
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 80 +++++++++++++++++++++--
1 file changed, 75 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 8afc9d240121..270db58a0e7c 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -50,6 +50,8 @@
#define HDMI14_MAX_TMDSCLK 340000000
+#define HOTPLUG_DEBOUNCE_MS 1100
+
static const u16 csc_coeff_default[3][4] = {
{ 0x2000, 0x0000, 0x0000, 0x0000 },
{ 0x0000, 0x2000, 0x0000, 0x0000 },
@@ -185,6 +187,7 @@ struct dw_hdmi {
hdmi_codec_plugged_cb plugged_cb;
struct device *codec_dev;
enum drm_connector_status last_connector_result;
+ struct delayed_work hpd_work;
};
const struct dw_hdmi_plat_data *dw_hdmi_to_plat_data(struct dw_hdmi *hdmi)
@@ -2517,6 +2520,20 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)
dw_hdmi_connector_status_update(hdmi, connector, connector->status);
}
+static void dw_hdmi_connector_enable_hpd(struct drm_connector *connector)
+{
+ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
+
+ enable_delayed_work(&hdmi->hpd_work);
+}
+
+static void dw_hdmi_connector_disable_hpd(struct drm_connector *connector)
+{
+ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
+
+ disable_delayed_work_sync(&hdmi->hpd_work);
+}
+
static void dw_hdmi_connector_destroy(struct drm_connector *connector)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
@@ -2538,6 +2555,8 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
.get_modes = dw_hdmi_connector_get_modes,
.atomic_check = dw_hdmi_connector_atomic_check,
+ .enable_hpd = dw_hdmi_connector_enable_hpd,
+ .disable_hpd = dw_hdmi_connector_disable_hpd,
};
static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
@@ -2968,6 +2987,20 @@ static const struct drm_edid *dw_hdmi_bridge_edid_read(struct drm_bridge *bridge
return dw_hdmi_edid_read(hdmi, connector);
}
+static void dw_hdmi_bridge_hpd_enable(struct drm_bridge *bridge)
+{
+ struct dw_hdmi *hdmi = bridge->driver_private;
+
+ enable_delayed_work(&hdmi->hpd_work);
+}
+
+static void dw_hdmi_bridge_hpd_disable(struct drm_bridge *bridge)
+{
+ struct dw_hdmi *hdmi = bridge->driver_private;
+
+ disable_delayed_work_sync(&hdmi->hpd_work);
+}
+
static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
@@ -2981,6 +3014,8 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.mode_valid = dw_hdmi_bridge_mode_valid,
.detect = dw_hdmi_bridge_detect,
.edid_read = dw_hdmi_bridge_edid_read,
+ .hpd_enable = dw_hdmi_bridge_hpd_enable,
+ .hpd_disable = dw_hdmi_bridge_hpd_disable,
};
/* -----------------------------------------------------------------------------
@@ -3101,8 +3136,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
status == connector_status_connected ?
"plugin" : "plugout");
- if (hdmi->bridge.dev)
- drm_helper_hpd_irq_event(hdmi->bridge.dev);
+ mod_delayed_work(system_percpu_wq, &hdmi->hpd_work,
+ msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
}
hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
@@ -3112,6 +3147,29 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static void dw_hdmi_hpd_work(struct work_struct *work)
+{
+ struct dw_hdmi *hdmi = container_of(work, struct dw_hdmi, hpd_work.work);
+ struct drm_device *dev = hdmi->bridge.dev;
+
+ if (WARN_ON(!dev))
+ return;
+
+ /*
+ * Notify the DRM core of the HPD event using drm_helper_hpd_irq_event()
+ * instead of drm_bridge_hpd_notify(). This will cause the DRM function
+ * check_connector_changed() to be called, which in turn calls the
+ * connector detect()/force() funcs to detect any connection status or
+ * epoch changes. The bridge connector detect() func also ensures that
+ * any hpd_notify() funcs are called for all bridges in the chain.
+ *
+ * drm_bridge_hpd_notify() shares a mutex with drm_bridge_hpd_disable(),
+ * and can result in a deadlock due to the disable_delayed_work_sync()
+ * call to wait on work to complete in dw_hdmi_bridge_hpd_disable().
+ */
+ drm_helper_hpd_irq_event(dev);
+}
+
static const struct dw_hdmi_phy_data dw_hdmi_phys[] = {
{
.type = DW_HDMI_PHY_DWC_HDMI_TX_PHY,
@@ -3396,6 +3454,9 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
goto err_res;
}
+ INIT_DELAYED_WORK(&hdmi->hpd_work, dw_hdmi_hpd_work);
+ disable_delayed_work(&hdmi->hpd_work);
+
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
dw_hdmi_irq, IRQF_SHARED,
dev_name(dev), hdmi);
@@ -3532,6 +3593,18 @@ EXPORT_SYMBOL_GPL(dw_hdmi_probe);
void dw_hdmi_remove(struct dw_hdmi *hdmi)
{
+ struct platform_device *pdev = to_platform_device(hdmi->dev);
+ int irq = platform_get_irq(pdev, 0);
+
+ /* Free, mute and clear phy interrupts */
+ devm_free_irq(hdmi->dev, irq, hdmi);
+ hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD | HDMI_IH_PHY_STAT0_RX_SENSE,
+ HDMI_IH_PHY_STAT0);
+
+ /* Cancel any pending hot plug work */
+ cancel_delayed_work_sync(&hdmi->hpd_work);
+
drm_bridge_remove(&hdmi->bridge);
if (hdmi->audio && !IS_ERR(hdmi->audio))
@@ -3539,9 +3612,6 @@ void dw_hdmi_remove(struct dw_hdmi *hdmi)
if (!IS_ERR(hdmi->cec))
platform_device_unregister(hdmi->cec);
- /* Disable all interrupts */
- hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
-
if (hdmi->i2c)
i2c_del_adapter(&hdmi->i2c->adap);
else
--
2.54.0
^ permalink raw reply related
* [PATCH v7 02/23] drm: bridge: dw_hdmi: Only notify connected status on HPD interrupt
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Lucas Stach
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
drm_helper_hpd_irq_event() and drm_bridge_hpd_notify() may incorrectly
be called with a connected status when HPD is high and RX sense is
changed. This typically happens when the HDMI cable is unplugged,
shortly before the HPD is changed to low.
The original intent of commit da09daf88108 ("drm: bridge: dw_hdmi: only
trigger hotplug event on link change") was to signal hotplug event at
correct interrupt states.
Based on the commit message the intent was to trigger hotplug event:
- when HPD goes high (plugin)
- when both HPD and RX sense has gone low (plugout)
However, following interrupt state changes can typically be observed
when the HDMI cable is unplugged:
- RX interrupt: HPD=high RX=low -> triggers a connected event
- HPD interrupt: HPD=low RX=low -> triggers a disconnected event
Fix this by only notify connected status on the HPD interrupt when HPD
is going high, not on the RX sense interrupt when RX sense is changed.
After this a connected event should be triggered when HPD=high at HPD
interrupt, and a disconnected event should be triggered when both
HPD=low and RX=low at either HPD or RX interrupt.
Fixes: da09daf88108 ("drm: bridge: dw_hdmi: only trigger hotplug event on link change")
Reviewed-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Collect t-b tag
v5: No change
v4: Collect r-b tag
v3: Update commit message
v2: New patch
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index d3e6a6562870..b7bfc0e9a6b2 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -3157,7 +3157,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
mutex_unlock(&hdmi->cec_notifier_mutex);
}
- if (phy_stat & HDMI_PHY_HPD)
+ if ((intr_stat & HDMI_IH_PHY_STAT0_HPD) &&
+ (phy_stat & HDMI_PHY_HPD))
status = connector_status_connected;
if (!(phy_stat & (HDMI_PHY_HPD | HDMI_PHY_RX_SENSE)))
--
2.54.0
^ permalink raw reply related
* [PATCH v7 18/23] drm: bridge: dw_hdmi: Drop call to drm_bridge_hpd_notify()
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
The use of calls to both drm_helper_hpd_irq_event() and
drm_bridge_hpd_notify() from the HPD IRQ handler may cause multiple
hotplug uevents and modesets when the bridge connector is used.
Use of drm_helper_hpd_irq_event() cause the internal DRM function
check_connector_changed() to be called, which in turn calls the
connector detect()/force() funcs to detect any connection status or
epoch changes, and when changed trigger a hotplug uevent. This also
help ensure that EDID and CEC phys addr is updated.
If only a call drm_bridge_hpd_notify() would be used, a custom connector
status/EDID change detection logic needs to be implemented, to fully
match what check_connector_changed() already provides.
The bridge connector detect() func also ensures that any hpd_notify()
funcs are called for all bridges in the chain, so there is not really
any need to have a call to drm_bridge_hpd_notify() here.
With both calls there is two hotplug uevents, two modesets and a total
of four .hpd_notify() calls (using a bridge connector):
dw_hdmi_irq(): EVENT=plugout
drm_helper_hpd_irq_event():
dw_hdmi_bridge_hpd_notify(status=2)
[drm:check_connector_changed] [CONNECTOR:46:HDMI-A-1] status updated from connected to disconnected
[drm:check_connector_changed] [CONNECTOR:46:HDMI-A-1] Changed epoch counter 1 => 2
[drm:drm_sysfs_connector_hotplug_event] [CONNECTOR:46:HDMI-A-1] generating connector hotplug event
drm_client_hotplug():
[drm:drm_fb_helper_hotplug_event]
[drm:drm_client_modeset_probe]
[drm:drm_helper_probe_single_connector_modes] [CONNECTOR:46:HDMI-A-1]
dw_hdmi_bridge_hpd_notify(status=2)
[drm:drm_helper_probe_single_connector_modes] [CONNECTOR:46:HDMI-A-1] disconnected
[drm:drm_edid_connector_update] [CONNECTOR:46:HDMI-A-1] EDID changed, epoch counter 3
[drm:drm_client_modeset_probe] No connectors reported connected with modes
[drm:drm_client_modeset_probe] [CONNECTOR:46:HDMI-A-1] enabled? no
[drm:drm_client_firmware_config.isra.0] Not using firmware configuration
[drm:drm_client_modeset_probe] picking CRTCs for 3840x2160 config
[drm:drm_client_hotplug] fbdev: ret=0
drm_bridge_hpd_notify():
dw_hdmi_bridge_hpd_notify(status=2)
[drm:drm_sysfs_connector_hotplug_event] [CONNECTOR:46:HDMI-A-1] generating connector hotplug event
drm_client_hotplug():
[drm:drm_fb_helper_hotplug_event]
[drm:drm_client_modeset_probe]
[drm:drm_helper_probe_single_connector_modes] [CONNECTOR:46:HDMI-A-1]
dw_hdmi_bridge_hpd_notify(status=2)
[drm:drm_helper_probe_single_connector_modes] [CONNECTOR:46:HDMI-A-1] disconnected
[drm:drm_client_modeset_probe] No connectors reported connected with modes
[drm:drm_client_modeset_probe] [CONNECTOR:46:HDMI-A-1] enabled? no
[drm:drm_client_firmware_config.isra.0] Not using firmware configuration
[drm:drm_client_modeset_probe] picking CRTCs for 3840x2160 config
[drm:drm_client_hotplug] fbdev: ret=0
Change to only call drm_helper_hpd_irq_event() from HPD IRQ handler to
ensure that only one hotplug uevent is sent to userspace when connection
status or EDID changes.
With only a call the drm_helper_hpd_irq_event() there is only a single
hotplug uevent and only two .hpd_notify() calls:
dw_hdmi_irq(): EVENT=plugout
drm_helper_hpd_irq_event():
dw_hdmi_bridge_hpd_notify(status=2)
[drm:check_connector_changed] [CONNECTOR:46:HDMI-A-1] status updated from connected to disconnected
[drm:check_connector_changed] [CONNECTOR:46:HDMI-A-1] Changed epoch counter 1 => 2
[drm:drm_sysfs_connector_hotplug_event] [CONNECTOR:46:HDMI-A-1] generating connector hotplug event
drm_client_hotplug():
[drm:drm_fb_helper_hotplug_event]
[drm:drm_client_modeset_probe]
[drm:drm_helper_probe_single_connector_modes] [CONNECTOR:46:HDMI-A-1]
dw_hdmi_bridge_hpd_notify(status=2)
[drm:drm_helper_probe_single_connector_modes] [CONNECTOR:46:HDMI-A-1] disconnected
[drm:drm_edid_connector_update] [CONNECTOR:46:HDMI-A-1] EDID changed, epoch counter 3
[drm:drm_client_modeset_probe] No connectors reported connected with modes
[drm:drm_client_modeset_probe] [CONNECTOR:46:HDMI-A-1] enabled? no
[drm:drm_client_firmware_config.isra.0] Not using firmware configuration
[drm:drm_client_modeset_probe] picking CRTCs for 3840x2160 config
[drm:drm_client_hotplug] fbdev: ret=0
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Drop the call from IRQ handler instead, prior to use of a HPD
delayed work to avoid a possible deadlock with use of sync() calls
in the bridge hpd_disable() ops,
Update commit message,
Collect t-b tag
v5: New patch
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 5dacb8a99715..8afc9d240121 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -3101,10 +3101,8 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
status == connector_status_connected ?
"plugin" : "plugout");
- if (hdmi->bridge.dev) {
+ if (hdmi->bridge.dev)
drm_helper_hpd_irq_event(hdmi->bridge.dev);
- drm_bridge_hpd_notify(&hdmi->bridge, status);
- }
}
hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
--
2.54.0
^ permalink raw reply related
* [PATCH v7 17/23] drm: bridge: dw_hdmi: Declare bridge CEC notifier support
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
EDID and CEC phys addr is now being updated in bridge detect() func,
making it possible to have CEC notifier support using the bridge
connector.
Add the CEC notifier bridge op to instruct the bridge connector to make
use of the generic CEC notifier helpers.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: Only declare CEC notifier support when CEC device register succeeds
v6: New patch
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 0c4388e7aa5e..5dacb8a99715 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -3515,6 +3515,10 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
pdevinfo.dma_mask = 0;
hdmi->cec = platform_device_register_full(&pdevinfo);
+ if (!IS_ERR(hdmi->cec)) {
+ hdmi->bridge.ops |= DRM_BRIDGE_OP_HDMI_CEC_NOTIFIER;
+ hdmi->bridge.hdmi_cec_dev = hdmi->dev;
+ }
}
drm_bridge_add(&hdmi->bridge);
--
2.54.0
^ permalink raw reply related
* [PATCH v7 01/23] drm: bridge: dw_hdmi: Disable scrambler feature when not supported
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel, Christopher Obbard
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
The scrambler feature can be left enabled when hotplugging from a sink
and mode that require scrambling to a sink that does not support SCDC or
scrambling.
Typically a blank screen or 'no signal' message can be observed after
using a HDMI 2.0 4K@60Hz mode and then hotplugging to a sink that only
support HDMI 1.4.
Fix this by disabling the scrambler feature when SCDC is not supported.
Fixes: 264fce6cc2c1 ("drm/bridge: dw-hdmi: Add SCDC and TMDS Scrambling support")
Reported-by: Christopher Obbard <chris.obbard@collabora.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Collect t-b tag
v5: No change
v4: No change
v3: Collect r-b tag
v2: New patch
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 41b3a9cfa2f5..d3e6a6562870 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2135,6 +2135,8 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
HDMI_MC_SWRSTZ);
drm_scdc_set_scrambling(hdmi->curr_conn, 0);
}
+ } else if (hdmi->version >= 0x200a) {
+ hdmi_writeb(hdmi, 0, HDMI_FC_SCRAMBLER_CTRL);
}
/* Set up horizontal active pixel width */
--
2.54.0
^ permalink raw reply related
* [PATCH v7 15/23] drm: bridge: dw_hdmi: Use generic CEC notifier helpers
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
The commit 8b1a8f8b2002 ("drm/display: add CEC helpers code") added
generic CEC helpers to be used by HDMI drivers.
Replace the open-coded CEC notifier handling with use of the generic CEC
notifier helpers. Ensure DRM_DISPLAY_HDMI_CEC_NOTIFIER_HELPER is also
selected when DRM_DW_HDMI_CEC is enabled so that the CEC helpers is
available.
The drmm release action for the generic CEC notifier should run just
before dw_hdmi_connector_destroy(), closely matching the lifetime of
the replaced CEC notifier and the connector.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Update commit message,
Collect t-b tag
v5: Collect r-b tag
v4: New patch
---
drivers/gpu/drm/bridge/synopsys/Kconfig | 1 +
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 26 +++++------------------
2 files changed, 6 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig
index a46df7583bcf..e6723af03b43 100644
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
@@ -49,6 +49,7 @@ config DRM_DW_HDMI_CEC
depends on DRM_DW_HDMI
select CEC_CORE
select CEC_NOTIFIER
+ select DRM_DISPLAY_HDMI_CEC_NOTIFIER_HELPER
help
Support the CE interface which is part of the Synopsys
Designware HDMI block.
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 0e84dff72470..37406555af7b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -23,12 +23,11 @@
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
-#include <media/cec-notifier.h>
-
#include <linux/media-bus-format.h>
#include <linux/videodev2.h>
#include <drm/bridge/dw_hdmi.h>
+#include <drm/display/drm_hdmi_cec_helper.h>
#include <drm/display/drm_hdmi_helper.h>
#include <drm/display/drm_scdc_helper.h>
#include <drm/drm_atomic.h>
@@ -183,8 +182,6 @@ struct dw_hdmi {
void (*enable_audio)(struct dw_hdmi *hdmi);
void (*disable_audio)(struct dw_hdmi *hdmi);
- struct cec_notifier *cec_notifier;
-
hdmi_codec_plugged_cb plugged_cb;
struct device *codec_dev;
enum drm_connector_status last_connector_result;
@@ -2453,7 +2450,7 @@ dw_hdmi_connector_status_update(struct dw_hdmi *hdmi,
if (status == connector_status_disconnected) {
drm_edid_connector_update(connector, NULL);
- cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
+ drm_connector_cec_phys_addr_invalidate(connector);
return;
}
@@ -2462,8 +2459,7 @@ dw_hdmi_connector_status_update(struct dw_hdmi *hdmi,
drm_edid_free(drm_edid);
if (status == connector_status_connected)
- cec_notifier_set_phys_addr(hdmi->cec_notifier,
- connector->display_info.source_physical_address);
+ drm_connector_cec_phys_addr_set(connector);
}
static enum drm_connector_status
@@ -2525,9 +2521,6 @@ static void dw_hdmi_connector_destroy(struct drm_connector *connector)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
- cec_notifier_conn_unregister(hdmi->cec_notifier);
- hdmi->cec_notifier = NULL;
-
drm_connector_cleanup(connector);
drm_bridge_put(&hdmi->bridge);
}
@@ -2550,8 +2543,6 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs =
static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
{
struct drm_connector *connector = &hdmi->connector;
- struct cec_connector_info conn_info;
- struct cec_notifier *notifier;
int ret;
if (hdmi->version >= 0x200a)
@@ -2587,15 +2578,8 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
drm_connector_attach_encoder(connector, hdmi->bridge.encoder);
- cec_fill_conn_info_from_drm(&conn_info, connector);
-
- notifier = cec_notifier_conn_register(hdmi->dev, NULL, &conn_info);
- if (!notifier)
- return -ENOMEM;
-
- hdmi->cec_notifier = notifier;
-
- return 0;
+ return drmm_connector_hdmi_cec_notifier_register(connector, NULL,
+ hdmi->dev);
}
/* -----------------------------------------------------------------------------
--
2.54.0
^ permalink raw reply related
* [PATCH v7 14/23] drm: bridge: dw_hdmi: Use display_info is_hdmi and has_audio
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
drm_edid_connector_update() is being called from bridge connector funcs
and from detect and force funcs for dw-hdmi connector.
Change to use is_hdmi and has_audio from display_info directly instead
of keeping our own state in sink_is_hdmi and sink_has_audio.
Also remove the old and unused edid struct member and related define.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change, re-order patch
v6: Collect t-b tag
v5: No change
v4: Collect r-b tag
v3: No change
v2: Collect r-b tag
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 32 ++++-------------------
1 file changed, 5 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a4ecf830103d..0e84dff72470 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -46,8 +46,6 @@
#define DDC_CI_ADDR 0x37
#define DDC_SEGMENT_ADDR 0x30
-#define HDMI_EDID_LEN 512
-
/* DW-HDMI Controller >= 0x200a are at least compliant with SCDC version 1 */
#define SCDC_MIN_SOURCE_VERSION 0x1
@@ -147,8 +145,6 @@ struct dw_hdmi {
int vic;
- u8 edid[HDMI_EDID_LEN];
-
struct {
const struct dw_hdmi_phy_ops *ops;
const char *name;
@@ -158,8 +154,6 @@ struct dw_hdmi {
struct i2c_adapter *ddc;
void __iomem *regs;
- bool sink_is_hdmi;
- bool sink_has_audio;
struct pinctrl *pinctrl;
struct pinctrl_state *default_state;
@@ -2056,7 +2050,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
- inv_val |= hdmi->sink_is_hdmi ?
+ inv_val |= display->is_hdmi ?
HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE;
@@ -2292,7 +2286,7 @@ static int dw_hdmi_poweron(struct dw_hdmi *hdmi,
if (hdmi->hdmi_data.enc_out_bus_format == MEDIA_BUS_FMT_FIXED)
hdmi->hdmi_data.enc_out_bus_format = MEDIA_BUS_FMT_RGB888_1X24;
- hdmi->hdmi_data.rgb_limited_range = hdmi->sink_is_hdmi &&
+ hdmi->hdmi_data.rgb_limited_range = display->is_hdmi &&
drm_default_rgb_quant_range(mode) ==
HDMI_QUANTIZATION_RANGE_LIMITED;
@@ -2312,7 +2306,7 @@ static int dw_hdmi_poweron(struct dw_hdmi *hdmi,
/* HDMI Initialization Step B.3 */
dw_hdmi_enable_video_path(hdmi);
- if (hdmi->sink_has_audio) {
+ if (display->has_audio) {
dev_dbg(hdmi->dev, "sink has audio support\n");
/* HDMI Initialization Step E - Configure audio */
@@ -2321,7 +2315,7 @@ static int dw_hdmi_poweron(struct dw_hdmi *hdmi,
}
/* not for DVI mode */
- if (hdmi->sink_is_hdmi) {
+ if (display->is_hdmi) {
dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__);
/* HDMI Initialization Step F - Configure AVI InfoFrame */
@@ -2435,29 +2429,13 @@ static const struct drm_edid *dw_hdmi_edid_read(struct dw_hdmi *hdmi,
struct drm_connector *connector)
{
const struct drm_edid *drm_edid;
- const struct edid *edid;
if (!hdmi->ddc)
return NULL;
drm_edid = drm_edid_read_ddc(connector, hdmi->ddc);
- if (!drm_edid) {
+ if (!drm_edid)
dev_dbg(hdmi->dev, "failed to get edid\n");
- return NULL;
- }
-
- /*
- * FIXME: This should use connector->display_info.is_hdmi and
- * connector->display_info.has_audio from a path that has read the EDID
- * and called drm_edid_connector_update().
- */
- edid = drm_edid_raw(drm_edid);
-
- dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
- edid->width_cm, edid->height_cm);
-
- hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
- hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
return drm_edid;
}
--
2.54.0
^ permalink raw reply related
* [PATCH v7 13/23] drm: bridge: dw_hdmi: Use dw_hdmi_connector_status_update()
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
Update connector EDID and CEC phys addr from detect and force funcs to
ensure that userspace always have access to latest read EDID after a
sink use a HPD low voltage pulse to indicate that EDID has changed.
With EDID being updated in detect and force funcs, there should no
longer be a need to re-read EDID in get_modes funcs, so drop it.
This change make the dw-hdmi connector work more closely like the bridge
connector does with a hdmi bridge.
Reviewed-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Pass struct dw_hdmi as a parameter,
Collect t-b tag
v5: No change
v4: Move last_connector_result assign in force ops to this patch,
Collect r-b tag
v3: Reworked 'Update EDID during hotplug processing' patch
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 28 ++++++++++++-----------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index a056e147731b..a4ecf830103d 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2473,36 +2473,36 @@ dw_hdmi_connector_status_update(struct dw_hdmi *hdmi,
{
const struct drm_edid *drm_edid;
+ if (status == connector_status_disconnected) {
+ drm_edid_connector_update(connector, NULL);
+ cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
+ return;
+ }
+
drm_edid = dw_hdmi_edid_read(hdmi, connector);
drm_edid_connector_update(connector, drm_edid);
drm_edid_free(drm_edid);
- cec_notifier_set_phys_addr(hdmi->cec_notifier,
- connector->display_info.source_physical_address);
+ if (status == connector_status_connected)
+ cec_notifier_set_phys_addr(hdmi->cec_notifier,
+ connector->display_info.source_physical_address);
}
static enum drm_connector_status
dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
- struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
- connector);
+ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
enum drm_connector_status status;
status = dw_hdmi_detect(hdmi);
- if (status == connector_status_disconnected)
- cec_notifier_phys_addr_invalidate(hdmi->cec_notifier);
+ dw_hdmi_connector_status_update(hdmi, connector, status);
return status;
}
static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
{
- struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
- connector);
-
- dw_hdmi_connector_status_update(hdmi, connector, connector->status);
-
return drm_edid_connector_add_modes(connector);
}
@@ -2532,13 +2532,15 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
static void dw_hdmi_connector_force(struct drm_connector *connector)
{
- struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
- connector);
+ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
mutex_lock(&hdmi->mutex);
hdmi->force = connector->force;
+ hdmi->last_connector_result = connector->status;
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
+
+ dw_hdmi_connector_status_update(hdmi, connector, connector->status);
}
static void dw_hdmi_connector_destroy(struct drm_connector *connector)
--
2.54.0
^ permalink raw reply related
* [PATCH v7 12/23] drm: bridge: dw_hdmi: Extract dw_hdmi_connector_status_update()
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
Move connector EDID update and CEC phys addr handling to a helper
function as a preparation before moving EDID refresh from get_modes
funcs to detect/force funcs.
Reviewed-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Pass struct dw_hdmi as a parameter, to allow calls from bridge funcs,
Collect t-b tag
v5: No change
v4: Collect r-b tag
v3: New patch
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 27 ++++++++++++++---------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 0dd4c823c60a..a056e147731b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2466,6 +2466,21 @@ static const struct drm_edid *dw_hdmi_edid_read(struct dw_hdmi *hdmi,
* DRM Connector Operations
*/
+static void
+dw_hdmi_connector_status_update(struct dw_hdmi *hdmi,
+ struct drm_connector *connector,
+ enum drm_connector_status status)
+{
+ const struct drm_edid *drm_edid;
+
+ drm_edid = dw_hdmi_edid_read(hdmi, connector);
+ drm_edid_connector_update(connector, drm_edid);
+ drm_edid_free(drm_edid);
+
+ cec_notifier_set_phys_addr(hdmi->cec_notifier,
+ connector->display_info.source_physical_address);
+}
+
static enum drm_connector_status
dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
@@ -2485,18 +2500,10 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
connector);
- const struct drm_edid *drm_edid;
- int ret;
- drm_edid = dw_hdmi_edid_read(hdmi, connector);
+ dw_hdmi_connector_status_update(hdmi, connector, connector->status);
- drm_edid_connector_update(connector, drm_edid);
- cec_notifier_set_phys_addr(hdmi->cec_notifier,
- connector->display_info.source_physical_address);
- ret = drm_edid_connector_add_modes(connector);
- drm_edid_free(drm_edid);
-
- return ret;
+ return drm_edid_connector_add_modes(connector);
}
static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
--
2.54.0
^ permalink raw reply related
* [PATCH v7 09/23] drm: bridge: dw_hdmi: Unregister CEC notifier during connector cleanup
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
The CEC notifier is being unregistered when the bridge detach,
something that happens earlier than normal connector cleanup.
Change to unregister the CEC notifier at connector cleanup, in the
connector .destroy() func, to align the lifetime of the connector and
the CEC notifier and closer match a drmres handled generic CEC notifier.
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Collect t-b tag
v5: New patch
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index cbbd15578042..5fd26ff8f55b 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2532,6 +2532,11 @@ static void dw_hdmi_connector_destroy(struct drm_connector *connector)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
+ mutex_lock(&hdmi->cec_notifier_mutex);
+ cec_notifier_conn_unregister(hdmi->cec_notifier);
+ hdmi->cec_notifier = NULL;
+ mutex_unlock(&hdmi->cec_notifier_mutex);
+
drm_connector_cleanup(connector);
drm_bridge_put(&hdmi->bridge);
}
@@ -2909,16 +2914,6 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge,
return dw_hdmi_connector_create(hdmi);
}
-static void dw_hdmi_bridge_detach(struct drm_bridge *bridge)
-{
- struct dw_hdmi *hdmi = bridge->driver_private;
-
- mutex_lock(&hdmi->cec_notifier_mutex);
- cec_notifier_conn_unregister(hdmi->cec_notifier);
- hdmi->cec_notifier = NULL;
- mutex_unlock(&hdmi->cec_notifier_mutex);
-}
-
static enum drm_mode_status
dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_info *info,
@@ -2996,7 +2991,6 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.attach = dw_hdmi_bridge_attach,
- .detach = dw_hdmi_bridge_detach,
.atomic_check = dw_hdmi_bridge_atomic_check,
.atomic_get_output_bus_fmts = dw_hdmi_bridge_atomic_get_output_bus_fmts,
.atomic_get_input_bus_fmts = dw_hdmi_bridge_atomic_get_input_bus_fmts,
--
2.54.0
^ permalink raw reply related
* [PATCH v7 08/23] drm: bridge: dw_hdmi: Remove previous_mode and mode_set
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
With the use of adjusted_mode directly from the crtc_state there is no
longer a need to store a copy in previous_mode, remove it and the now
unneeded mode_set ops.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Collect t-b tag
v5: No change, rebase on next-20260508
v4: No change
v3: Collect r-b tag
v2: No change
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 19 +------------------
1 file changed, 1 insertion(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 161ab16fdd78..cbbd15578042 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -156,8 +156,6 @@ struct dw_hdmi {
bool enabled;
} phy;
- struct drm_display_mode previous_mode;
-
struct i2c_adapter *ddc;
void __iomem *regs;
bool sink_is_hdmi;
@@ -167,7 +165,7 @@ struct dw_hdmi {
struct pinctrl_state *default_state;
struct pinctrl_state *unwedge_state;
- struct mutex mutex; /* for state below and previous_mode */
+ struct mutex mutex; /* for state below */
enum drm_connector_force force; /* mutex-protected force state */
struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */
bool disabled; /* DRM has disabled our bridge */
@@ -2941,20 +2939,6 @@ dw_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
return mode_status;
}
-static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
- const struct drm_display_mode *orig_mode,
- const struct drm_display_mode *mode)
-{
- struct dw_hdmi *hdmi = bridge->driver_private;
-
- mutex_lock(&hdmi->mutex);
-
- /* Store the display mode for plugin/DKMS poweron events */
- drm_mode_copy(&hdmi->previous_mode, mode);
-
- mutex_unlock(&hdmi->mutex);
-}
-
static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_atomic_commit *state)
{
@@ -3018,7 +3002,6 @@ static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
.atomic_get_input_bus_fmts = dw_hdmi_bridge_atomic_get_input_bus_fmts,
.atomic_enable = dw_hdmi_bridge_atomic_enable,
.atomic_disable = dw_hdmi_bridge_atomic_disable,
- .mode_set = dw_hdmi_bridge_mode_set,
.mode_valid = dw_hdmi_bridge_mode_valid,
.detect = dw_hdmi_bridge_detect,
.edid_read = dw_hdmi_bridge_edid_read,
--
2.54.0
^ permalink raw reply related
* [PATCH v7 07/23] drm: bridge: dw_hdmi: Fold poweron and setup functions
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
Fold the poweron and setup functions into one function and use the
adjusted_mode directly from the new crtc_state to remove the need of
storing previous_mode.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Collect t-b tag
v5: No change, rebase on next-20260508
v4: No change
v3: Collect r-b tag
v2: No change
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 7a9b4a7e9cbf..161ab16fdd78 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2254,9 +2254,9 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi)
HDMI_IH_MUTE_FC_STAT2);
}
-static int dw_hdmi_setup(struct dw_hdmi *hdmi,
- const struct drm_connector *connector,
- const struct drm_display_mode *mode)
+static int dw_hdmi_poweron(struct dw_hdmi *hdmi,
+ const struct drm_connector *connector,
+ const struct drm_display_mode *mode)
{
const struct drm_display_info *display = &connector->display_info;
int ret;
@@ -2396,15 +2396,6 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
}
-static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
-{
- /*
- * The curr_conn field is guaranteed to be valid here, as this function
- * is only be called when !hdmi->disabled.
- */
- dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode);
-}
-
static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
{
if (hdmi->phy.enabled) {
@@ -2982,15 +2973,19 @@ static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
struct drm_atomic_commit *state)
{
struct dw_hdmi *hdmi = bridge->driver_private;
+ const struct drm_display_mode *mode;
struct drm_connector *connector;
+ struct drm_crtc *crtc;
connector = drm_atomic_get_new_connector_for_encoder(state,
bridge->encoder);
+ crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+ mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;
mutex_lock(&hdmi->mutex);
hdmi->disabled = false;
hdmi->curr_conn = connector;
- dw_hdmi_poweron(hdmi);
+ dw_hdmi_poweron(hdmi, connector, mode);
dw_hdmi_update_phy_mask(hdmi);
handle_plugged_change(hdmi, true);
mutex_unlock(&hdmi->mutex);
--
2.54.0
^ permalink raw reply related
* [PATCH v7 06/23] drm: bridge: dw_hdmi: Use passed mode instead of stored previous_mode
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
Use the passed mode instead of mixing use of passed mode and the stored
previous_mode in dw_hdmi_setup(). The passed mode is currenly always the
previous_mode.
Also fix a small typo and add a variable to help shorten a code line.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Collect t-b tag
v5: No change
v4: No change
v3: Collect r-b tag
v2: Update commit message, s/type/typo/
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 8bec9b5cd803..7a9b4a7e9cbf 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2258,6 +2258,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi,
const struct drm_connector *connector,
const struct drm_display_mode *mode)
{
+ const struct drm_display_info *display = &connector->display_info;
int ret;
hdmi_disable_overflow_interrupts(hdmi);
@@ -2303,12 +2304,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi,
hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
/* HDMI Initialization Step B.1 */
- hdmi_av_composer(hdmi, &connector->display_info, mode);
+ hdmi_av_composer(hdmi, display, mode);
- /* HDMI Initializateion Step B.2 */
- ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data,
- &connector->display_info,
- &hdmi->previous_mode);
+ /* HDMI Initialization Step B.2 */
+ ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, display, mode);
if (ret)
return ret;
hdmi->phy.enabled = true;
--
2.54.0
^ permalink raw reply related
* [PATCH v7 05/23] drm: bridge: dw_hdmi: Call poweron/poweroff from atomic enable/disable
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
Change to only call poweron/poweroff from atomic_enable/atomic_disable
funcs instead of trying to be clever by keeping a bridge_is_on state and
poweron/off in the hotplug IRQ handler.
The bridge is already enabled/disabled depending on connection status
with the call to drm_helper_hpd_irq_event() in hotplug IRQ handler.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: No change
v6: Update commit message,
Collect t-b tag
v5: No change
v4: No change
v3: Collect r-b tag
v2: Update commit message
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 33 ++---------------------
1 file changed, 2 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 9d795c550f8a..8bec9b5cd803 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -171,7 +171,6 @@ struct dw_hdmi {
enum drm_connector_force force; /* mutex-protected force state */
struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */
bool disabled; /* DRM has disabled our bridge */
- bool bridge_is_on; /* indicates the bridge is on */
bool rxsense; /* rxsense state */
u8 phy_mask; /* desired phy int mask settings */
u8 mc_clkdis; /* clock disable register */
@@ -2400,8 +2399,6 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
{
- hdmi->bridge_is_on = true;
-
/*
* The curr_conn field is guaranteed to be valid here, as this function
* is only be called when !hdmi->disabled.
@@ -2415,30 +2412,6 @@ static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
hdmi->phy.enabled = false;
}
-
- hdmi->bridge_is_on = false;
-}
-
-static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
-{
- int force = hdmi->force;
-
- if (hdmi->disabled) {
- force = DRM_FORCE_OFF;
- } else if (force == DRM_FORCE_UNSPECIFIED) {
- if (hdmi->rxsense)
- force = DRM_FORCE_ON;
- else
- force = DRM_FORCE_OFF;
- }
-
- if (force == DRM_FORCE_OFF) {
- if (hdmi->bridge_is_on)
- dw_hdmi_poweroff(hdmi);
- } else {
- if (!hdmi->bridge_is_on)
- dw_hdmi_poweron(hdmi);
- }
}
/*
@@ -2563,7 +2536,6 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)
mutex_lock(&hdmi->mutex);
hdmi->force = connector->force;
- dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
}
@@ -3001,7 +2973,7 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
mutex_lock(&hdmi->mutex);
hdmi->disabled = true;
hdmi->curr_conn = NULL;
- dw_hdmi_update_power(hdmi);
+ dw_hdmi_poweroff(hdmi);
dw_hdmi_update_phy_mask(hdmi);
handle_plugged_change(hdmi, false);
mutex_unlock(&hdmi->mutex);
@@ -3019,7 +2991,7 @@ static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
mutex_lock(&hdmi->mutex);
hdmi->disabled = false;
hdmi->curr_conn = connector;
- dw_hdmi_update_power(hdmi);
+ dw_hdmi_poweron(hdmi);
dw_hdmi_update_phy_mask(hdmi);
handle_plugged_change(hdmi, true);
mutex_unlock(&hdmi->mutex);
@@ -3119,7 +3091,6 @@ void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
if (hpd)
hdmi->rxsense = true;
- dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
}
mutex_unlock(&hdmi->mutex);
--
2.54.0
^ permalink raw reply related
* [PATCH v7 04/23] drm: bridge: dw_hdmi: Hold bridge ref until connector cleanup
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Cristian Ciocaltea, Louis Chauvet
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
drmres connector cleanup typically run after devres has released the
last dw-hdmi bridge reference. Since struct dw_hdmi, where the connector
lives, is freed when the last bridge reference is released, connector
cleanup can end up accessing freed memory.
Call trace without a bridge reference held until connector cleanup:
- dw_hdmi_bridge_detach()
- dw_hdmi_bridge_destroy() <<-- struct dw_hdmi is free()
- [drm:drm_managed_release] drmres release begin
- [drm:drm_managed_release] REL (...) drm_mode_config_init_release (0 bytes)
- dw_hdmi_connector_destroy()
- drm_connector_cleanup() <<-- drm_connector is use-after-free
[...]
- [drm:drm_managed_release] drmres release end
Hold a bridge reference for as long as the connector exists and drop it
after drm_connector_cleanup() has completed to keep struct dw_hdmi alive
until connector teardown is finished and avoids the use-after-free.
Call trace with a bridge reference held until connector cleanup:
- dw_hdmi_bridge_detach()
- [drm:drm_managed_release] drmres release begin
- [drm:drm_managed_release] REL (...) drm_mode_config_init_release (0 bytes)
- dw_hdmi_connector_destroy()
- drm_connector_cleanup() <<-- drm_connector is destroy()
- drm_bridge_put()
- dw_hdmi_bridge_destroy() <<-- struct dw_hdmi is free()
[...]
- [drm:drm_managed_release] drmres release end
Fixes: ed6987b67418 ("drm/bridge: dw-hdmi: convert to devm_drm_bridge_alloc() API")
Tested-by: Diederik de Haas <diederik@cknow-tech.com> # Rock64, RockPro64, Quartz64-B
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: Add fixes tag, re-order patch
v6: Collect t-b tag
v5: New patch
This use-after-free issue likely existed before commit ed6987b67418 when
devm_kzalloc() was used instead of devm_drm_bridge_alloc(). However,
v6.16-rc1 first introduced bridge refcount and drm_bridge_put(),
parts that are used to help fix the use-after-free issue.
KASAN report a slab-use-after-free in __refcount_add_not_zero when,
echo fe0a0000.hdmi > /sys/bus/platform/drivers/dwhdmi-rockchip/unbind
on a Rockchip RK3566 device prior to this fix.
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index b7bfc0e9a6b2..9d795c550f8a 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2568,10 +2568,18 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)
mutex_unlock(&hdmi->mutex);
}
+static void dw_hdmi_connector_destroy(struct drm_connector *connector)
+{
+ struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector);
+
+ drm_connector_cleanup(connector);
+ drm_bridge_put(&hdmi->bridge);
+}
+
static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = dw_hdmi_connector_detect,
- .destroy = drm_connector_cleanup,
+ .destroy = dw_hdmi_connector_destroy,
.force = dw_hdmi_connector_force,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -2588,6 +2596,7 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
struct drm_connector *connector = &hdmi->connector;
struct cec_connector_info conn_info;
struct cec_notifier *notifier;
+ int ret;
if (hdmi->version >= 0x200a)
connector->ycbcr_420_allowed =
@@ -2600,10 +2609,14 @@ static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);
- drm_connector_init_with_ddc(hdmi->bridge.dev, connector,
- &dw_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA,
- hdmi->ddc);
+ ret = drm_connector_init_with_ddc(hdmi->bridge.dev, connector,
+ &dw_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ hdmi->ddc);
+ if (ret)
+ return ret;
+
+ drm_bridge_get(&hdmi->bridge);
/*
* drm_connector_attach_max_bpc_property() requires the
--
2.54.0
^ permalink raw reply related
* [PATCH v7 03/23] drm: bridge: dw_hdmi: Free IRQ before CEC adapter is unregistered
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Luca Ceresoli,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Russell King, Hans Verkuil, Archit Taneja
Cc: Liu Ying, Sandy Huang, Andy Yan, Chen-Yu Tsai, Christian Hewitt,
Diederik de Haas, Nicolas Frattaroli, Dmitry Baryshkov, dri-devel,
linux-arm-kernel, linux-rockchip, linux-amlogic, linux-sunxi, imx,
linux-kernel
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
The interrupt allocated with devm_request_threaded_irq() can be
use-after-free when the devres release action try to free_irq().
KASAN report a slab-use-after-free in dw_hdmi_cec_hardirq during unbind:
Call trace:
[...]
dw_hdmi_cec_hardirq+0x4cc/0x560
free_irq+0x48c/0x7e4
devm_irq_release+0x54/0x90
dr_node_release+0x38/0x5c
release_nodes+0xac/0x130
devres_release_all+0xf4/0x1b0
device_unbind_cleanup+0x28/0x1f8
device_release_driver_internal+0x358/0x470
device_release_driver+0x18/0x24
bus_remove_device+0x33c/0x4f0
device_del+0x2d8/0x790
platform_device_del+0x34/0x1e0
platform_device_unregister+0x14/0x3c
dw_hdmi_remove+0x74/0x180
[...]
Freed by:
[...]
kfree+0x1dc/0x5dc
cec_delete_adapter+0xd4/0x118
cec_devnode_release+0xa4/0xe0
device_release+0xa0/0x200
kobject_put+0x14c/0x26c
put_device+0x14/0x30
cec_unregister_adapter+0x20c/0x280
dw_hdmi_cec_remove+0x8c/0xd0
[...]
Explicitly devm_free_irq() before the CEC adapter is unregistered to
fix this possible use-after-free issue.
Fixes: a616e63c56ef ("drm/bridge: dw-hdmi: add cec driver")
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
v7: New patch
KASAN report a slab-use-after-free in dw_hdmi_cec_hardirq when,
echo fe0a0000.hdmi > /sys/bus/platform/drivers/dwhdmi-rockchip/unbind
on a Rockchip RK3566 device prior to this fix.
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
index 9549dabde941..67a2a242d3ca 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
@@ -309,6 +309,7 @@ static void dw_hdmi_cec_remove(struct platform_device *pdev)
struct dw_hdmi_cec *cec = platform_get_drvdata(pdev);
cec_notifier_cec_adap_unregister(cec->notify, cec->adap);
+ devm_free_irq(&pdev->dev, cec->irq, cec->adap);
cec_unregister_adapter(cec->adap);
}
--
2.54.0
^ permalink raw reply related
* [PATCH v7 00/23] drm: bridge: dw_hdmi: Misc enable/disable, CEC and EDID cleanup
From: Jonas Karlman @ 2026-05-18 18:01 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Heiko Stuebner
Cc: Laurent Pinchart, Jernej Skrabec, Luca Ceresoli, Liu Ying,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Sandy Huang, Andy Yan, Chen-Yu Tsai,
Christian Hewitt, Diederik de Haas, Nicolas Frattaroli,
Dmitry Baryshkov, dri-devel, linux-arm-kernel, linux-rockchip,
linux-amlogic, linux-sunxi, imx, linux-kernel, Jonas Karlman
This is a revival of an old dw-hdmi series and is the first series part
of a new effort to upstream old LibreELEC HDMI 2.0 patches for Rockchip
RK33xx devices.
This series ensure poweron/poweroff and CEC phys addr invalidation is
happening during normal DRM funcs, ensures EDID and CEC phys addr is
updated in detect() similar to how the bridge connector works with a
HDMI bridge attached, and also changes to debounce hotplug processing
to prevent a full disable/enable cycle during a HPD low voltage pulse.
After this series HPD, EDID and CEC handling should work very similar
regardless is the dw-hdmi connector or the bridge connector is used.
It should also help ensure a smoother transition when dw-hdmi is fully
converted into a HDMI bridge in a future series.
These changes have mainly been tested on Rockchip RK3328, RK3399 and
RK3568 devices using both the dw-hdmi connector and also using a basic
convert to use a bridge connector. The changes has also been tested on
Amlogic S905X, S905Y2 and A311D devices that uses the bridge connector.
Testing with a Rock Pi 4 (RK3399) using a Reaspberry Pi Monitor with
Linux kms client console using drm.debug=0xe should log something like
following:
Power cycle monitor using the power button:
[CONNECTOR:68:HDMI-A-1] CEA VCDB 0x4a
[CONNECTOR:68:HDMI-A-1] HDMI: DVI dual 0, max TMDS clock 0 kHz
[CONNECTOR:68:HDMI-A-1] ELD monitor RPI MON156
[CONNECTOR:68:HDMI-A-1] HDMI: latency present 0 0, video latency 0 0, audio latency 0 0
[CONNECTOR:68:HDMI-A-1] ELD size 36, SAD count 1
[CONNECTOR:68:HDMI-A-1] Same epoch counter 10
Cable unplugged:
[CONNECTOR:68:HDMI-A-1] EDID changed, epoch counter 11
[CONNECTOR:68:HDMI-A-1] status updated from connected to disconnected
[CONNECTOR:68:HDMI-A-1] Changed epoch counter 10 => 12
[CONNECTOR:68:HDMI-A-1] generating connector hotplug event
[CONNECTOR:68:HDMI-A-1] Sent hotplug event
Cable connected:
[CONNECTOR:68:HDMI-A-1] CEA VCDB 0x4a
[CONNECTOR:68:HDMI-A-1] HDMI: DVI dual 0, max TMDS clock 0 kHz
[CONNECTOR:68:HDMI-A-1] ELD monitor RPI MON156
[CONNECTOR:68:HDMI-A-1] HDMI: latency present 0 0, video latency 0 0, audio latency 0 0
[CONNECTOR:68:HDMI-A-1] ELD size 36, SAD count 1
[CONNECTOR:68:HDMI-A-1] status updated from disconnected to connected
[CONNECTOR:68:HDMI-A-1] Changed epoch counter 12 => 13
[CONNECTOR:68:HDMI-A-1] generating connector hotplug event
[CONNECTOR:68:HDMI-A-1] Sent hotplug event
This series has evolved into an initial part of a larger multi series
effort to:
- drm: bridge: dw_hdmi: Misc enable/disable, CEC and EDID cleanup [v7]
- drm/bridge: dw-hdmi: Improve input/output bus format handling
- drm/bridge: dw-hdmi: Convert to a HDMI bridge and use of bridge connector
- drm/bridge: dw-hdmi: Add and use tmds_char_rate_valid() plat data ops
- drm/meson: hdmi: Misc cleanup and use CEC notifier helpers [v1]
- phy: rockchip: inno-hdmi: Change TMDS rate handling to configure() ops [v4]
- drm/rockchip: dw_hdmi: Misc cleanup and propagate bus format [v2]
- drm/rockchip: dw_hdmi: Enable YCbCr and Deep Color modes
Link to snapshot: https://github.com/Kwiboo/linux-rockchip/commits/next-20260518-rk-hdmi-v5/
Changes in v7:
- Add patch to fix use-after-free when CEC adapter is unregistered
- Only declare CEC notifier support when CEC device register succeeds
- Re-order patches to drop drm_edid_raw() use before exposing more usage
- Change to free irq before mute and clear using IH regs
- Rebased on next-20260518
Link to v6: https://lore.kernel.org/dri-devel/20260516183838.2024991-1-jonas@kwiboo.se/
Changes in v6:
- Update EDID and CEC phys addr in the bridge detect() func
- Add CEC notifier bridge op for the bridge connector
- Change back to disable_delayed_work_sync() in hpd disable ops,
a possible deadlock is avoided by not using drm_bridge_hpd_notify()
- Drop use of a suspend helper now that hpd disable ops use sync() calls
- Ensure HPD interrupt is masked and IRQ handler is disabled early
in dw_hdmi_remove() to prevent any irq re-arming of delayed work
- Update a few commit messages and cover letter
- Collect t-b tags
Link to v5: https://lore.kernel.org/dri-devel/20260510124111.1226584-1-jonas@kwiboo.se/
Changes in v5:
- Add patch that holds a bridge ref until connector cleanup, to fix
a use-after-free issue during connector cleanup
- Add patch that unregister CEC notifier during connector cleanup
- Add patch that adds a common suspend helper
- Add patch that drops call to drm_bridge_hpd_notify()
- Collect r-b tag
- Rebased on next-20260508
Link to v4: https://lore.kernel.org/dri-devel/20260504191059.275928-1-jonas@kwiboo.se/
Changes in v4:
- Change to use generic CEC notifier helpers
- Disable/mask hpd_work until enable_hpd()/hpd_enable()
- Read connector status directly from HW regs in hpd_work
- Continued rework of HDP and RXSENSE interrupt handling
- Collect r-b tags
- Rebased on next-20260430
Link to v3: https://lore.kernel.org/dri-devel/20260403185303.80748-1-jonas@kwiboo.se/
Changes in v3:
- Rework EDID refresh handling to closer match bridge connector
- Use delayed work to debounce HPD processing
- Update commit messages
- Collect r-b tags
- Rebased on next-20260401
Link to v2: https://lore.kernel.org/dri-devel/20240908132823.3308029-1-jonas@kwiboo.se/
Changes in v2:
- Add patch to disable scrambler feature when not supported
- Add patch to only notify connected status on HPD interrupt
- Update commit messages
- Collect r-b tags
- Rebased on next-20240906
Link to v1: https://lore.kernel.org/dri-devel/20240611155108.1436502-1-jonas@kwiboo.se/
Jonas Karlman (23):
drm: bridge: dw_hdmi: Disable scrambler feature when not supported
drm: bridge: dw_hdmi: Only notify connected status on HPD interrupt
drm: bridge: dw_hdmi: Free IRQ before CEC adapter is unregistered
drm: bridge: dw_hdmi: Hold bridge ref until connector cleanup
drm: bridge: dw_hdmi: Call poweron/poweroff from atomic enable/disable
drm: bridge: dw_hdmi: Use passed mode instead of stored previous_mode
drm: bridge: dw_hdmi: Fold poweron and setup functions
drm: bridge: dw_hdmi: Remove previous_mode and mode_set
drm: bridge: dw_hdmi: Unregister CEC notifier during connector cleanup
drm: bridge: dw_hdmi: Invalidate CEC phys addr from connector detect
drm: bridge: dw_hdmi: Remove cec_notifier_mutex
drm: bridge: dw_hdmi: Extract dw_hdmi_connector_status_update()
drm: bridge: dw_hdmi: Use dw_hdmi_connector_status_update()
drm: bridge: dw_hdmi: Use display_info is_hdmi and has_audio
drm: bridge: dw_hdmi: Use generic CEC notifier helpers
drm: bridge: dw_hdmi: Update EDID and CEC phys addr in bridge detect()
drm: bridge: dw_hdmi: Declare bridge CEC notifier support
drm: bridge: dw_hdmi: Drop call to drm_bridge_hpd_notify()
drm: bridge: dw_hdmi: Use delayed_work to debounce hotplug event
drm: bridge: dw_hdmi: Rework HDP and RXSENSE interrupt handling
drm: bridge: dw_hdmi: Remove the empty dw_hdmi_setup_rx_sense()
drm: bridge: dw_hdmi: Remove the empty dw_hdmi_phy_update_hpd()
drm: bridge: dw_hdmi: Merge top and bottom half IRQ handlers
drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c | 1 -
drivers/gpu/drm/bridge/synopsys/Kconfig | 1 +
drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c | 1 +
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 502 +++++++-----------
drivers/gpu/drm/meson/meson_dw_hdmi.c | 3 -
drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 -
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 2 -
include/drm/bridge/dw_hdmi.h | 6 -
8 files changed, 192 insertions(+), 326 deletions(-)
--
2.54.0
^ permalink raw reply
* Re: [PATCH] thermal: imx: do not split quoted string across lines
From: Daniel Lezcano @ 2026-05-18 17:56 UTC (permalink / raw)
To: Mayur Kumar, rafael, daniel.lezcano, Frank.Li, s.hauer, rui.zhang,
lukasz.luba, festevam
Cc: linux-pm, imx, linux-arm-kernel, linux-kernel, kernel
In-Reply-To: <20260511174255.215207-1-kmayur809@gmail.com>
On 5/11/26 19:42, Mayur Kumar wrote:
> The checkpatch tool warns against splitting quoted strings across
> multiple lines. Join the dev_info message into a single line to
> improve the ability to grep for the message in the source.
>
> Signed-off-by: Mayur Kumar <kmayur809@gmail.com>
> ---
Applied, thanks
^ permalink raw reply
* Re: [PATCH v5 0/8] unwind, arm64: add sframe unwinder for kernel
From: Dylan Hatch @ 2026-05-18 17:55 UTC (permalink / raw)
To: Mostafa Saleh
Cc: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
Jiri Kosina, Jens Remus, Mark Rutland, Prasanna Kumar T S M,
Puranjay Mohan, Song Liu, joe.lawrence, linux-toolchains,
linux-kernel, live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <agcEMEl-QR0g6DgF@google.com>
Hi Mostafa,
On Fri, May 15, 2026 at 4:32 AM Mostafa Saleh <smostafa@google.com> wrote:
>
> On Tue, Apr 28, 2026 at 06:36:35PM +0000, Dylan Hatch wrote:
> > Implement a generic kernel sframe-based [1] unwinder. The main goal is
> > to improve reliable stacktrace on arm64 by unwinding across exception
> > boundaries.
> >
> > On x86, the ORC unwinder provides reliable stacktrace through similar
> > methodology, but arm64 lacks the necessary support from objtool to
> > create ORC unwind tables.
> >
> > Currently, there's already a sframe unwinder proposed for userspace: [2].
> > To maintain common definitions and algorithms for sframe lookup, a
> > substantial portion of this patch series aims to refactor the sframe
> > lookup code to support both kernel and userspace sframe sections.
> >
> > Currently, only GNU Binutils support sframe. This series relies on the
> > Sframe V3 format, which is supported in binutils 2.46.
> >
> > These patches are based on Steven Rostedt's sframe/core branch [3],
> > which is and aggregation of existing work done for x86 sframe userspace
> > unwind, and contains [2]. This branch is, in turn, based on Linux
> > v7.0-rc3. This full series (applied to the sframe/core branch) is
> > available on github: [4].
> >
>
> Not sure if related, but after updating my toolchain
> (aarch64-linux-gnu-gcc (Debian 15.2.0-4) 15.2.0), I hit link errors:
> ld.lld: error: arch/arm64/kernel/vdso/vgettimeofday.o:(.sframe) is being placed in '.sframe'
> ld.lld: error: arch/arm64/kernel/vdso/vgetrandom.o:(.sframe) is being placed in '.sframe`
Previously when developing against the SFrame V2 format, I had fixed
these warnings with the VDSO Makefile change currently in this series:
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 7dec05dd33b7..c60ef921956f 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -38,7 +38,7 @@ ccflags-y += -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
CC_FLAGS_REMOVE_VDSO := $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) \
$(RANDSTRUCT_CFLAGS) $(KSTACK_ERASE_CFLAGS) \
$(GCC_PLUGINS_CFLAGS) \
- $(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \
+ $(CC_FLAGS_LTO) $(CC_FLAGS_CFI) $(CC_FLAGS_SFRAME) \
-Wmissing-prototypes -Wmissing-declarations
CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables
But the warnings seem to have returned after upgrading my toolchain,
possibly due to SFrame V3 or some confounding change in GCC. The
--gsframe in the assembler should be set to 'no' by default, so
perhaps GCC is providing an override --gsframe internally?
>
> I applied this series hoping that fix it, but it doesn't, so far I
> have this hack :
> diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S
> index 52314be29191..53bdf757ee44 100644
> --- a/arch/arm64/kernel/vdso/vdso.lds.S
> +++ b/arch/arm64/kernel/vdso/vdso.lds.S
> @@ -77,7 +77,7 @@ SECTIONS
> /DISCARD/ : {
> *(.data .data.* .gnu.linkonce.d.* .sdata*)
> *(.bss .sbss .dynbss .dynsbss)
> - *(.eh_frame .eh_frame_hdr)
> + *(.eh_frame .eh_frame_hdr .sframe)
> }
> }
>
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 60c8c22fd3e4..759903acd6fc 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -1064,6 +1064,7 @@
> /* ld.bfd warns about .gnu.version* even when not emitted */ \
> *(.gnu.version*) \
> *(__tracepoint_check) \
> + *(.sframe) \
>
> #define DISCARDS \
> /DISCARD/ : { \
Since this series only handles kernel stacktrace, I believe it's
better to omit the .sframe section entirely in the case where only
ARCH_SUPPORTS_UNWIND_KERNEL_SFRAME is enabled. I think this hack may
work better for this purpose:
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index c60ef921956f..29f802bfedb1 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -41,7 +41,7 @@ CC_FLAGS_REMOVE_VDSO := $(CC_FLAGS_FTRACE) -Os
$(CC_FLAGS_SCS) \
$(CC_FLAGS_LTO) $(CC_FLAGS_CFI) $(CC_FLAGS_SFRAME) \
-Wmissing-prototypes -Wmissing-declarations
-CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables
+CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables
-Wa,--gsframe=no
CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_REMOVE_VDSO)
CFLAGS_REMOVE_vgetrandom.o = $(CC_FLAGS_REMOVE_VDSO)
Though, I don't understand why it is necessary to provide --gsframe=no
explicitly. If this approach seems ok to other folks/maintainers, I
can fold this into my series.
On the topic of SFrame for VDSO, Jens has a patch adding support for
this as part of a series to support userspace SFrame unwinding for
arm64:
https://lore.kernel.org/lkml/20260417150827.1183376-4-jremus@linux.ibm.com/
>
>
> Thanks,
> Mostafa
>
Thanks,
Dylan
^ permalink raw reply related
* Re: [PATCH 0/3] iommu: Add PCI vendor:device ID to IOMMU fault logs
From: Jason Gunthorpe @ 2026-05-18 17:54 UTC (permalink / raw)
To: Robin Murphy
Cc: Oguz, Yigit, joro@8bytes.org, will@kernel.org,
baolu.lu@linux.intel.com, dwmw2@infradead.org,
suravee.suthikulpanit@amd.com, nicolinc@nvidia.com,
iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <4cbd2bd2-9acc-4c72-a4f5-6c6cf31f71e1@arm.com>
On Mon, May 18, 2026 at 04:52:57PM +0100, Robin Murphy wrote:
> TBH I think the more appropriate solution would be to have vfio-pci register
> its own fault handler, wherein it can properly deal with rate-limiting
> and/or entirely suppressing fault reports from misbehaving userspace, and if
> and when it does want to log something it is then free to do that in
> whatever format it wants, independent of the underlying IOMMU driver.
+1
Jason
^ permalink raw reply
* Re: [PATCH] iommu: Allow device driver to use its own PASID space for SVA
From: Jason Gunthorpe @ 2026-05-18 17:52 UTC (permalink / raw)
To: Joonwon Kang
Cc: kirill.shutemov, Alexander.Grest, alexander.shishkin, amhetre,
baolu.lu, bp, dave.hansen, easwar.hariharan, hpa, iommu,
jacob.jun.pan, joro, jpb, kas, kees, kevin.tian, linux-arm-kernel,
linux-kernel, mingo, nicolinc, peterz, praan, robin.murphy,
ryasuoka, smostafa, sohil.mehta, tglx, will, x86, xin
In-Reply-To: <20260518090654.730478-1-joonwonkang@google.com>
On Mon, May 18, 2026 at 09:06:54AM +0000, Joonwon Kang wrote:
> > On Fri, May 15, 2026 at 09:46:05AM +0000, Joonwon Kang wrote:
> > > diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> > > index 0ca3912ecb7f..61e2e52105e5 100644
> > > --- a/arch/x86/kernel/traps.c
> > > +++ b/arch/x86/kernel/traps.c
> > > @@ -864,6 +864,8 @@ static bool try_fixup_enqcmd_gp(void)
> > > return false;
> > >
> > > pasid = mm_get_enqcmd_pasid(current->mm);
> > > + if (pasid == IOMMU_PASID_INVALID)
> > > + return false;
> >
> > If you do this then probably you should get rid of mm_valid_pasid(),
> > mm_get_enqcmd_pasid() already has the NULL check so the two functions
> > are kind of pointless.
> >
> > You also missed the other place calling mm_valid_pasid() that should
> > really be sensitive to this as well:
> >
> > static int prctl_enable_tagged_addr(struct mm_struct *mm, unsigned long nr_bits)
> > {
> > [..]
> > if (mm_valid_pasid(mm) &&
> > !test_bit(MM_CONTEXT_FORCE_TAGGED_SVA, &mm->context.flags))
> > return -EINVAL;
> >
> > Make that removal a prep patch
> >
>
> Thanks for pointing this out. I think mm_valid_pasid() is to check if SVA
> is currently in action while mm_get_enqcmd_pasid() is to get the PASID for
> "ENQCMD instruction execution".
> Since it is now possible with this patch to activate SVA without involving
> EL0(for ENQCMD-like instructions),
I see, this thing about which is about LAM should remain, yes
But all the "EL0" machinery about trapping and enabling ENQCMD should
be moved over to mm_get_enqcmd_pasid() and never call mm_valid_pasid()
Jason
^ permalink raw reply
* Re: [PATCH v1] virt: arm-cca-guest: use raw variant of smp_processor_id() in arm_cca_report_new()
From: Catalin Marinas @ 2026-05-18 17:21 UTC (permalink / raw)
To: Kohei Enju
Cc: Will Deacon, Sami Mujawar, Gavin Shan, Steven Price,
Suzuki K Poulose, linux-arm-kernel, linux-kernel
In-Reply-To: <agsSyRT7z-F5iBIp@FCCLS0092175.localdomain>
Hi Kohei,
On Mon, May 18, 2026 at 10:38:53PM +0900, Kohei Enju wrote:
> On 05/18 13:33, Catalin Marinas wrote:
> > On Mon, May 18, 2026 at 12:31:31PM +0900, Kohei Enju wrote:
> > > diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> > > index 0c9ea24a200c..2d450caee3e4 100644
> > > --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> > > +++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> > > @@ -108,7 +108,7 @@ static int arm_cca_report_new(struct tsm_report *report, void *data)
> > > * allocate outblob based on the returned value from the 'init'
> > > * call and that cannot be done in an atomic context.
> > > */
> > > - cpu = smp_processor_id();
> > > + cpu = raw_smp_processor_id();
> >
> > That's just hiding the warning which might be genuine, irrespective of
> > what the comment says. Sashiko has some good points:
> >
> > https://sashiko.dev/#/patchset/20260518033157.1865498-1-enju.kohei@fujitsu.com
> >
> > Basically what guarantees that the cpu won't go offline? Can we use
> > migrate_disable() and ignore the smp_call_function_single() altogether?
> > It looks like a hack anyway.
[...]
> You've raised a very valid point about raw_smp_processor_id()
> potentially hiding a genuine issue. I agree this would be a concern in
> most contexts.
>
> However, this implementation was intentionally designed not to block CPU
> hotplug:
> https://lore.kernel.org/linux-arm-kernel/7a83461d-40fd-4e61-8833-5dae2abaf82b@arm.com/
>
> As mentioned in the thread above, the potential failure from the target
> CPU going offline (resulting in -ENXIO) is an expected and tolerated
> condition in this path.
> Using migrate_disable() would go against the non-blocking design goal.
>
> Given the context, the debug warning looks false positive for our
> specific use case to me, and I believe raw_smp_processor_id() correctly
> reflects the design intent by simply acquiring a CPU number without
> debug checks.
Thanks, I wasn't aware of the old discussion. If user-space can
tolerate, than it's fine.
Would you mind updating the comment above the changed line? It talks
about not allocating memory in atomic context, so migrate_disable()
would solve this. Just mention that it can't block CPU hotplug events
either and user-space can handle spurious errors.
With that:
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply
* Re: [PATCH v1] regulator: Use named initializers for arrays of i2c_device_data
From: Mark Brown @ 2026-05-18 17:13 UTC (permalink / raw)
To: Woody Douglass
Cc: Laurent Pinchart, Uwe Kleine-König (The Capable Hub),
Liam Girdwood, Markus Schneider-Pargmann, Michael Hennerich,
Support Opensource, Ivaylo Ivanov, Claudiu Beznea, Andrei Simion,
Saravanan Sekar, Matthias Brugger, AngeloGioacchino Del Regno,
Jagan Teki, Icenowy Zheng, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org
In-Reply-To: <54168033-c968-4565-afe8-2f1f8547ddf0@carnegierobotics.com>
[-- Attachment #1: Type: text/plain, Size: 469 bytes --]
On Mon, May 18, 2026 at 05:07:46PM +0000, Woody Douglass wrote:
> On 5/15/26 08:28, Laurent Pinchart wrote:
> > CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender.
Please delete unneeded context from mails when replying. Doing this
makes it much easier to find your reply in the message, helping ensure
it won't be missed by people scrolling through the irrelevant quoted
material.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v1] regulator: Use named initializers for arrays of i2c_device_data
From: Woody Douglass @ 2026-05-18 17:07 UTC (permalink / raw)
To: Laurent Pinchart, Uwe Kleine-König (The Capable Hub)
Cc: Liam Girdwood, Mark Brown, Markus Schneider-Pargmann,
Michael Hennerich, Support Opensource, Ivaylo Ivanov,
Claudiu Beznea, Andrei Simion, Saravanan Sekar, Matthias Brugger,
AngeloGioacchino Del Regno, Jagan Teki, Icenowy Zheng,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org
In-Reply-To: <20260515122816.GB52035@killaraus.ideasonboard.com>
On 5/15/26 08:28, Laurent Pinchart wrote:
> CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender.
>
>
> Hi Uwe,
>
> Thank you for the patch.
>
> On Fri, May 15, 2026 at 12:31:50PM +0200, Uwe Kleine-König (The Capable Hub) wrote:
>> While being less compact, using named initializers allows to more easily
>> see which members of the structs are assigned which value without having
>> to lookup the declaration of the struct. And it's also more robust
>> against changes to the struct definition.
>>
>> The mentioned robustness is relevant for a planned change to struct
>> i2c_device_id that replaces .driver_data by an anonymous union.
>>
>> While touching all these arrays, unify usage of whitespace and commas.
>>
>> This patch doesn't modify the compiled arrays, only their representation
>> in source form benefits. The former was confirmed with x86 and arm64
>> builds.
>>
>> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
>> ---
>> Hello,
>>
>> the mentioned change to i2c_device_id is the following:
>>
>> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
>> index 23ff24080dfd..aebd3a5e90af 100644
>> --- a/include/linux/mod_devicetable.h
>> +++ b/include/linux/mod_devicetable.h
>> @@ -477,7 +477,11 @@ struct rpmsg_device_id {
>>
>> struct i2c_device_id {
>> char name[I2C_NAME_SIZE];
>> - kernel_ulong_t driver_data; /* Data private to the driver */
>> + union {
>> + /* Data private to the driver */
>> + kernel_ulong_t driver_data;
>> + const void *driver_data_ptr;
>> + };
>> };
>>
>> /* pci_epf */
>>
>> and this requires that .driver_data is assigned via a named initializer
>> for static data. This requirement isn't a bad one because named
>> initializers are also much better readable than list initializers.
>>
>> The union added to struct i2c_device_id enables further cleanups like:
>>
>> diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c
>> index 0123ca8157a8..dfb0b07500a7 100644
>> --- a/drivers/regulator/ad5398.c
>> +++ b/drivers/regulator/ad5398.c
>> @@ -207,8 +207,8 @@ struct ad5398_current_data_format {
>> static const struct ad5398_current_data_format df_10_4_120 = {10, 4, 0, 120000};
>>
>> static const struct i2c_device_id ad5398_id[] = {
>> - { .name = "ad5398", .driver_data = (kernel_ulong_t)&df_10_4_120 },
>> - { .name = "ad5821", .driver_data = (kernel_ulong_t)&df_10_4_120 },
>> + { .name = "ad5398", .driver_data_ptr = &df_10_4_120 },
>> + { .name = "ad5821", .driver_data_ptr = &df_10_4_120 },
>> { }
>> };
>> MODULE_DEVICE_TABLE(i2c, ad5398_id);
>> @@ -219,8 +219,7 @@ static int ad5398_probe(struct i2c_client *client)
>> struct regulator_init_data *init_data = dev_get_platdata(&client->dev);
>> struct regulator_config config = { };
>> struct ad5398_chip_info *chip;
>> - const struct ad5398_current_data_format *df =
>> - (struct ad5398_current_data_format *)id->driver_data;
>> + const struct ad5398_current_data_format *df = id->driver_data;
>>
>> chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
>> if (!chip)
>>
>> that are an improvement for readability (again!) and it keeps some
>> properties of the pointers (here: being const) without having to pay
>> attention for that.
>>
>> My additional motivation for this effort is CHERI[1]. This is a hardware
>> extension that uses 128 bit pointers but unsigned long is still 64 bit.
>> So with CHERI you cannot store pointers in unsigned long variables.
>>
>> Best regards
>> Uwe
>>
>> [1] https://cheri-alliance.org/discover-cheri/
>> https://lwn.net/Articles/1037974/
>>
>> drivers/regulator/88pg86x.c | 4 +--
>> drivers/regulator/ad5398.c | 4 +--
>> drivers/regulator/da9121-regulator.c | 20 +++++++--------
>> drivers/regulator/da9210-regulator.c | 4 +--
>> drivers/regulator/da9211-regulator.c | 18 +++++++-------
>> drivers/regulator/fan53880.c | 4 +--
>> drivers/regulator/isl9305.c | 4 +--
>> drivers/regulator/lp3971.c | 2 +-
>> drivers/regulator/lp3972.c | 2 +-
>> drivers/regulator/lp872x.c | 34 +++++++++++++-------------
>> drivers/regulator/lp8755.c | 4 +--
>> drivers/regulator/ltc3589.c | 6 ++---
>> drivers/regulator/ltc3676.c | 2 +-
>> drivers/regulator/max1586.c | 2 +-
>> drivers/regulator/max20086-regulator.c | 8 +++---
>> drivers/regulator/max20411-regulator.c | 2 +-
>> drivers/regulator/max77503-regulator.c | 2 +-
>> drivers/regulator/max77675-regulator.c | 2 +-
>> drivers/regulator/max77826-regulator.c | 2 +-
>> drivers/regulator/max77838-regulator.c | 2 +-
>> drivers/regulator/max77857-regulator.c | 8 +++---
>> drivers/regulator/max8649.c | 2 +-
>> drivers/regulator/max8893.c | 2 +-
>> drivers/regulator/max8952.c | 2 +-
>> drivers/regulator/mcp16502.c | 2 +-
>> drivers/regulator/mp5416.c | 6 ++---
>> drivers/regulator/mp8859.c | 4 +--
>> drivers/regulator/mp886x.c | 6 ++---
>> drivers/regulator/mpq7920.c | 4 +--
>> drivers/regulator/mt6311-regulator.c | 4 +--
>> drivers/regulator/pf530x-regulator.c | 8 +++---
>> drivers/regulator/pf8x00-regulator.c | 8 +++---
>> drivers/regulator/pv88060-regulator.c | 4 +--
>> drivers/regulator/pv88080-regulator.c | 8 +++---
>> drivers/regulator/pv88090-regulator.c | 4 +--
>> drivers/regulator/slg51000-regulator.c | 4 +--
>> drivers/regulator/sy8106a-regulator.c | 2 +-
>> drivers/regulator/sy8824x.c | 8 +++---
>> drivers/regulator/sy8827n.c | 4 +--
>> drivers/regulator/tps6286x-regulator.c | 10 ++++----
>> drivers/regulator/tps6287x-regulator.c | 10 ++++----
>> 41 files changed, 119 insertions(+), 119 deletions(-)
> [snip]
>
>> diff --git a/drivers/regulator/pf530x-regulator.c b/drivers/regulator/pf530x-regulator.c
>> index f789c4b6a499..e7b13d60106b 100644
>> --- a/drivers/regulator/pf530x-regulator.c
>> +++ b/drivers/regulator/pf530x-regulator.c
>> @@ -353,10 +353,10 @@ static const struct of_device_id pf530x_dt_ids[] = {
>> MODULE_DEVICE_TABLE(of, pf530x_dt_ids);
>>
>> static const struct i2c_device_id pf530x_i2c_id[] = {
>> - { "pf5300", 0 },
>> - { "pf5301", 0 },
>> - { "pf5302", 0 },
>> - {},
>> + { .name = "pf5300", .driver_data = 0 },
>> + { .name = "pf5301", .driver_data = 0 },
>> + { .name = "pf5302", .driver_data = 0 },
> I think you can drop driver_data here. It doesn't appear to be used by
> the driver.
I can confirm this, the pf530x driver does not use the driver_data
member. This is an improvement, thank you!
Reviewed-by: Woodrow Douglass <wdouglass@carnegierobotics.com>
> I like the result overall. With this small issue addressed,
>
> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>
>> + { }
>> };
>> MODULE_DEVICE_TABLE(i2c, pf530x_i2c_id);
>>
> [snip]
>
> --
> Regards,
>
> Laurent Pinchart
^ permalink raw reply
* [PATCH 2/2] PCI: meson: Add missing remove callback
From: Shuvam Pandey @ 2026-05-18 16:59 UTC (permalink / raw)
To: Jingoo Han, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Bjorn Helgaas, Yue Wang,
Neil Armstrong
Cc: Rob Herring, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Fan Ni, Shradha Todi, Hanjie Lin, linux-pci, linux-amlogic,
linux-arm-kernel, linux-kernel
meson_pcie_probe() powers on the PHY and registers the DesignWare host
bridge with dw_pcie_host_init(), but the driver has no remove callback.
On driver unbind or module unload, the driver core therefore proceeds to
devres cleanup without first unregistering the host bridge or powering off
the PHY.
Add a remove callback that deinitializes the DesignWare host bridge and
powers off the PHY while device-managed resources are still valid.
Fixes: 9c0ef6d34fdb ("PCI: amlogic: Add the Amlogic Meson PCIe controller driver")
Signed-off-by: Shuvam Pandey <shuvampandey1@gmail.com>
---
drivers/pci/controller/dwc/pci-meson.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 0694084f6..c96e2244a 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -451,6 +451,14 @@ static int meson_pcie_probe(struct platform_device *pdev)
return ret;
}
+static void meson_pcie_remove(struct platform_device *pdev)
+{
+ struct meson_pcie *mp = platform_get_drvdata(pdev);
+
+ dw_pcie_host_deinit(&mp->pci.pp);
+ meson_pcie_power_off(mp);
+}
+
static const struct of_device_id meson_pcie_of_match[] = {
{
.compatible = "amlogic,axg-pcie",
@@ -464,6 +472,7 @@ MODULE_DEVICE_TABLE(of, meson_pcie_of_match);
static struct platform_driver meson_pcie_driver = {
.probe = meson_pcie_probe,
+ .remove = meson_pcie_remove,
.driver = {
.name = "meson-pcie",
.of_match_table = meson_pcie_of_match,
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox