* [PATCH v2 01/10] Revert "drm/nouveau/gsp: add support for GA100"
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 22:38 ` [PATCH v2 02/10] drm/nouveau/gsp: add SEC2 to GA100 chip table Timur Tabi
` (10 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
This reverts commit 20e0c197802c545db220157fafd567a10f2b7672.
Despite claiming to add GA100 support, that commit actually has quite
a few problems. It falsely claims that there is no VBIOS. GA100 does
have a VBIOS, but it has no display engine, so it cannot use the
PRAMIN method the read VBIOS and must fall back to using PROM.
For whatever reason, the VBIOS on GA100 has an "Init-from-ROM"
(IFR) header where the PCI Expansion ROM would normally be found.
So to find that ROM, Nouveau needs to parse the IFR header.
The commit also falsely claimed that there is no graphics (GR) engine.
So rather than try to fix that commit, just revert it and start over
from scratch.
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
---
.../gpu/drm/nouveau/nvkm/engine/device/base.c | 11 +++++++++--
.../gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c | 4 ++++
.../gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c | 18 +++++-------------
3 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index 72848ed80df7..b101e14f841e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -2513,6 +2513,7 @@ static const struct nvkm_device_chip
nv170_chipset = {
.name = "GA100",
.bar = { 0x00000001, tu102_bar_new },
+ .bios = { 0x00000001, nvkm_bios_new },
.devinit = { 0x00000001, ga100_devinit_new },
.fault = { 0x00000001, tu102_fault_new },
.fb = { 0x00000001, ga100_fb_new },
@@ -2529,7 +2530,6 @@ nv170_chipset = {
.vfn = { 0x00000001, ga100_vfn_new },
.ce = { 0x000003ff, ga100_ce_new },
.fifo = { 0x00000001, ga100_fifo_new },
- .sec2 = { 0x00000001, tu102_sec2_new },
};
static const struct nvkm_device_chip
@@ -3341,7 +3341,6 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x166: device->chip = &nv166_chipset; break;
case 0x167: device->chip = &nv167_chipset; break;
case 0x168: device->chip = &nv168_chipset; break;
- case 0x170: device->chip = &nv170_chipset; break;
case 0x172: device->chip = &nv172_chipset; break;
case 0x173: device->chip = &nv173_chipset; break;
case 0x174: device->chip = &nv174_chipset; break;
@@ -3361,6 +3360,14 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x1b6: device->chip = &nv1b6_chipset; break;
case 0x1b7: device->chip = &nv1b7_chipset; break;
default:
+ if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) {
+ switch (device->chipset) {
+ case 0x170: device->chip = &nv170_chipset; break;
+ default:
+ break;
+ }
+ }
+
if (!device->chip) {
nvdev_error(device, "unknown chipset (%08x)\n", boot0);
ret = -ENODEV;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c
index fdd820eeef81..27a13aeccd3c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c
@@ -41,11 +41,15 @@ ga100_gsp_flcn = {
static const struct nvkm_gsp_func
ga100_gsp = {
.flcn = &ga100_gsp_flcn,
+ .fwsec = &tu102_gsp_fwsec,
.sig_section = ".fwsignature_ga100",
.booter.ctor = tu102_gsp_booter_ctor,
+ .fwsec_sb.ctor = tu102_gsp_fwsec_sb_ctor,
+ .fwsec_sb.dtor = tu102_gsp_fwsec_sb_dtor,
+
.dtor = r535_gsp_dtor,
.oneinit = tu102_gsp_oneinit,
.init = tu102_gsp_init,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
index dd82c76b8b9a..19cb269e7a26 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
@@ -318,13 +318,8 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
if (ret)
return ret;
- /*
- * Calculate FB layout. FRTS is a memory region created by the FWSEC-FRTS firmware.
- * FWSEC comes from VBIOS. So on systems with no VBIOS (e.g. GA100), the FRTS does
- * not exist. Therefore, use the existence of VBIOS to determine whether to reserve
- * an FRTS region.
- */
- gsp->fb.wpr2.frts.size = device->bios ? 0x100000 : 0;
+ /* Calculate FB layout. */
+ gsp->fb.wpr2.frts.size = 0x100000;
gsp->fb.wpr2.frts.addr = ALIGN_DOWN(gsp->fb.bios.addr, 0x20000) - gsp->fb.wpr2.frts.size;
gsp->fb.wpr2.boot.size = gsp->boot.fw.size;
@@ -348,12 +343,9 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
if (ret)
return ret;
- /* Only boot FWSEC-FRTS if it actually exists */
- if (gsp->fb.wpr2.frts.size) {
- ret = nvkm_gsp_fwsec_frts(gsp);
- if (WARN_ON(ret))
- return ret;
- }
+ ret = nvkm_gsp_fwsec_frts(gsp);
+ if (WARN_ON(ret))
+ return ret;
/* Reset GSP into RISC-V mode. */
ret = gsp->func->reset(gsp);
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v2 02/10] drm/nouveau/gsp: add SEC2 to GA100 chip table
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
2026-04-30 22:38 ` [PATCH v2 01/10] Revert "drm/nouveau/gsp: add support for GA100" Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 22:38 ` [PATCH v2 03/10] drm/nouveau/gsp: use fb.bios.addr for gspFwWprEnd instead of vga_workspace.addr Timur Tabi
` (9 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
The booter-load and booter-unload firmware run on the SEC2 falcon.
During tu102_gsp_oneinit(), the booter constructor needs device->sec2
to access the SEC2 falcon.
Without the .sec2 entry, device->sec2 is NULL and this dereference
crashes during GSP-RM boot.
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
---
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index b101e14f841e..5af12037a5b9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -2530,6 +2530,7 @@ nv170_chipset = {
.vfn = { 0x00000001, ga100_vfn_new },
.ce = { 0x000003ff, ga100_ce_new },
.fifo = { 0x00000001, ga100_fifo_new },
+ .sec2 = { 0x00000001, tu102_sec2_new },
};
static const struct nvkm_device_chip
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v2 03/10] drm/nouveau/gsp: use fb.bios.addr for gspFwWprEnd instead of vga_workspace.addr
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
2026-04-30 22:38 ` [PATCH v2 01/10] Revert "drm/nouveau/gsp: add support for GA100" Timur Tabi
2026-04-30 22:38 ` [PATCH v2 02/10] drm/nouveau/gsp: add SEC2 to GA100 chip table Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 22:38 ` [PATCH v2 04/10] drm/nouveau/gsp: read MMU_LOCK to fix WPR placement on GA100 Timur Tabi
` (8 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
In OpenRM's kgspCalculateFbLayout_TU102(), gspFwWprEnd is derived from
vbiosReservedOffset, which is computed as:
vbiosReservedOffset = min(mmuLockLo, vgaWorkspaceOffset)
The VGA workspace offset is one input into this calculation, not the
direct source of gspFwWprEnd. vbiosReservedOffset is the effective
top boundary for WPR2 placement, and it may be lower than the VGA
workspace when VBIOS has locked a region via MMU_LOCK.
In Nouveau, gsp->fb.bios.addr is the equivalent of vbiosReservedOffset,
while gsp->fb.bios.vga_workspace.addr corresponds to the raw VGA
workspace location. The original code assigned vga_workspace.addr to
gspFwWprEnd, which produced the correct result only because bios.addr
was always set equal to vga_workspace.addr and never adjusted.
Use gsp->fb.bios.addr for gspFwWprEnd to correctly mirror OpenRM's
layout logic, so that future adjustments to bios.addr (such as clamping
it to an MMU_LOCK boundary) are properly reflected in the WPR metadata
passed to the booter.
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
---
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
index 19cb269e7a26..aa3ac34989b7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
@@ -246,7 +246,7 @@ tu102_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
meta->bootBinOffset = gsp->fb.wpr2.boot.addr;
meta->frtsOffset = gsp->fb.wpr2.frts.addr;
meta->frtsSize = gsp->fb.wpr2.frts.size;
- meta->gspFwWprEnd = ALIGN_DOWN(gsp->fb.bios.vga_workspace.addr, 0x20000);
+ meta->gspFwWprEnd = ALIGN_DOWN(gsp->fb.bios.addr, 0x20000);
meta->fbSize = gsp->fb.size;
meta->vgaWorkspaceOffset = gsp->fb.bios.vga_workspace.addr;
meta->vgaWorkspaceSize = gsp->fb.bios.vga_workspace.size;
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v2 04/10] drm/nouveau/gsp: read MMU_LOCK to fix WPR placement on GA100
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
` (2 preceding siblings ...)
2026-04-30 22:38 ` [PATCH v2 03/10] drm/nouveau/gsp: use fb.bios.addr for gspFwWprEnd instead of vga_workspace.addr Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 22:38 ` [PATCH v2 05/10] drm/nouveau: only boot FRTS if its region is allocated Timur Tabi
` (7 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
On GA100, the row remapper hardware reserves a small amount of DRAM at
the end of framebuffer for spare rows used to repair memory errors at
runtime. When an uncorrectable ECC error is detected in a DRAM row,
the row remapper redirects accesses to a spare row, transparently
repairing the fault.
The LOCAL_MEMORY_RANGE register (0x100ce0) reports the GPU's FB address
range, but its encoding rounds to 1GB boundaries. On GA100, VBIOS
originally rounded this value down, which could lose up to ~1GB of
usable FB. As a workaround, newer VBIOS instead rounds up to the next
1GB boundary and programs MMU_LOCK (registers 0x1fa82c/0x1fa830) to
mark the gap between the actual usable FB and the rounded-up range as
reserved.
OpenRM's kgspCalculateFbLayout_TU102() handles this by reading the
MMU_LOCK registers and computing the WPR top boundary as:
vbiosReservedOffset = min(mmuLockLo, vgaWorkspaceOffset)
Without this, the WPR region is placed at the top of LOCAL_MEMORY_RANGE,
which overlaps the reserved region. The booter firmware detects this
and rejects the WPR layout.
Add ga100_gsp_mmu_lock_lo() to read the MMU_LOCK range and clamp
gsp->fb.bios.addr accordingly, mirroring OpenRM's behavior.
This is a GA100-only issue. GA102 and later add the
NV_USABLE_FB_SIZE_IN_MB register which reports the correct usable FB
size directly, eliminating the need for the MMU_LOCK workaround.
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
---
.../gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c | 49 +++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
index aa3ac34989b7..66f285b60f1e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
@@ -291,6 +291,42 @@ tu102_gsp_vga_workspace_addr(struct nvkm_gsp *gsp, u64 fb_size)
return addr;
}
+/*
+ * Read the MMU_LOCK range programmed by VBIOS.
+ *
+ * The row remapper reserves a small amount of DRAM at the end of FB for
+ * spare rows used to repair memory errors. The register used to report
+ * FB size rounds to 1GB boundaries, and VBIOS rounds up rather than
+ * down -- reporting a larger size than is actually usable. To
+ * compensate, VBIOS programs MMU_LOCK to fence off the unusable region
+ * at the top. We must read this and keep WPR below it.
+ *
+ * Returns the low address of the locked region, or 0 if not set.
+ */
+static u64
+ga100_gsp_mmu_lock_lo(struct nvkm_gsp *gsp)
+{
+ struct nvkm_device *device = gsp->subdev.device;
+ u32 lo, hi;
+ u64 addr_lo, addr_hi;
+
+ /* NV_PFB_PRI_MMU_LOCK_CFG_PRIV_LEVEL_MASK */
+ if (!(nvkm_rd32(device, 0x1fa7c8) & 0x00000001))
+ return 0;
+
+ lo = nvkm_rd32(device, 0x1fa82c); /* NV_PFB_PRI_MMU_LOCK_ADDR_LO */
+ hi = nvkm_rd32(device, 0x1fa830); /* NV_PFB_PRI_MMU_LOCK_ADDR_HI */
+
+ addr_lo = (u64)(lo >> 4) << 12;
+ addr_hi = (u64)(hi >> 4) << 12;
+
+ if (addr_hi < addr_lo)
+ return 0;
+
+ nvkm_debug(&gsp->subdev, "MMU_LOCK range: 0x%llx - 0x%llx\n", addr_lo, addr_hi);
+ return addr_lo;
+}
+
int
tu102_gsp_oneinit(struct nvkm_gsp *gsp)
{
@@ -304,6 +340,19 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
gsp->fb.bios.addr = gsp->fb.bios.vga_workspace.addr;
gsp->fb.bios.size = gsp->fb.bios.vga_workspace.size;
+ /*
+ * On GA100, VBIOS may lock the top of FB via MMU_LOCK to reserve
+ * space for the row remapper. Mirror OpenRM's kgspCalculateFbLayout
+ * by clamping bios.addr to min(mmuLockLo, vgaWorkspace) so that the
+ * entire WPR2 layout and gspFwWprEnd stay within usable FB.
+ */
+ if (device->chipset == 0x170) {
+ u64 lock_lo = ga100_gsp_mmu_lock_lo(gsp);
+
+ if (lock_lo)
+ gsp->fb.bios.addr = min(gsp->fb.bios.addr, lock_lo);
+ }
+
ret = gsp->func->booter.ctor(gsp, "booter-load", gsp->fws.booter.load,
&device->sec2->falcon, &gsp->booter.load);
if (ret)
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v2 05/10] drm/nouveau: only boot FRTS if its region is allocated
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
` (3 preceding siblings ...)
2026-04-30 22:38 ` [PATCH v2 04/10] drm/nouveau/gsp: read MMU_LOCK to fix WPR placement on GA100 Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 22:38 ` [PATCH v2 06/10] drm/nouveau: GA100 has an FRTS region size of zero Timur Tabi
` (6 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
On some Nvidia GPUs (i.e. GA100), the FRTS region is not allocated
(its size is set to 0). In such cases, FWSEC-FRTS should not be run.
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
---
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
index 66f285b60f1e..fc8db6bcaf23 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
@@ -392,9 +392,12 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
if (ret)
return ret;
- ret = nvkm_gsp_fwsec_frts(gsp);
- if (WARN_ON(ret))
- return ret;
+ /* Only boot FWSEC-FRTS if it actually exists */
+ if (gsp->fb.wpr2.frts.size) {
+ ret = nvkm_gsp_fwsec_frts(gsp);
+ if (WARN_ON(ret))
+ return ret;
+ }
/* Reset GSP into RISC-V mode. */
ret = gsp->func->reset(gsp);
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v2 06/10] drm/nouveau: GA100 has an FRTS region size of zero
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
` (4 preceding siblings ...)
2026-04-30 22:38 ` [PATCH v2 05/10] drm/nouveau: only boot FRTS if its region is allocated Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 22:38 ` [PATCH v2 07/10] drm/nouveau/bios: specify correct display fuse register for Ampere and Ada Timur Tabi
` (5 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
When booting with GSP-RM, the FRTS data region normally needs to be
allocated. However, on GA100, this region is not used and so its
size needs to be set to zero.
The truth is that GA100 is just special, and the simplest way to
determine the proper FRTS data region size is to check for this
GPU specifically.
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
---
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
index fc8db6bcaf23..11a37963bd4e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/tu102.c
@@ -367,8 +367,13 @@ tu102_gsp_oneinit(struct nvkm_gsp *gsp)
if (ret)
return ret;
- /* Calculate FB layout. */
- gsp->fb.wpr2.frts.size = 0x100000;
+ /*
+ * Calculate FB layout. FRTS is a memory region created by running the FWSEC-FRTS
+ * command, which writes power management data into WPR2. On GA100, the booter
+ * firmware handles WPR2 setup directly and FRTS data is not needed, so no FRTS
+ * region is reserved.
+ */
+ gsp->fb.wpr2.frts.size = device->chipset == 0x170 ? 0 : 0x100000;
gsp->fb.wpr2.frts.addr = ALIGN_DOWN(gsp->fb.bios.addr, 0x20000) - gsp->fb.wpr2.frts.size;
gsp->fb.wpr2.boot.size = gsp->boot.fw.size;
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v2 07/10] drm/nouveau/bios: specify correct display fuse register for Ampere and Ada
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
` (5 preceding siblings ...)
2026-04-30 22:38 ` [PATCH v2 06/10] drm/nouveau: GA100 has an FRTS region size of zero Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 22:38 ` [PATCH v2 08/10] drm/nouveau/bios: skip the IFR header if present Timur Tabi
` (4 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
The NV_FUSE_STATUS_OPT_DISPLAY register is used to determine whether
the GPU has display hardware. The current code that normally reads
this register is instead hard-coded to check for GA100 vs later GPUs.
Since this function is called only on pre-Hopper GPUs, and this
if-statement applies only to GA100 and later, the check works
because GA100 is the only non-display Ampere and Ada GPU.
However, there actually is a register that can be read, so we should
use it.
Fixes: a34632482f1e ("drm/nouveau/bios/ga10[024]: initial support")
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
---
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c
index d5411d176e3a..0d9e6cdd6119 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c
@@ -65,13 +65,14 @@ pramin_init(struct nvkm_bios *bios, const char *name)
/* we can't get the bios image pointer without PDISP */
if (device->card_type >= GA100)
- addr = device->chipset == 0x170; /*XXX: find the fuse reg for this */
+ addr = nvkm_rd32(device, 0x820c04);
else
if (device->card_type >= GM100)
addr = nvkm_rd32(device, 0x021c04);
else
if (device->card_type >= NV_C0)
addr = nvkm_rd32(device, 0x022500);
+
if (addr & 0x00000001) {
nvkm_debug(subdev, "... display disabled\n");
return ERR_PTR(-ENODEV);
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v2 08/10] drm/nouveau/bios: skip the IFR header if present
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
` (6 preceding siblings ...)
2026-04-30 22:38 ` [PATCH v2 07/10] drm/nouveau/bios: specify correct display fuse register for Ampere and Ada Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 22:38 ` [PATCH v2 09/10] drm/nouveau/gsp: require GSP-RM for GA100 support Timur Tabi
` (3 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
The GPU's ROM may begin with an Init-from-ROM (IFR) header that precedes
the PCI Expansion ROM images (VBIOS). When present, the PROM shadow
method must parse this header to determine the offset where the PCI ROM
images actually begin, and adjust all subsequent reads accordingly.
On most GPUs this is not needed because either the PRAMIN shadow method
(which reads from VRAM via the display engine) succeeds first, or the IFR
microcode has already applied the ROM offset so that PROM reads
transparently skip the header. However, on GA100 neither of these
applies: GA100 has no display engine (so PRAMIN is unavailable), and the
IFR offset is not applied to PROM reads on this GPU.
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
---
.../drm/nouveau/nvkm/subdev/bios/shadowrom.c | 110 ++++++++++++++++--
1 file changed, 101 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c
index 39144ceb117b..9e171b1bad73 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowrom.c
@@ -24,34 +24,126 @@
#include <subdev/pci.h>
+#define NV_PBUS_IFR_FMT_FIXED0_SIGNATURE_VALUE 0x4947564E /* "NVGI" */
+#define NV_ROM_DIRECTORY_IDENTIFIER 0x44524652 /* "RFRD" */
+
+struct priv {
+ struct nvkm_device *device;
+ u32 pci_rom_offset;
+};
+
static u32
nvbios_prom_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
{
- struct nvkm_device *device = data;
+ struct priv *priv = data;
+ struct nvkm_device *device = priv->device;
u32 i;
- if (offset + length <= 0x00100000) {
- for (i = offset; i < offset + length; i += 4)
- *(u32 *)&bios->data[i] = nvkm_rd32(device, 0x300000 + i);
- return length;
- }
- return 0;
+
+ /* Make sure we don't try to read past the end of data[] */
+ if (offset + length > bios->size)
+ return 0;
+
+ /* Make sure the read falls within the 1MB PROM window */
+ if (offset + priv->pci_rom_offset + length > 0x00100000)
+ return 0;
+
+ for (i = offset; i < offset + length; i += 4)
+ *(u32 *)&bios->data[i] = nvkm_rd32(device, 0x300000 + priv->pci_rom_offset + i);
+ return length;
}
static void
nvbios_prom_fini(void *data)
{
- struct nvkm_device *device = data;
+ struct priv *priv = data;
+ struct nvkm_device *device = priv->device;
+
nvkm_pci_rom_shadow(device->pci, true);
+
+ kfree(data);
}
static void *
nvbios_prom_init(struct nvkm_bios *bios, const char *name)
{
struct nvkm_device *device = bios->subdev.device;
+ struct priv *priv;
+ u32 fixed0;
+
+ /* There is no PROM on NV4x iGPUs */
if (device->card_type == NV_40 && device->chipset >= 0x4c)
return ERR_PTR(-ENODEV);
+
+ priv = kzalloc_obj(*priv);
+ if (!priv)
+ return ERR_PTR(-ENOMEM);
+
+ /* Disable the PCI ROM shadow so that we can read PROM. */
nvkm_pci_rom_shadow(device->pci, false);
- return device;
+
+ /*
+ * Check for an IFR header. If present, parse it to find the actual PCI ROM header.
+ *
+ * The IFR header is documented in Documentation/gpu/nova/core/vbios.rst
+ */
+ fixed0 = nvkm_rd32(device, 0x300000);
+ if (fixed0 == NV_PBUS_IFR_FMT_FIXED0_SIGNATURE_VALUE) {
+ u32 fixed1 = nvkm_rd32(device, 0x300004);
+ u8 version = (fixed1 >> 8) & 0xff;
+ u32 fixed2, data_size, offset, signature;
+
+ switch (version) {
+ case 1:
+ case 2:
+ data_size = (fixed1 >> 16) & 0x7fff;
+ priv->pci_rom_offset = nvkm_rd32(device, 0x300000 + data_size + 4);
+ break;
+ case 3:
+ fixed2 = nvkm_rd32(device, 0x300008);
+ data_size = fixed2 & 0x000fffff;
+
+ /* ROM directory offset */
+ offset = nvkm_rd32(device, 0x300000 + data_size) + 4096;
+
+ signature = nvkm_rd32(device, 0x300000 + offset);
+ if (signature != NV_ROM_DIRECTORY_IDENTIFIER) {
+ nvkm_error(&bios->subdev, "could not find IFR ROM directory\n");
+ goto fail;
+ }
+
+ priv->pci_rom_offset = nvkm_rd32(device, 0x300000 + offset + 8);
+
+ break;
+ default:
+ nvkm_error(&bios->subdev, "unsupported IFR header version %u\n",
+ version);
+ goto fail;
+ }
+
+ /* Double-check that the offset is valid */
+ if (priv->pci_rom_offset >= 0x00100000) {
+ nvkm_error(&bios->subdev,
+ "PCI ROM offset of 0x%x is too large\n", priv->pci_rom_offset);
+ goto fail;
+ }
+
+ /* If there is an IFR header, there must also be a PCI ROM header. */
+ signature = nvkm_rd32(device, 0x300000 + priv->pci_rom_offset) & 0xffff;
+ if (signature != 0xaa55) {
+ nvkm_error(&bios->subdev,
+ "could not find PCI ROM signature at offset 0x%x\n",
+ priv->pci_rom_offset);
+ goto fail;
+ }
+ }
+
+ priv->device = device;
+ return priv;
+
+fail:
+ nvkm_pci_rom_shadow(device->pci, true);
+ kfree(priv);
+ return ERR_PTR(-ENODEV);
}
const struct nvbios_source
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v2 09/10] drm/nouveau/gsp: require GSP-RM for GA100 support
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
` (7 preceding siblings ...)
2026-04-30 22:38 ` [PATCH v2 08/10] drm/nouveau/bios: skip the IFR header if present Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 22:38 ` [PATCH v2 10/10] drm/nouveau/gsp: formally support GA100 Timur Tabi
` (2 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
Nouveau supports Turing and Ampere GPUs with or without GSP-RM.
Support without GSP-RM is mostly academic, since GSP-RM is
needed to run the GPU at full clocks. It is also the default
mode for these GPUs.
GA100 is a special case, however. The current code has some support
for running GA100 without GSP-RM, but several features are missing.
More importantly, some required firmware images like ucode_ahesasc.bin
are not available and would need to be provided by Nvidia.
To prevent Nouveau from even trying to boot on GA100 without GSP-RM,
remove the non-GSP fallback option in the ga100_gsps[] array.
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
---
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c
index 27a13aeccd3c..d5126fe39d27 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga100.c
@@ -63,7 +63,6 @@ static struct nvkm_gsp_fwif
ga100_gsps[] = {
{ 1, tu102_gsp_load, &ga100_gsp, &r570_rm_tu102, "570.144" },
{ 0, tu102_gsp_load, &ga100_gsp, &r535_rm_tu102, "535.113.01" },
- { -1, gv100_gsp_nofw, &gv100_gsp },
{}
};
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH v2 10/10] drm/nouveau/gsp: formally support GA100
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
` (8 preceding siblings ...)
2026-04-30 22:38 ` [PATCH v2 09/10] drm/nouveau/gsp: require GSP-RM for GA100 support Timur Tabi
@ 2026-04-30 22:38 ` Timur Tabi
2026-04-30 23:10 ` (subset) [PATCH v2 00/10] drm/nouveau: fix GA100 issues Danilo Krummrich
2026-05-28 17:33 ` Danilo Krummrich
11 siblings, 0 replies; 15+ messages in thread
From: Timur Tabi @ 2026-04-30 22:38 UTC (permalink / raw)
To: Lyude Paul, Danilo Krummrich, David Airlie, nouveau
Now that Nouveau supports GA100 properly, it should no longer require
the NvEnableUnsupportedChipsets parameter in order to enable it.
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
---
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index 5af12037a5b9..ea62dc97f118 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -3342,6 +3342,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x166: device->chip = &nv166_chipset; break;
case 0x167: device->chip = &nv167_chipset; break;
case 0x168: device->chip = &nv168_chipset; break;
+ case 0x170: device->chip = &nv170_chipset; break;
case 0x172: device->chip = &nv172_chipset; break;
case 0x173: device->chip = &nv173_chipset; break;
case 0x174: device->chip = &nv174_chipset; break;
@@ -3361,14 +3362,6 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x1b6: device->chip = &nv1b6_chipset; break;
case 0x1b7: device->chip = &nv1b7_chipset; break;
default:
- if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) {
- switch (device->chipset) {
- case 0x170: device->chip = &nv170_chipset; break;
- default:
- break;
- }
- }
-
if (!device->chip) {
nvdev_error(device, "unknown chipset (%08x)\n", boot0);
ret = -ENODEV;
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: (subset) [PATCH v2 00/10] drm/nouveau: fix GA100 issues
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
` (9 preceding siblings ...)
2026-04-30 22:38 ` [PATCH v2 10/10] drm/nouveau/gsp: formally support GA100 Timur Tabi
@ 2026-04-30 23:10 ` Danilo Krummrich
2026-05-19 13:36 ` Timur Tabi
2026-05-28 17:33 ` Danilo Krummrich
11 siblings, 1 reply; 15+ messages in thread
From: Danilo Krummrich @ 2026-04-30 23:10 UTC (permalink / raw)
To: Timur Tabi; +Cc: Danilo Krummrich, nouveau
On Thu, 30 Apr 2026 17:38:28 -0500, Timur Tabi wrote:
> [PATCH v2 00/10] drm/nouveau: fix GA100 issues
Applied, thanks!
Branch: drm-misc-fixes
Tree: https://gitlab.freedesktop.org/drm/misc/kernel.git
[1/10] Revert "drm/nouveau/gsp: add support for GA100"
commit: c9e3878ae2f5
The patch will appear in the next linux-next integration (typically within 24
hours on weekdays).
The patch is queued up for Linus's tree and should land in the next -rc release.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: (subset) [PATCH v2 00/10] drm/nouveau: fix GA100 issues
2026-04-30 23:10 ` (subset) [PATCH v2 00/10] drm/nouveau: fix GA100 issues Danilo Krummrich
@ 2026-05-19 13:36 ` Timur Tabi
2026-05-20 21:07 ` Danilo Krummrich
0 siblings, 1 reply; 15+ messages in thread
From: Timur Tabi @ 2026-05-19 13:36 UTC (permalink / raw)
To: dakr@kernel.org; +Cc: nouveau@lists.freedesktop.org
On Fri, 2026-05-01 at 01:10 +0200, Danilo Krummrich wrote:
> On Thu, 30 Apr 2026 17:38:28 -0500, Timur Tabi wrote:
> > [PATCH v2 00/10] drm/nouveau: fix GA100 issues
>
> Applied, thanks!
>
> Branch: drm-misc-fixes
> Tree: https://gitlab.freedesktop.org/drm/misc/kernel.git
>
> [1/10] Revert "drm/nouveau/gsp: add support for GA100"
> commit: c9e3878ae2f5
>
> The patch will appear in the next linux-next integration (typically within 24
> hours on weekdays).
>
> The patch is queued up for Linus's tree and should land in the next -rc release.
Danilo,
What's the plan for the rest of the patch set?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: (subset) [PATCH v2 00/10] drm/nouveau: fix GA100 issues
2026-05-19 13:36 ` Timur Tabi
@ 2026-05-20 21:07 ` Danilo Krummrich
0 siblings, 0 replies; 15+ messages in thread
From: Danilo Krummrich @ 2026-05-20 21:07 UTC (permalink / raw)
To: maarten.lankhorst, mripard, tzimmermann; +Cc: nouveau@lists.freedesktop.org
Hi Maarten, Maxime, Thomas,
On Tue May 19, 2026 at 3:36 PM CEST, Timur Tabi wrote:
> On Fri, 2026-05-01 at 01:10 +0200, Danilo Krummrich wrote:
>> On Thu, 30 Apr 2026 17:38:28 -0500, Timur Tabi wrote:
>> > [PATCH v2 00/10] drm/nouveau: fix GA100 issues
>>
>> Applied, thanks!
>>
>> Branch: drm-misc-fixes
>> Tree: https://gitlab.freedesktop.org/drm/misc/kernel.git
>>
>> [1/10] Revert "drm/nouveau/gsp: add support for GA100"
>> commit: c9e3878ae2f5
>>
>> The patch will appear in the next linux-next integration (typically within 24
>> hours on weekdays).
>>
>> The patch is queued up for Linus's tree and should land in the next -rc release.
>
> Danilo,
>
> What's the plan for the rest of the patch set?
Can we please get drm-fixes-2026-05-08-1 (commit c9e3878ae2f5 ("Revert
"drm/nouveau/gsp: add support for GA100"") backmerged into drm-misc-next?
Thanks,
Danilo
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: (subset) [PATCH v2 00/10] drm/nouveau: fix GA100 issues
2026-04-30 22:38 [PATCH v2 00/10] drm/nouveau: fix GA100 issues Timur Tabi
` (10 preceding siblings ...)
2026-04-30 23:10 ` (subset) [PATCH v2 00/10] drm/nouveau: fix GA100 issues Danilo Krummrich
@ 2026-05-28 17:33 ` Danilo Krummrich
11 siblings, 0 replies; 15+ messages in thread
From: Danilo Krummrich @ 2026-05-28 17:33 UTC (permalink / raw)
To: Timur Tabi; +Cc: Danilo Krummrich, nouveau
On Thu, 30 Apr 2026 17:38:28 -0500, Timur Tabi wrote:
> [PATCH v2 00/10] drm/nouveau: fix GA100 issues
Applied, thanks!
Branch: drm-misc-next
Tree: https://gitlab.freedesktop.org/drm/misc/kernel.git
[2/10] drm/nouveau/gsp: add SEC2 to GA100 chip table
commit: 604d0efb17cc
[3/10] drm/nouveau/gsp: use fb.bios.addr for gspFwWprEnd instead of vga_workspace.addr
commit: 3cee1a10b8a6
[4/10] drm/nouveau/gsp: read MMU_LOCK to fix WPR placement on GA100
commit: 0094a7a95d52
[5/10] drm/nouveau: only boot FRTS if its region is allocated
commit: 0ae50100b228
[6/10] drm/nouveau: GA100 has an FRTS region size of zero
commit: 16d4747cd152
[7/10] drm/nouveau/bios: specify correct display fuse register for Ampere and Ada
commit: c1cf2d5db80c
[8/10] drm/nouveau/bios: skip the IFR header if present
commit: 4beeac5d2015
[9/10] drm/nouveau/gsp: require GSP-RM for GA100 support
commit: f0de0f89cc1e
[10/10] drm/nouveau/gsp: formally support GA100
commit: 61de054a772a
The patches will appear in the next linux-next integration (typically within 24
hours on weekdays).
The patches are queued up for the upcoming merge window for the next major
kernel release.
^ permalink raw reply [flat|nested] 15+ messages in thread