From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D6DEE3CE096 for ; Wed, 5 Aug 2026 17:29:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785950963; cv=none; b=lIACPeO2NJ4ZOlALqtotUlKlO4YbigWZScffpstKI/54BDGWHC7u8vxFLQ8pzdcQ10c5b5iLvtoV8pVkQNxjQiHK3uhZ81c9OZ0NkMNc7blwU4G38vrJitFaYne0FMBIBGMygYOhkaRVwbm/yd7KQP6q1v5WfoqVcqmGhSF+3cA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785950963; c=relaxed/simple; bh=oQOSMCmWoRT9JLS2SlVcS5j+ssxKIpk6ugMCjmodD0k=; h=Message-ID:Subject:From:To:Cc:Date:In-Reply-To:References: Content-Type:MIME-Version; b=BmexsqWa1EQv96eDfsr/UoGHlnQjnQHFHeFkRG1Rc/3vO0bry+WbC5b7s1Jkw75ogk9UYRQ2VMfV+7PjyAC2NRP5qxXEzOLDDG6uvL25ezFF8fOTniLVapE+9GUo5Uj8UO4PRGHEw2W49RTU+IazeGqDAi5JfcwWqgUHhZzW8Bk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=SiPyu6//; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=oC5/bX6O; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="SiPyu6//"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="oC5/bX6O" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1785950960; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=f0EJjLd2CiUGDjKzo2WpgZtP8C/lKhszyy+rUI8pYGE=; b=SiPyu6//aPvjI+PNvjo2FQ2DksnUMRQcRk18jxP+JYpi6yfkiiOWZzJ7tpth3CzaQnl78x i//W1jGK7s/kL7Z3TQLti2dY8ynsa9LoBDzKojwYHycm5rEvOZsVx+TT3lfVA8rKVliqxr nVfcNzJT2lteHk2yVT7FMLNEyzuvCLI= Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-625-V02kXtQ1P_WNa78CUSuptQ-1; Wed, 05 Aug 2026 13:29:18 -0400 X-MC-Unique: V02kXtQ1P_WNa78CUSuptQ-1 X-Mimecast-MFC-AGG-ID: V02kXtQ1P_WNa78CUSuptQ_1785950958 Received: by mail-qk1-f198.google.com with SMTP id af79cd13be357-934993d0f39so150690085a.0 for ; Wed, 05 Aug 2026 10:29:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1785950957; x=1786555757; darn=vger.kernel.org; h=mime-version:user-agent:content-transfer-encoding:content-type :references:in-reply-to:date:cc:to:from:subject:message-id:from:to :cc:subject:date:message-id:reply-to:content-type; bh=f0EJjLd2CiUGDjKzo2WpgZtP8C/lKhszyy+rUI8pYGE=; b=oC5/bX6OEe6HMayTGlYtmW+9mgK8lcW2yPUOPeQZDygH6ipACElDir2E/O8pbGxs6T NsujIXmbc+6WngTVoH4aeH0creImIxyOVR9by/EP2B//AkCujVda4+9RUviYT1BlUMFi M0EoldC7IKy/bHpjqWufEsSsookyopuOIkBasTwq0Stg9sppM2OrygRg1ROnsv1xKEsN Zvu5QEbQy7CFCNZJRbyOzDfDrhHLu4Sye5K7IwksZjl6v7UqgVPWJFVXhVcXfa0JwsmF O3RAnpypAuSBWVQu1L4wJMvp805wghsVacB8RgCBPHsS/bpFTiisAeoeEKOL/VfZTzZM ZYCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785950957; x=1786555757; h=mime-version:user-agent:content-transfer-encoding:content-type :references:in-reply-to:date:cc:to:from:subject:message-id:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=f0EJjLd2CiUGDjKzo2WpgZtP8C/lKhszyy+rUI8pYGE=; b=SAnnaQimy0skNZ4yG7VdcFDK2sdqQPpDZZMgn3VFgPLaV/D4gnWa/RyswxwGh3R85P vPJbdwcjL5Zsq0ZzsOFXZPrvA30zAHHzeZsFacp1XhLYfvbGrmZsH34Z3hWTGOxDwLaj 8yd/LKSaojA4n3KkpFrlvZM2qI6EcCslH8tBlgkNsJhyBF+ZmBZig1mbFNK4nYJfKMTp jyysqHp4Ez6shMk8ut1gBPcGiiqmrWdaxVdw+OaTo+U5QZPi9XrfFbSbEK7vj+aihxXc qC9zvYt2Ym6coWPslLmOFSf53egGwbeMrSNtvXkPlimpLIckXf2hM7073A3bFRz9alF/ Vytw== X-Forwarded-Encrypted: i=1; AHgh+Rq2/1lU9p82CcYgUApbQ6pXgb5ur26z9lO2ntoW/4xt9ZagMsjhZmr0BnBCjBBMctYn/JqS4R/eqD9PUc0=@vger.kernel.org X-Gm-Message-State: AOJu0Yy+T0p+4NVeNbPQT45pBkLRQ6rsLIJqeOPVww+QAaFmlXI8ddlN cnMUxsovIry3jXvxEpabea7cLtSa5RwjunxH/E2Z06Jd9r6yRItRF/4a69BQeB/yyekwhkCBX2P OwzJZ4huAt5zD4Q1wkHcd5WmnbUS8MIrEfgGG7Le4oOzMBFOKSFUEpwrYfsR4bo4GEw== X-Gm-Gg: AR+sD12chRkwkIF1VqaGyjuGlqqGlf65nCpXKHai/CxDslqdU+whtdnnPG/c4GbrfcU ATeCCt52F+T1AoiTJGBxiqSw9xJG/nCs4w6/bKA87QYFsdR1lLH+leeSaQa2uM7s6EMupJb9JB1 DyLhnkQfIUbTNRdkF4TnYZMd+2/qqYDb0NKcCm79jr8z1xcj/p+xVLB4iWo93BNT3rKhWD0m99+ UvAFypzkp8dKv3lgCl1FodGQlfQR4sHT0R3te88A/tMwC82tXOg8j2o/auuePTHEL+iSkKlI1Gx Xup+CpFkZtwv3dUTIhKMMc+Mf0Qk8KqbRwZS2tLOI9YQEMo57UM38nx90fphnJliAt9EgIUm X-Received: by 2002:a05:620a:f12:b0:915:a111:86ae with SMTP id af79cd13be357-9364922a3ecmr742287985a.35.1785950957454; Wed, 05 Aug 2026 10:29:17 -0700 (PDT) X-Received: by 2002:a05:620a:f12:b0:915:a111:86ae with SMTP id af79cd13be357-9364922a3ecmr742282985a.35.1785950956885; Wed, 05 Aug 2026 10:29:16 -0700 (PDT) Received: from [192.168.8.4] ([100.0.180.93]) by smtp.gmail.com with ESMTPSA id af79cd13be357-9364a567666sm196142685a.33.2026.08.05.10.29.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Aug 2026 10:29:16 -0700 (PDT) Message-ID: <2de49c1551bef14f30776221c10e43ebf1305ff6.camel@redhat.com> Subject: Re: [PATCH] drm/nouveau/disp: Prevent division-by-zero during DisplayPort link training transitions From: lyude@redhat.com To: Arjan Filius Cc: Danilo Krummrich , nouveau@lists.freedesktop.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Date: Wed, 05 Aug 2026 13:29:15 -0400 In-Reply-To: <6BF6102D-CBBC-4C98-8E74-F2AD208A7169@xs4all.nl> References: <69D67A9F-1A56-4814-AE68-50559DED42AF@xs4all.nl> <6BF6102D-CBBC-4C98-8E74-F2AD208A7169@xs4all.nl> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.58.3 (3.58.3-1.fc43) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 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, >=20 > 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.=20 > 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. >=20 > 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 >=20 > 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,=20 > and had to fsck my disks due to it, I remembered the fix I once > debugged and posted in 2024.=20 > 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,=20 > but ended up to basically reproduce the fix i had written in 2024 > (without AI). >=20 >=20 > Regarding the two patches (A and B):=20 > * **Patch B** was the version I compiled and tested locally with the > `nvkm_warn()` statement > =C2=A0 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). >=20 > To avoid any confusion i repeat my patch, which does not produce any > logging every time,=20 > but just avoids the lockup referencing null pointers when external > displays goes to sleep. >=20 >=20 > ```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) > =C2=A0{ > =C2=A0 struct nvkm_subdev *subdev =3D &head->disp->engine.subdev; > =C2=A0 > + /* If the DisplayPort link is inactive (0 lanes), skip > configuration */ > + if (ior->dp.nr =3D=3D 0) > + return; > + > =C2=A0 const u32 khz =3D head->asy.hz / 1000; > =C2=A0 const u32 linkKBps =3D ior->dp.bw * 27000; > =C2=A0 const u32 symbol =3D 100000; > ``` >=20 > 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. >=20 > Hope this claries it. >=20 > Best regards, > Arjan Filius >=20 >=20 > > On 16 Jul 2026, at 22:40, lyude@redhat.com=C2=A0wrote: > >=20 > > 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. > >=20 > > On Thu, 2026-07-16 at 16:55 +0200, Arjan Filius wrote: > > > Dear Nouveau Maintainers, > > > =C2=A0 > > > 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. > > > =C2=A0 > > > --- > > > =C2=A0 > > > ### BRIEF EXPLANATION > > > =C2=A0 > > > 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 =3D=3D 0`).=20 > > > =C2=A0 > > > 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. > > > =C2=A0 > > > 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. > > >=20 > > > *=C2=A0=C2=A0 **Tested Kernel Version:** `7.1.3` (mainline stable bra= nch) > > >=20 > > > --- > > >=20 > > > ### EXTREMELY DETAILED TECHNICAL BREAKDOWN > > >=20 > > > #### 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`).=20 > > >=20 > > > #### 2. Root Cause Analysis (Code Level) > > > Inside `drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c`, when > > > `ior- > > > > dp.nr =3D=3D 0`, the driver executes the following lines in > > > `nv50_disp_super_2_2_dp()`: > > >=20 > > > *=C2=A0=C2=A0 **Line 1179:** Calculations for horizontal blank symbol= s: > > > =C2=A0=C2=A0=C2=A0 ```c > > > =C2=A0=C2=A0=C2=A0 h =3D h - (3 * ior->dp.ef) - (12 / ior->dp.nr); > > > =C2=A0=C2=A0=C2=A0 ``` > > > *=C2=A0=C2=A0 **Line 1185:** Calculations for vertical blank symbols: > > > =C2=A0=C2=A0=C2=A0 ```c > > > =C2=A0=C2=A0=C2=A0 v =3D v - ((36 / ior->dp.nr) + 3) - 1; > > > =C2=A0=C2=A0=C2=A0 ``` > > > *=C2=A0=C2=A0 **Line 1190:** Calculations for active link data rate: > > > =C2=A0=C2=A0=C2=A0 ```c > > > =C2=A0=C2=A0=C2=A0 link_data_rate =3D (khz * head->asy.or.depth / 8) = / ior->dp.nr; > > > =C2=A0=C2=A0=C2=A0 ``` > > >=20 > > > 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). > > >=20 > > > #### 3. Daily Workday Trigger Scenario > > > 1.=C2=A0 The T430 (via dock) and a secondary workstation are both > > > connected to different inputs on the same external monitors. > > > 2.=C2=A0 The monitors' input sources are switched to the secondary > > > workstation. > > > 3.=C2=A0 At the end of the day, the secondary workstation goes to > > > sleep or > > > is shut down. > > > 4.=C2=A0 With no active inputs, the external monitors enter power- > > > saving > > > standby mode. > > > 5.=C2=A0 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. > > >=20 > > > #### 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]=C2=A0 ? nv50_disp_super_2_2_dp+0xa7/0x320 > > > [nouveau] > > > [di jul 23 10:28:26 2024]=C2=A0 nv50_disp_super_2_2+0xf2/0x160 > > > [nouveau] > > > [di jul 23 10:28:26 2024]=C2=A0 nv50_disp_super+0x139/0x280 [nouveau] > > > ``` > > >=20 > > > #### 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 > > > =3D 0), skipping display configuration. > > > [45162.232402] nouveau 0000:01:00.0: disp: DP link is inactive > > > (lanes > > > =3D 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] > > > ``` > > >=20 > > > --- > > >=20 > > > Signed-off-by: Arjan Filius > > > --- > > >=20 > > > ### CHOOSE ONE OF THE PATCH OPTIONS BELOW TO APPEND: > > >=20 > > > #### 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.* > > >=20 > > > ```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) > > > =C2=A0{ > > > =C2=A0 struct nvkm_subdev *subdev =3D &head->disp->engine.subdev; > > > =C2=A0 > > > + /* If the DisplayPort link is inactive (0 lanes), skip > > > configuration */ > > > + if (ior->dp.nr =3D=3D 0) > > > + return; > > > + > > > =C2=A0 const u32 khz =3D head->asy.hz / 1000; > > > =C2=A0 const u32 linkKBps =3D ior->dp.bw * 27000; > > > =C2=A0 const u32 symbol =3D 100000; > > > ``` > > >=20 > > > #### OPTION B: The Warning/Verbose Patch (What was tested > > > locally) > > > *Note: Prints warning logs to the kernel buffer for validation > > > and > > > troubleshooting.* > > >=20 > > > ```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) > > > =C2=A0{ > > > =C2=A0 struct nvkm_subdev *subdev =3D &head->disp->engine.subdev; > > > =C2=A0 > > > + /* If the DisplayPort link is inactive (0 lanes), skip > > > configuration */ > > > + if (ior->dp.nr =3D=3D 0) { > > > + nvkm_warn(subdev, "DP link is inactive (lanes =3D > > > 0), > > > skipping display configuration.\n"); > > > + return; > > > + } > > > + > > > =C2=A0 const u32 khz =3D head->asy.hz / 1000; > > > =C2=A0 const u32 linkKBps =3D ior->dp.bw * 27000; > > > =C2=A0 const u32 symbol =3D 100000; > > > ``` > >=20