On Sun, 2026-10-18 at 13:01 +0200, Arjan Filius wrote:
> Hi Lyude,
> Just a friendly gentle ping on this patch whenever you have a chance
> to take a look.
> No rush if you're still swamped with runtime PM work, but wanted to
> check in to see if you need anything else from my side (or if you'd
> prefer me to resend it as a standalone [PATCH v2] formatted with git-
> format-patch).
> Thanks again for your time!

I will try to review this asap, unfortunately I am quite swamped and in
the middle of moving - so I need to focus on the stuff that's assigned
on my plate this week.

I think the one thing that would be appreciated is if you could re-add
the old commit message you had before generating the new one with an
LLM - it was easier to read IMO.

> Best regards,
> Arjan Filius
> 
> > On 5 Aug 2026, at 19:29, [email protected] wrote:
> > 
> > JFYI - going to try to review/test this ASAP, just been sidetracked
> > chasing some big runtime PM issues in nouveau atm :S
> > 
> > On Fri, 2026-07-17 at 10:15 +0200, Arjan Filius wrote:
> > > Hello Lyude,
> > > 
> > > Yes, I did use generative AI to help refine and structure this
> > > (old)
> > > patch.
> > > It is completely based on work/debug/fixing I had done manually
> > > few
> > > years back. 
> > > Generative AI helped me to send the message, but re-used my old
> > > patched code, brushed up a bit.
> > > And tested it this week on kernel 7.1.3, but previous tested on
> > > 6.8.0.x and 6.9.9 kernels.
> > > 
> > > In 2024 i submitted a bug report/fix/workaround (to prevent a
> > > full
> > > lockup every day) on the Freedesktop GitLab under Issue 377:
> > > https://gitlab.freedesktop.org/drm/nouveau/-/issues/377
> > > 
> > > Back then, my local workaround was a bit less elegant, and had a
> > > few
> > > extra checks/debug statements.
> > > I had almost forgotten about the issue since my workaround was
> > > running fine.
> > > When I recently booted up a clean mainline 7.1.3 kernel and saw
> > > the
> > > system freeze again within a day and every day, 
> > > and had to fsck my disks due to it, I remembered the fix I once
> > > debugged and posted in 2024. 
> > > I wanted to see if I could find a cleaner, more elegant solution
> > > and
> > > used AI for it, to see if the patch could be in a nicer place, 
> > > but ended up to basically reproduce the fix i had written in 2024
> > > (without AI).
> > > 
> > > 
> > > Regarding the two patches (A and B): 
> > > * **Patch B** was the version I compiled and tested locally with
> > > the
> > > `nvkm_warn()` statement
> > >   so I could verify in `dmesg` that the standby transitions were
> > > actually triggering the block and being safely bypassed.
> > > * **Patch A** is the exact same check but silent (without the
> > > warning
> > > logs).
> > > 
> > > To avoid any confusion i repeat my patch, which does not produce
> > > any
> > > logging every time, 
> > > but just avoids the lockup referencing null pointers when
> > > external
> > > displays goes to sleep.
> > > 
> > > 
> > > ```diff
> > > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > index 51c045bdfcbb..ab1bc0898def 100644
> > > --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > @@ -1157,6 +1157,10 @@ nv50_disp_super_2_2_dp(struct nvkm_head
> > > *head,
> > > struct nvkm_ior *ior)
> > >  {
> > >   struct nvkm_subdev *subdev = &head->disp->engine.subdev;
> > >  
> > > + /* If the DisplayPort link is inactive (0 lanes), skip
> > > configuration */
> > > + if (ior->dp.nr == 0)
> > > + return;
> > > +
> > >   const u32 khz = head->asy.hz / 1000;
> > >   const u32 linkKBps = ior->dp.bw * 27000;
> > >   const u32 symbol = 100000;
> > > ```
> > > 
> > > This completely fixes my lenovo T430(NVIDIA NVS 5400M) + 4338
> > > Dock
> > > and 2 external (multi-input) monitors freeze, proven over some
> > > years.
> > > At the time the nvidia kernel driver on my T430 became an issue
> > > wih
> > > newer kernels, and notice nouveau driver did pretty well too.
> > > 
> > > Hope this claries it.
> > > 
> > > Best regards,
> > > Arjan Filius
> > > 
> > > 
> > > > On 16 Jul 2026, at 22:40, [email protected] wrote:
> > > > 
> > > > Hi, can you please clarify whether or not you used generative
> > > > AI
> > > > for
> > > > this patch series? If so, this needs to be noted as part of the
> > > > commit
> > > > message. Additionally, both of these patches look to be
> > > > identical
> > > > except that one prints a message and the other doesn't. You can
> > > > just
> > > > send a single version, we will figure out how to handle that
> > > > part
> > > > after.
> > > > 
> > > > On Thu, 2026-07-16 at 16:55 +0200, Arjan Filius wrote:
> > > > > Dear Nouveau Maintainers,
> > > > >  
> > > > > Please find below a proposed patch to prevent a division-by-
> > > > > zero
> > > > > kernel oops and subsequent lockup in the Nouveau display
> > > > > supervisor
> > > > > engine when DisplayPort links transition to 0 active lanes.
> > > > > This
> > > > > bug
> > > > > was observed and patched/tested against the mainline kernel
> > > > > version
> > > > > **7.1.3**, but is present in all current upstream code.
> > > > >  
> > > > > ---
> > > > >  
> > > > > ### BRIEF EXPLANATION
> > > > >  
> > > > > During screen sleep transitions or multi-input display
> > > > > switches
> > > > > (KVM
> > > > > switching), the active lane count of a DisplayPort link can
> > > > > temporarily drop to 0 (`ior->dp.nr == 0`). 
> > > > >  
> > > > > When this occurs, the DisplayPort supervisor function
> > > > > `nv50_disp_super_2_2_dp` is invoked via modeset interrupts.
> > > > > Without
> > > > > an early-exit guard, the function attempts to perform
> > > > > symbols/hblank
> > > > > and link rate calculations that divide by `ior->dp.nr`,
> > > > > resulting
> > > > > in
> > > > > a kernel division-by-zero math exception, lockup, and system
> > > > > freeze.
> > > > >  
> > > > > This patch adds an early-exit check at the beginning of
> > > > > `nv50_disp_super_2_2_dp` to abort display configuration when
> > > > > the
> > > > > link
> > > > > training lanes count is zero.
> > > > > 
> > > > > *   **Tested Kernel Version:** `7.1.3` (mainline stable
> > > > > branch)
> > > > > 
> > > > > ---
> > > > > 
> > > > > ### EXTREMELY DETAILED TECHNICAL BREAKDOWN
> > > > > 
> > > > > #### 1. Hardware Context
> > > > > This bug has been consistently reproduced on a Lenovo
> > > > > ThinkPad
> > > > > T430
> > > > > (Intel HD 4000 + discrete NVIDIA NVS 5400M / GF108 chipset)
> > > > > connected
> > > > > to a Lenovo ThinkPad Mini Dock Plus Series 3 (Model 4338)
> > > > > with
> > > > > dual
> > > > > external monitors on dock DisplayPorts (`DP-2` and `DP-3`). 
> > > > > 
> > > > > #### 2. Root Cause Analysis (Code Level)
> > > > > Inside `drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c`,
> > > > > when
> > > > > `ior-
> > > > > > dp.nr == 0`, the driver executes the following lines in
> > > > > `nv50_disp_super_2_2_dp()`:
> > > > > 
> > > > > *   **Line 1179:** Calculations for horizontal blank symbols:
> > > > >     ```c
> > > > >     h = h - (3 * ior->dp.ef) - (12 / ior->dp.nr);
> > > > >     ```
> > > > > *   **Line 1185:** Calculations for vertical blank symbols:
> > > > >     ```c
> > > > >     v = v - ((36 / ior->dp.nr) + 3) - 1;
> > > > >     ```
> > > > > *   **Line 1190:** Calculations for active link data rate:
> > > > >     ```c
> > > > >     link_data_rate = (khz * head->asy.or.depth / 8) / ior-
> > > > > >dp.nr;
> > > > >     ```
> > > > > 
> > > > > In all three instances, the denominator `ior->dp.nr` is `0`,
> > > > > causing
> > > > > an immediate kernel math exception in the display workqueue
> > > > > (`nouveau_display_hpd_work` or `nv50_disp_super`), locking up
> > > > > the
> > > > > graphics pipeline, freezing the screen, and hanging any
> > > > > reboot
> > > > > attempts (requiring a physical hard reset).
> > > > > 
> > > > > #### 3. Daily Workday Trigger Scenario
> > > > > 1.  The T430 (via dock) and a secondary workstation are both
> > > > > connected to different inputs on the same external monitors.
> > > > > 2.  The monitors' input sources are switched to the secondary
> > > > > workstation.
> > > > > 3.  At the end of the day, the secondary workstation goes to
> > > > > sleep or
> > > > > is shut down.
> > > > > 4.  With no active inputs, the external monitors enter power-
> > > > > saving
> > > > > standby mode.
> > > > > 5.  When the user subsequently wakes up or interacts with the
> > > > > T430,
> > > > > the driver attempts a modeset refresh. Since the monitors are
> > > > > asleep
> > > > > and inputs are switched away, the lanes count is read as `0`,
> > > > > triggering the division-by-zero oops.
> > > > > 
> > > > > #### 4. Stack Trace (Oops Log)
> > > > > ```text
> > > > > [di jul 23 10:28:25 2024] nouveau 0000:01:00.0: DRM: DDC
> > > > > responded,
> > > > > but no EDID for DP-2
> > > > > [di jul 23 10:28:25 2024] nouveau 0000:01:00.0: DRM: DDC
> > > > > responded,
> > > > > but no EDID for DP-3
> > > > > [di jul 23 10:28:26 2024] Workqueue: nvkm-disp
> > > > > nv50_disp_super
> > > > > [nouveau]
> > > > > [di jul 23 10:28:26 2024] RIP:
> > > > > 0010:nv50_disp_super_2_2_dp+0xa7/0x320
> > > > > [nouveau]
> > > > > [di jul 23 10:28:26 2024]  ?
> > > > > nv50_disp_super_2_2_dp+0xa7/0x320
> > > > > [nouveau]
> > > > > [di jul 23 10:28:26 2024]  nv50_disp_super_2_2+0xf2/0x160
> > > > > [nouveau]
> > > > > [di jul 23 10:28:26 2024]  nv50_disp_super+0x139/0x280
> > > > > [nouveau]
> > > > > ```
> > > > > 
> > > > > #### 5. Verification Proof (Bypass Log)
> > > > > With the patch applied and running on kernel `7.1.3-custom
> > > > > #2`,
> > > > > the
> > > > > screen standby transition was bypassed cleanly. The driver
> > > > > caught
> > > > > the
> > > > > lane count of 0, bypassed display configuration, and
> > > > > proceeded to
> > > > > put
> > > > > the graphics chip into its low-power runtime suspend state
> > > > > (`suspended`) without locking up the OS:
> > > > > ```text
> > > > > [45162.232371] nouveau 0000:01:00.0: disp: DP link is
> > > > > inactive
> > > > > (lanes
> > > > > = 0), skipping display configuration.
> > > > > [45162.232402] nouveau 0000:01:00.0: disp: DP link is
> > > > > inactive
> > > > > (lanes
> > > > > = 0), skipping display configuration.
> > > > > [45178.605627] nouveau 0000:01:00.0: timeout
> > > > > [45178.605629] WARNING: nv50_disp_dmac_fini+0x168/0x1c0
> > > > > [nouveau]
> > > > > [45180.608524] nouveau 0000:01:00.0: disp: ch 1 fini timeout,
> > > > > 8e061008
> > > > > [45182.608521] nouveau 0000:01:00.0: timeout
> > > > > [45182.608523] WARNING: nv50_disp_core_fini+0x143/0x190
> > > > > [nouveau]
> > > > > ```
> > > > > 
> > > > > ---
> > > > > 
> > > > > Signed-off-by: Arjan Filius <[email protected]>
> > > > > ---
> > > > > 
> > > > > ### CHOOSE ONE OF THE PATCH OPTIONS BELOW TO APPEND:
> > > > > 
> > > > > #### OPTION A: The Silent Production Patch (RECOMMENDED FOR
> > > > > UPSTREAM)
> > > > > *Note: Kernel maintainers generally reject warnings or print
> > > > > spam
> > > > > for
> > > > > expected hardware sleep/disconnect transitions. A silent
> > > > > return
> > > > > is
> > > > > the preferred upstream pattern.*
> > > > > 
> > > > > ```diff
> > > > > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > > > b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > > > index 51c045bdfcbb..ab1bc0898def 100644
> > > > > --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > > > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > > > @@ -1157,6 +1157,10 @@ nv50_disp_super_2_2_dp(struct
> > > > > nvkm_head
> > > > > *head,
> > > > > struct nvkm_ior *ior)
> > > > >  {
> > > > >   struct nvkm_subdev *subdev = &head->disp-
> > > > > >engine.subdev;
> > > > >  
> > > > > + /* If the DisplayPort link is inactive (0 lanes),
> > > > > skip
> > > > > configuration */
> > > > > + if (ior->dp.nr == 0)
> > > > > + return;
> > > > > +
> > > > >   const u32 khz = head->asy.hz / 1000;
> > > > >   const u32 linkKBps = ior->dp.bw * 27000;
> > > > >   const u32 symbol = 100000;
> > > > > ```
> > > > > 
> > > > > #### OPTION B: The Warning/Verbose Patch (What was tested
> > > > > locally)
> > > > > *Note: Prints warning logs to the kernel buffer for
> > > > > validation
> > > > > and
> > > > > troubleshooting.*
> > > > > 
> > > > > ```diff
> > > > > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > > > b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > > > index 51c045bdfcbb..ab1bc0898def 100644
> > > > > --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > > > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
> > > > > @@ -1157,6 +1157,12 @@ nv50_disp_super_2_2_dp(struct
> > > > > nvkm_head
> > > > > *head,
> > > > > struct nvkm_ior *ior)
> > > > >  {
> > > > >   struct nvkm_subdev *subdev = &head->disp-
> > > > > >engine.subdev;
> > > > >  
> > > > > + /* If the DisplayPort link is inactive (0 lanes),
> > > > > skip
> > > > > configuration */
> > > > > + if (ior->dp.nr == 0) {
> > > > > + nvkm_warn(subdev, "DP link is inactive (lanes
> > > > > =
> > > > > 0),
> > > > > skipping display configuration.\n");
> > > > > + return;
> > > > > + }
> > > > > +
> > > > >   const u32 khz = head->asy.hz / 1000;
> > > > >   const u32 linkKBps = ior->dp.bw * 27000;
> > > > >   const u32 symbol = 100000;
> > > > > ```
> > > > 
> > 
> 

Reply via email to