Reviewed-by: Lyude Paul <[email protected]> On Sun, 2026-08-16 at 15:09 +0200, Marek Czernohous wrote: > From: Marek Czernohous <[email protected]> > > NVAC (MCP79/MCP7A) uses g94_pci_func, whose .msi_rearm is > nv40_pci_msi_rearm(): a re-arm write through the MMIO mirror of PCI > config space. On this IGP that path is unreliable; when a re-arm is > missed the interrupt line stays dead, command submission times out > and > the GPU appears hung until reboot. On an Apple Mac mini (early 2009, > MCP79, boot0 0x0ac080b1) this showed as sporadic fifo timeouts and > GPU > hangs under load unless MSI was disabled via config=NvMSI=0. > > Give NVAC its own pci func that re-arms through real PCI config space > (nv46_pci_msi_rearm) instead. This follows existing precedent: > nv46.c > documents the MMIO-mirror re-arm as broken on several related parts, > and commit 5112abc6a433 ("drm/nouveau/pci/g92: Fix rearm") fixed g92 > the same way while moving the remaining chipsets, NVAC included, into > the newly added shared g94 table, where NVAC stayed on the MMIO path. > This change completes that fix for NVAC. The sibling IGP NVAA > (MCP77/MCP78) has MSI disabled entirely as "reported broken" in > nvkm_pci_new_(); NVAC works correctly once the re-arm goes through > config space, so disabling MSI is not necessary. > > Only NVAC is switched: that is the hardware this has been validated > on. The other users of g94_pci_func (G94/G96/G98/GT2xx and the > MCP77/MCP89 IGPs) keep their current behavior; MCP77 and MCP89 > plausibly want the same treatment but were not tested. > > Tested on the Mac mini as a daily driver for two months with MSI > enabled and zero fifo timeouts. Independently confirmed stable on an > iMac9,1 (MCP79) running 6.12.90 with the v1 form of this change (the > same one-line functional switch, applied to that kernel's g94 > implementation). > > Fixes: 5112abc6a433 ("drm/nouveau/pci/g92: Fix rearm") > Cc: <[email protected]> # v6.16+ > Tested-by: Fab Stz <[email protected]> > Assisted-by: Claude:claude-opus-4-7 > Assisted-by: Claude:claude-opus-4-8 > Signed-off-by: Marek Czernohous <[email protected]> > --- > .../gpu/drm/nouveau/include/nvkm/subdev/pci.h | 1 + > .../gpu/drm/nouveau/nvkm/engine/device/base.c | 2 +- > .../gpu/drm/nouveau/nvkm/subdev/pci/Kbuild | 1 + > .../gpu/drm/nouveau/nvkm/subdev/pci/mcp79.c | 35 > +++++++++++++++++++ > 4 files changed, 38 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/pci/mcp79.c > > diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h > b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h > index 112b674ed9c8..0172e0d200f8 100644 > --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h > +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h > @@ -46,6 +46,7 @@ int nv4c_pci_new(struct nvkm_device *, enum > nvkm_subdev_type, int inst, struct n > int g84_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int > inst, struct nvkm_pci **); > int g92_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int > inst, struct nvkm_pci **); > int g94_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int > inst, struct nvkm_pci **); > +int mcp79_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int > inst, struct nvkm_pci **); > int gf100_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int > inst, struct nvkm_pci **); > int gf106_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int > inst, struct nvkm_pci **); > int gk104_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int > inst, struct nvkm_pci **); > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c > b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c > index ea62dc97f118..f7e02a16e5bc 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c > @@ -1237,7 +1237,7 @@ nvac_chipset = { > .mc = { 0x00000001, g98_mc_new }, > .mmu = { 0x00000001, mcp77_mmu_new }, > .mxm = { 0x00000001, nv50_mxm_new }, > - .pci = { 0x00000001, g94_pci_new }, > + .pci = { 0x00000001, mcp79_pci_new }, > .therm = { 0x00000001, g84_therm_new }, > .timer = { 0x00000001, nv41_timer_new }, > .volt = { 0x00000001, nv40_volt_new }, > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild > b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild > index a14ea0f7b1c8..90f03baeb22a 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild > @@ -9,6 +9,7 @@ nvkm-y += nvkm/subdev/pci/nv4c.o > nvkm-y += nvkm/subdev/pci/g84.o > nvkm-y += nvkm/subdev/pci/g92.o > nvkm-y += nvkm/subdev/pci/g94.o > +nvkm-y += nvkm/subdev/pci/mcp79.o > nvkm-y += nvkm/subdev/pci/gf100.o > nvkm-y += nvkm/subdev/pci/gf106.o > nvkm-y += nvkm/subdev/pci/gk104.o > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/mcp79.c > b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/mcp79.c > new file mode 100644 > index 000000000000..e2ae242f1aa7 > --- /dev/null > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/mcp79.c > @@ -0,0 +1,35 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright 2026 Marek Czernohous > + * > + * MCP79/MCP7A (NVAC): like g94, but MSI re-arm goes through real > PCI > + * config space. The MMIO-mirror re-arm is unreliable on this IGP > and a > + * missed re-arm kills the interrupt line (see the nv46 comment; g92 > + * already re-arms through config space for the same reason). > + */ > +#include "priv.h" > + > +static const struct nvkm_pci_func > +mcp79_pci_func = { > + .cfg = { .addr = 0x088000, .size = 0x1000 }, > + > + .init = g84_pci_init, > + .msi_rearm = nv46_pci_msi_rearm, > + > + .pcie.init = g84_pcie_init, > + .pcie.set_link = g84_pcie_set_link, > + > + .pcie.max_speed = g84_pcie_max_speed, > + .pcie.cur_speed = g84_pcie_cur_speed, > + > + .pcie.set_version = g84_pcie_set_version, > + .pcie.version = g84_pcie_version, > + .pcie.version_supported = g92_pcie_version_supported, > +}; > + > +int > +mcp79_pci_new(struct nvkm_device *device, enum nvkm_subdev_type > type, int inst, > + struct nvkm_pci **ppci) > +{ > + return nvkm_pci_new_(&mcp79_pci_func, device, type, inst, > ppci); > +}
