Return to

Navi Reset Kernel Patch

Navi Reset

What this does is use powerplay tables to turn the card off and back on again. (Insert IT crowd meme here, haha).

@gnif has done it again. Good work!! :smiley:

Ok, here is the navi reset. Navi is easier to implement as the SMU has most of the logic in it.

From 69ea42207b544b6e3fa9755022bff09d2ce953d9 Mon Sep 17 00:00:00 2001
From: Geoffrey McRae <[email protected]>
Date: Thu, 12 Sep 2019 03:19:28 +1000
Subject: [PATCH] pci quirk: AMD Navi 10 series vendor specific reset

Signed-off-by: Geoffrey McRae <[email protected]>
 drivers/pci/quirks.c | 98 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 44c4ae1abd00..d94ddb1c6832 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3825,6 +3825,97 @@ static int delay_250ms_after_flr(struct pci_dev *dev, int probe)
 	return 0;
+ * AMD Navi 10 series GPUs require a vendor specific reset procedure.
+ * According to AMD a PSP mode 2 reset should be enough however at this
+ * time the details of how to perform this are not available to us.
+ * Instead we can signal the SMU to enter and exit BACO which has the same
+ * desired effect.
+ */
+static int reset_amd_navi10(struct pci_dev *dev, int probe)
+	const int mmMP0_SMN_C2PMSG_81 = 0x16091;
+	const int mmMP1_SMN_C2PMSG_66 = 0x16282;
+	const int mmMP1_SMN_C2PMSG_82 = 0x16292;
+	const int mmMP1_SMN_C2PMSG_90 = 0x1629a;
+	u16 cfg;
+	resource_size_t mmio_base, mmio_size;
+	uint32_t __iomem * mmio;
+	unsigned int sol;
+	unsigned int timeout;
+	/* bus resets still cause navi to flake out */
+	dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET;
+	if (probe)
+		return 0;
+	/* save the PCI state and enable memory access */
+	pci_save_state(dev);
+	pci_read_config_word(dev, PCI_COMMAND, &cfg);
+	pci_write_config_word(dev, PCI_COMMAND, cfg | PCI_COMMAND_MEMORY);
+	/* map BAR5 */
+	mmio_base = pci_resource_start(dev, 5);
+	mmio_size = pci_resource_len(dev, 5);
+	mmio = ioremap_nocache(mmio_base, mmio_size);
+	if (mmio == NULL) {
+		pci_disable_device(dev);
+		pci_err(dev, "Navi10: cannot iomap device\n");
+		return 0;
+	}
+	/* check the sign of life indicator */
+	sol = readl(mmio + mmMP0_SMN_C2PMSG_81);
+	pci_info(dev, "Navi10: SOL 0x%x\n", sol);
+	if (sol == 0 || sol == 0xffffffff) {
+		pci_info(dev, "Navi10: device doesn't need to be reset\n");
+		goto out;
+	}
+	pci_info(dev, "Navi10: performing BACO reset\n");
+	/* the SMU might be busy already, wait for it */
+	for(timeout = 200; timeout && readl(mmio + mmMP1_SMN_C2PMSG_90) != 0; --timeout)
+		msleep(1);
+	readl(mmio + mmMP1_SMN_C2PMSG_90);
+	/* send PPSMC_MSG_ArmD3 */
+	writel(0x00, mmio + mmMP1_SMN_C2PMSG_90);
+	writel(0x46, mmio + mmMP1_SMN_C2PMSG_66);
+	for(timeout = 200; timeout && readl(mmio + mmMP1_SMN_C2PMSG_90) != 0; --timeout)
+		msleep(1);
+	/* send PPSMC_MSG_EnterBaco with param */
+	writel(0x00, mmio + mmMP1_SMN_C2PMSG_90);
+	writel(0x00, mmio + mmMP1_SMN_C2PMSG_82);
+	writel(0x18, mmio + mmMP1_SMN_C2PMSG_66);
+	for(timeout = 200; timeout && readl(mmio + mmMP1_SMN_C2PMSG_90) != 0; --timeout)
+		msleep(1);
+	/* wait for the regulators to shutdown */
+	msleep(400);
+	/* send PPSMC_MSG_ExitBaco */
+	writel(0x00, mmio + mmMP1_SMN_C2PMSG_90);
+	writel(0x19, mmio + mmMP1_SMN_C2PMSG_66);
+	for(timeout = 200; timeout && readl(mmio + mmMP1_SMN_C2PMSG_90) != 0; --timeout)
+		msleep(1);
+	/* wait for regulators to startup again */
+	msleep(400);
+	/* unmap BAR5 */
+	iounmap(mmio);
+	/* restore the PCI state and command register */
+	pci_restore_state(dev);
+	pci_write_config_word(dev, PCI_COMMAND, cfg);
+	return 0;
 static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
 		 reset_intel_82599_sfp_virtfn },
