of_drm_find_bridge() is deprecated. Move to its replacement
of_drm_find_and_get_bridge() which gets a bridge reference, and ensure it
is put when done.
dw_hdmi->bridge is used only in dw_hdmi_top_thread_irq(), so in order to
avoid potential use-after-free ensure the irq is freed before putting the
dw_hdmi->bridge reference.
Acked-by: Maxime Ripard <mripard@kernel.org>
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
---
drivers/gpu/drm/meson/meson_dw_hdmi.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index 0d7c68b29dff..fef1702acb14 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -778,7 +778,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
if (IS_ERR(meson_dw_hdmi->hdmi))
return PTR_ERR(meson_dw_hdmi->hdmi);
- meson_dw_hdmi->bridge = of_drm_find_bridge(pdev->dev.of_node);
+ meson_dw_hdmi->bridge = of_drm_find_and_get_bridge(pdev->dev.of_node);
DRM_DEBUG_DRIVER("HDMI controller initialized\n");
@@ -789,8 +789,12 @@ static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
void *data)
{
struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+ int irq = platform_get_irq(pdev, 0);
+ devm_free_irq(dev, irq, meson_dw_hdmi);
dw_hdmi_unbind(meson_dw_hdmi->hdmi);
+ drm_bridge_put(meson_dw_hdmi->bridge);
}
static const struct component_ops meson_dw_hdmi_ops = {
--
2.52.0
Hi Luca,
On Fri, Jan 9, 2026 at 11:03 AM Luca Ceresoli <luca.ceresoli@bootlin.com> wrote:
>
> of_drm_find_bridge() is deprecated. Move to its replacement
> of_drm_find_and_get_bridge() which gets a bridge reference, and ensure it
> is put when done.
>
> dw_hdmi->bridge is used only in dw_hdmi_top_thread_irq(), so in order to
> avoid potential use-after-free ensure the irq is freed before putting the
> dw_hdmi->bridge reference.
>
> Acked-by: Maxime Ripard <mripard@kernel.org>
> Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
[...]
> @@ -789,8 +789,12 @@ static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
> void *data)
> {
> struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
> + struct platform_device *pdev = to_platform_device(dev);
> + int irq = platform_get_irq(pdev, 0);
>
> + devm_free_irq(dev, irq, meson_dw_hdmi);
I have one question (so I can understand things better):
is there a particular reason why you went with free'ing the IRQ
instead of "just" masking it (so the hardware won't fire anymore of
those IRQs)?
Best regards,
Martin
Hello Martin,
On Mon Jan 12, 2026 at 11:21 PM CET, Martin Blumenstingl wrote:
> Hi Luca,
>
> On Fri, Jan 9, 2026 at 11:03 AM Luca Ceresoli <luca.ceresoli@bootlin.com> wrote:
>>
>> of_drm_find_bridge() is deprecated. Move to its replacement
>> of_drm_find_and_get_bridge() which gets a bridge reference, and ensure it
>> is put when done.
>>
>> dw_hdmi->bridge is used only in dw_hdmi_top_thread_irq(), so in order to
>> avoid potential use-after-free ensure the irq is freed before putting the
>> dw_hdmi->bridge reference.
>>
>> Acked-by: Maxime Ripard <mripard@kernel.org>
>> Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
> Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>
> [...]
>> @@ -789,8 +789,12 @@ static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
>> void *data)
>> {
>> struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
>> + struct platform_device *pdev = to_platform_device(dev);
>> + int irq = platform_get_irq(pdev, 0);
>>
>> + devm_free_irq(dev, irq, meson_dw_hdmi);
> I have one question (so I can understand things better):
> is there a particular reason why you went with free'ing the IRQ
> instead of "just" masking it (so the hardware won't fire anymore of
> those IRQs)?
One reason is symmetry: _bind requests the irq, so _unbind does the
reverse.
Another is I don't have the hardware, so I wanted my changes to be as small
and clear as possible.
In principle one could request/free the irq in probe/remove and then
enable/disable it in bind/unbind. Whether it would be a good or bad idea I
don't know, but surely it would be more complex and I wouldn't want to do
it without any chance to test it on hardware.
Also, that would only optimize the case of multiple bind/unbind cycles,
which are not quite realistic without bridge hotplug. And brigde hotplug
does not exist yet in mainline, and when it will arrive it will be used
only for a few use cases.
I hope this answers your question.
Best regards,
Luca
--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Hi Luca,
On Tue, Jan 13, 2026 at 6:31 PM Luca Ceresoli <luca.ceresoli@bootlin.com> wrote:
[...]
> >> @@ -789,8 +789,12 @@ static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
> >> void *data)
> >> {
> >> struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
> >> + struct platform_device *pdev = to_platform_device(dev);
> >> + int irq = platform_get_irq(pdev, 0);
> >>
> >> + devm_free_irq(dev, irq, meson_dw_hdmi);
> > I have one question (so I can understand things better):
> > is there a particular reason why you went with free'ing the IRQ
> > instead of "just" masking it (so the hardware won't fire anymore of
> > those IRQs)?
>
> One reason is symmetry: _bind requests the irq, so _unbind does the
> reverse.
>
> Another is I don't have the hardware, so I wanted my changes to be as small
> and clear as possible.
Understood, thanks!
> In principle one could request/free the irq in probe/remove and then
> enable/disable it in bind/unbind. Whether it would be a good or bad idea I
> don't know, but surely it would be more complex and I wouldn't want to do
> it without any chance to test it on hardware.
>
> Also, that would only optimize the case of multiple bind/unbind cycles,
> which are not quite realistic without bridge hotplug. And brigde hotplug
> does not exist yet in mainline, and when it will arrive it will be used
> only for a few use cases.
>
> I hope this answers your question.
Yes, I was curious whether you considered devm_free_irq() as the only
"correct" approach (in this case I would have recommended a comment)
or whether other approaches are fine too.
This is useful knowledge for me in case we ever need to restructure the driver.
Best regards,
Martin
On 1/9/26 11:02, Luca Ceresoli wrote:
> of_drm_find_bridge() is deprecated. Move to its replacement
> of_drm_find_and_get_bridge() which gets a bridge reference, and ensure it
> is put when done.
>
> dw_hdmi->bridge is used only in dw_hdmi_top_thread_irq(), so in order to
> avoid potential use-after-free ensure the irq is freed before putting the
> dw_hdmi->bridge reference.
>
> Acked-by: Maxime Ripard <mripard@kernel.org>
> Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
> ---
> drivers/gpu/drm/meson/meson_dw_hdmi.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> index 0d7c68b29dff..fef1702acb14 100644
> --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
> +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
> @@ -778,7 +778,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
> if (IS_ERR(meson_dw_hdmi->hdmi))
> return PTR_ERR(meson_dw_hdmi->hdmi);
>
> - meson_dw_hdmi->bridge = of_drm_find_bridge(pdev->dev.of_node);
> + meson_dw_hdmi->bridge = of_drm_find_and_get_bridge(pdev->dev.of_node);
>
> DRM_DEBUG_DRIVER("HDMI controller initialized\n");
>
> @@ -789,8 +789,12 @@ static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
> void *data)
> {
> struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
> + struct platform_device *pdev = to_platform_device(dev);
> + int irq = platform_get_irq(pdev, 0);
>
> + devm_free_irq(dev, irq, meson_dw_hdmi);
> dw_hdmi_unbind(meson_dw_hdmi->hdmi);
> + drm_bridge_put(meson_dw_hdmi->bridge);
> }
>
> static const struct component_ops meson_dw_hdmi_ops = {
>
Acked-by: Neil Armstrong <neil.armstrong@linaro.org>
Thanks,
Neil
© 2016 - 2026 Red Hat, Inc.