Public

Reviewed-by: Roman Li <[email protected]>

> -----Original Message-----
> From: amd-gfx <[email protected]> On Behalf Of Mattia
> Tadini
> Sent: Saturday, September 19, 2026 4:26 PM
> To: Wentland, Harry <[email protected]>; Li, Sun peng (Leo)
> <[email protected]>; Rodrigo Siqueira <[email protected]>; Deucher,
> Alexander <[email protected]>; Koenig, Christian
> <[email protected]>; David Airlie <[email protected]>; Simona Vetter
> <[email protected]>
> Cc: [email protected]; [email protected]; linux-
> [email protected]
> Subject: [PATCH] drm/amd/display: only clear the hotplug sources the ASIC has
>
> [Some people who received this message don't often get email from
> [email protected]. Learn why this is important at
> https://aka.ms/LearnAboutSenderIdentification ]
>
> amdgpu_dm_hpd_init() clears every hotplug source in the enum before enabling 
> the
> ones it needs:
>
>         for (i = DC_IRQ_SOURCE_HPD1; i <= DC_IRQ_SOURCE_HPD6RX; i++)
>
> DC fills the unused slots of its interrupt table with dummy handlers that 
> assert when
> touched, so on an ASIC with fewer than six HPD lines that sweep warns and 
> taints
> the kernel. DCN 2.0.1 has two:
> mmHPD0_DC_HPD_INT_CONTROL and mmHPD1_DC_HPD_INT_CONTROL
> are the only hotplug registers in dcn_2_0_1_offset.h, against five in
> dcn_2_1_0_offset.h, and irq_service_dcn201.c defines hpd_int_entry(0) and (1)
> accordingly.
>
> On an AMD BC-250, which appears to be the only GPU using DCN 201, every boot
> produces this for sources 3 to 6:
>
>   [drm] *ERROR* dal_irq_service_dummy_ack: called for
>       non-implemented irq source, src_id=0, ext_id=0
>   [drm] dal_irq_service_set: src: 3, st: 0
>   WARNING: .../display/dc/irq/irq_service.c:129
>       at dal_irq_service_set.cold+0x2d/0x76 [amdgpu]
>    dal_irq_service_set+0x4c/0x100 [amdgpu]
>    amdgpu_dm_hpd_init.cold+0x15/0x12e [amdgpu]
>    dm_hw_init+0x4c/0x170 [amdgpu]
>    amdgpu_device_init.cold+0x1727/0x1ec0 [amdgpu]
>
> and the machine comes up tainted W, which makes every unrelated bug report 
> from
> it harder to read.
>
> Walk the links this ASIC has instead of the whole enum, and skip a link with 
> no
> hotplug line of its own, which is the same guard the enable loop further down
> already applies. A source owned by a real link is implemented by definition, 
> so the
> dummy handlers are no longer reached.
> Parts with six HPD lines are unaffected.
>
> Signed-off-by: Mattia Tadini <[email protected]>
> ---
>
> Tested on an ASRock AMD BC-250 (Cyan Skillfish, DCN 2.0.1, two HPD lines),
> kernel 7.2.6, across reboots before and after the change:
>
>   before:  2 WARN splats and 8 error lines per boot, for sources 3 to 6
>            /proc/sys/kernel/tainted = 12864
>   after:   no dummy_ack, no irq_service warning, no call trace at all
>            /proc/sys/kernel/tainted = 12352
>
> The 512 that goes away is the W bit. What is left comes from an unrelated 
> out-of-
> tree module on that machine.
>
> Nothing regressed: both DisplayPort connectors still report the right status, 
> the
> driver logs no HPD failure, and amdgpu keeps servicing interrupts normally.
>
> I do not have an ASIC with six HPD lines to test the unchanged path on.
>  .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 22 ++++++++++++++-----
>  1 file changed, 17 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
> index e49803a..b0ede5d 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
> @@ -903,11 +903,23 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
>         int i;
>         bool use_polling = false;
>
> -       /* First, clear all hpd and hpdrx interrupts */
> -       for (i = DC_IRQ_SOURCE_HPD1; i <= DC_IRQ_SOURCE_HPD6RX; i++) {
> -               if (!dc_interrupt_set(adev->dm.dc, i, false))
> -                       drm_err(dev, "Failed to clear hpd(rx) source=%d on 
> init\n",
> -                               i);
> +       /*
> +        * First, clear all hpd and hpdrx interrupts, over the links this ASIC
> +        * has rather than over the whole enum: the unused slots of the DC
> +        * interrupt table hold dummy handlers that assert when touched.
> +        */
> +       for (i = 0; i < adev->dm.dc->link_count; i++) {
> +               const struct dc_link *link = adev->dm.dc->links[i];
> +
> +               if (link->irq_source_hpd != DC_IRQ_SOURCE_INVALID &&
> +                   !dc_interrupt_set(adev->dm.dc, link->irq_source_hpd, 
> false))
> +                       drm_err(dev, "Failed to clear hpd source=%d on 
> init\n",
> +                               link->irq_source_hpd);
> +
> +               if (link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID &&
> +                   !dc_interrupt_set(adev->dm.dc, link->irq_source_hpd_rx, 
> false))
> +                       drm_err(dev, "Failed to clear hpdrx source=%d on 
> init\n",
> +                               link->irq_source_hpd_rx);
>         }
>
>         drm_connector_list_iter_begin(dev, &iter);
> --
> 2.55.0

Reply via email to