@@ -3836,6 +3927,13 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
 	{ PCI_VENDOR_ID_INTEL, 0x0953, delay_250ms_after_flr },
 		reset_chelsio_generic_dev },
+	{ PCI_VENDOR_ID_ATI, 0x7310, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x7312, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x7318, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x7319, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x731a, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x731b, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x731f, reset_amd_navi10 },
 	{ 0 }

reserved :smiley:

1 Like

For those that would like to support my work on things like this please see the below options:


Any word about a Radeon VII reset patch? Would this work with Vega 20 if you changed the PCI IDs?

I don’t have a Radeon VII to implement this on, and it almost certainly wont work on the Vega 20, the Vega reset implementation is far more complex and some base register addresses have been changed.

Would be the logical next step. Anyone have a Radeon VII to give to Geoff?

You could provide it to him as a temp and he sends it back after he is done.

I know someone from the forums with a Radeon VII locally. I could ask him about it.

Is there something I need to have in mind in regards to the setup. I took the 5.3-rc1 Manjaro kernel from here: and edited the PKGBUILD so it incorporates the new patch.

Now when I do a clean shutdown and try to restart the VM with my Navi passed through the boot hangs: I can see the TianoCore boot logo and the endless rotating windows loading icon below it.

I followed the directions in the arch wiki to setuo passthrough on Manjaro.

My VM Setup is the following VM.txt (6.2 KB)

Edit: Don’t know what was wrong. I did destroy the VM and kept the disc image and created a new VM with the very same image. Windows got a error saying it needs to restart and now everything works.

These threads from the Manjaro forum explained it for me:

I have done a self compilation of the Kernel the first time myself for this patch. It is not much work on Manjaro and Arch in general.

  1. Find the correct sources: First you clone the repositories of the kernel source for the kernel you want to use from here: So in this page I would recommend you go into the linux53 branch and then hit the blue clone-button and copy the “Clone via https”-link. You need the package “git” installed on your system.

  2. Clone the code: Use the terminal navigate to a folder of your choice and run “git clone”. You will have a new linux53 folder. These are the sources for the 5.3 Manjaro Kernel.

  3. Copy the code from the Navi patch into a file in the linux53 folder and name it navi.patch or something like this.

  4. Create a SHA256 Checksum with "shasum -a 256 and keep the checksum it generates

  5. Open the PKGBUILD file in the linux53 folder in a text editor:

  6. Change the line _kernelname=-MANJARO to something like _kernelname=-VFIO. You do this because it makes it easier to see that you use your patched Kernel when yo run uname -u and also avoids the case that when Manjaro publishes a newer kernel version that yours will be replaced with a newer but unpatched version.

  7. At the beginning of the file there is a list of files beginning with “source=(” and then listing all the files. At the End behind “‘0013-bootsplash.patch’” create an additional line before the braces close with ‘navi.patch’ or whatever you named your patch file.

  8. Directly below the sources part in the PKGBUILD file is the “sha256sums=(”-part with the sha256 checksums. Because you added the navi.patch as the last file in the sources section you need to add the checksum you generated here as the last checksum before the braces close in the same manner.

At this point the PKGBUILD will know about your patch and can verify it with the checksum you generated. Now we need to apply it.

  1. Behind the end of the

    patch -Np1 -i “${srcdir}/vfs-ino.patch”

lines add an additional line like this:

  patch -Np1 -i "${srcdir}/navi.patch"`
  1. Save and apply your edits

  2. Install manjaro-tools-pkg sudo pacman -S manjaro-tools-pkg

  3. outside of the linux53 folder run buildpkg -p linux53

  4. The compilation takes 2 hours for me -> wait

  5. in the terminal cd /var/cache/manjaro-tools/pkg/stable/x86_64 your new kernel and it header will be there

  6. Install both with sudo pacman -U <kernelfilename> <headerfilename>

  7. Reboot and choose your new kernel in the grub menu by holding shift while booting

  8. ?

  9. Profit

Edit: I wanted to add that packages you install from the Arch User Repository (AUR) on Arch or Manjaro are being build in the same way. You should familiarize yourselfs with the build steps because you can verify and edit alls the software from the AUR if you understand buildpkg.