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; > > > > > ``` > > > > > > >
