On Sat 20 Jun 2026 08:18:41 PM , Christopher Snowhill wrote:
> 
> 
> On Sat 20 Jun 2026 07:49:30 PM , Christopher Snowhill wrote:
> > 
> > 
> > On Wed 17 Jun 2026 10:32:51 AM , Leo Li wrote:
> > > 
> > > 
> > > On 2026-06-17 00:35, Matthew Schwartz wrote:
> > > > On 6/16/26 1:18 PM, [email protected] wrote:
> > > > 
> > > > [...]
> > > > 
> > > >> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c 
> > > >> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
> > > >> index c9916ed0ddc14..8a6b732cf80c8 100644
> > > >> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
> > > >> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
> > > >> @@ -281,7 +281,14 @@ static inline int 
> > > >> amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
> > > >>                        drm_crtc_vblank_restore(crtc);
> > > >>        }
> > > >>  
> > > >> -      if (dc_supports_vrr(dm->dc->ctx->dce_version)) {
> > > >> +      /*
> > > >> +       * On DCN, VUPDATE_NO_LOCK is the single OTG interrupt used to 
> > > >> deliver
> > > >> +       * vblank and pageflip completion events, so enable it whenever 
> > > >> vblank
> > > >> +       * is enabled. On DCE, vupdate is only needed in VRR mode.
> > > >> +       */
> > > >> +      if (amdgpu_ip_version(adev, DCE_HWIP, 0) != 0) {
> > > >> +              rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, enable);
> > > >> +      } else if (dc_supports_vrr(dm->dc->ctx->dce_version)) {
> > > > 
> > > > Hi Leo (dropping Stable),
> > > > 
> > > > This arms VUPDATE_NO_LOCK on all of DCN, but 
> > > > amdgpu_dm_handle_vrr_transition() still disables it when switching from 
> > > > VRR active -> inactive. This causes a new flip_done timed out event 
> > > > when a compositor like gamescope disables VRR while it's already active.
> > > 
> > > Good catch, I wonder why the kms_vrr IGT tests did not catch this...
> > > I'll roll your fix into v2 with your signed-off-by and co-authored-by.
> > > 
> > > Thanks,
> > > Leo
> > 
> > The Stable backport is also needed for 7.1.1. I tested it specifically
> > there, and ran into the same exact VRR transition issue, unknowingly.
> > Except in this case, it was with LabWC, configured with VRR set to
> > fullscreen only, so it was disabling it immediately on configure. Oh
> > well. I'm building 7.1.1 with the backport and this workaround rolled
> > into it now, and will report back if there are any further issues.
> > 
> > -Christopher
> 
> Dang, looks like I don't get a free pass with this patch, since the
> function in question doesn't plumb that state directly in 7.1.1.

Looks like I can do some backporting too. Here's a free backport of the
same patch series to 7.1.1:

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index c198a0b..da7ed11 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -9851,8 +9851,16 @@ static void update_stream_irq_parameters(
 static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,
                                            struct dm_crtc_state *new_state)
 {
+       struct amdgpu_device *adev = drm_to_adev(new_state->base.crtc->dev);
        bool old_vrr_active = amdgpu_dm_crtc_vrr_active(old_state);
        bool new_vrr_active = amdgpu_dm_crtc_vrr_active(new_state);
+       /*
+        * On DCN, VUPDATE_NO_LOCK is the sole vblank and pageflip completion
+        * source and amdgpu_dm_crtc_set_vblank() keeps it armed whenever
+        * vblank is enabled, so it must not be toggled with the VRR state.
+        * Only DCE gates vupdate on VRR.
+        */
+       bool vrr_gates_vupdate = amdgpu_ip_version(adev, DCE_HWIP, 0) == 0;

        if (!old_vrr_active && new_vrr_active) {
                /* Transition VRR inactive -> active:
@@ -9863,7 +9871,8 @@ static void amdgpu_dm_handle_vrr_transition(struct
dm_crtc_state *old_state,
                 * We also need vupdate irq for the actual core vblank
handling
                 * at end of vblank.
                 */
-               WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc,
true) != 0);
+               if (vrr_gates_vupdate)
+
WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 0);
                WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0);
                drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR
