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);
> +}

Reply via email to