off->on: Get vblank ref\n",
                                 __func__, new_state->base.crtc->base.id);
@@ -9871,7 +9880,8 @@ static void amdgpu_dm_handle_vrr_transition(struct
dm_crtc_state *old_state,
                /* Transition VRR active -> inactive:
                 * Allow vblank irq disable again for fixed refresh rate.
                 */
-               WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc,
false) != 0);
+               if (vrr_gates_vupdate)
+
WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 0);
                drm_crtc_vblank_put(new_state->base.crtc);
                drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u VRR
on->off: Drop vblank ref\n",
                                 __func__, new_state->base.crtc->base.id);


Cool, only one line changed. And no need to plumb the function
parameter.

> 
> > 
> > > 
> > > > 
> > > > I had to fix it up with something like:
> > > > 
> > > > diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
> > > > b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > index e09c0eb9f865..ee337ca816cf 100644
> > > > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> > > > @@ -10085,8 +10085,16 @@ static void 
> > > > amdgpu_dm_handle_vrr_transition(struct amdgpu_display_manager *dm,
> > > >                                             struct dm_crtc_state 
> > > > *old_state,
> > > >                                             struct dm_crtc_state 
> > > > *new_state)
> > > >  {
> > > > +       struct amdgpu_device *adev = dm->adev;
> > > >         bool old_vrr_active = amdgpu_dm_crtc_vrr_active(old_state);
> > > >         bool new_vrr_active = amdgpu_dm_crtc_vrr_active(new_state);
> > > > +       /*
> > > > +        * On DCN, VUPDATE_NO_LOCK is the sole vblank and pageflip 
> > > > completion
> > > > +        * source and amdgpu_dm_crtc_set_vblank() keeps it armed 
> > > > whenever
> > > > +        * vblank is enabled, so it must not be toggled with the VRR 
> > > > state.
> > > > +        * Only DCE gates vupdate on VRR.
> > > > +        */
> > > > +       bool vrr_gates_vupdate = amdgpu_ip_version(adev, DCE_HWIP, 0) 
> > > > == 0;
> > > >  
> > > >         if (!old_vrr_active && new_vrr_active) {
> > > >                 /* Transition VRR inactive -> active:
> > > > @@ -10097,7 +10105,8 @@ static void 
> > > > amdgpu_dm_handle_vrr_transition(struct amdgpu_display_manager *dm,
> > > >                  * We also need vupdate irq for the actual core vblank 
> > > > handling
> > > >                  * at end of vblank.
> > > >                  */
> > > > -               
> > > > WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 
> > > > 0);
> > > > +               if (vrr_gates_vupdate)
> > > > +                       
> > > > WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 
> > > > 0);
> > > >                 WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0);
> > > >                 drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u 
> > > > VRR off->on: Get vblank ref\n",
> > > >                                  __func__, 
> > > > new_state->base.crtc->base.id);
> > > > @@ -10113,7 +10122,8 @@ static void 
> > > > amdgpu_dm_handle_vrr_transition(struct amdgpu_display_manager *dm,
> > > >                 /* Transition VRR active -> inactive:
> > > >                  * Allow vblank irq disable again for fixed refresh 
> > > > rate.
> > > >                  */
> > > > -               
> > > > WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 
> > > > 0);
> > > > +               if (vrr_gates_vupdate)
> > > > +                       
> > > > WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 
> > > > 0);
> > > >                 drm_crtc_vblank_put(new_state->base.crtc);
> > > >                 drm_dbg_driver(new_state->base.crtc->dev, "%s: crtc=%u 
> > > > VRR on->off: Drop vblank ref\n",
> > > >                                  __func__, 
> > > > new_state->base.crtc->base.id);
> > > > 
> > > > Feel free to fold some version of this into the next version if it 
> > > > makes sense, or pick it up with my s-o-b.
> > > > 
> > > > Thanks,
> > > > Matthew
> > > > 
> > > 

Attachment: signature.asc
Description: PGP signature

Reply via email to