Navi Reset Bug Kernel Patch v2

v3 @belfrypossum posted on VFIO discord, fixes a minor issue.

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 2a589b6d6ed8..1b84090db691 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3969,17 +3969,517 @@ 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 PSP to perform a mode 1 reset, which _is_
+ * available to us. Unfortunately, it probably takes more time.
+ */
+static int reset_amd_navi10(struct pci_dev *dev, int probe)
+{
+	static const u16 vega10_device_ids[] = { 0x6860, 0x6861, 0x6862, 0x6863,
+						 0x6864, 0x6867, 0x6868, 0x6869,
+						 0x686a, 0x686b, 0x686c, 0x686d,
+						 0x686e, 0x686f, 0x687f };
+
+	static const u16 vega12_device_ids[] = {
+		0x69A0, 0x69A1, 0x69A2, 0x69A3, 0x69AF,
+	};
+
+	static const u16 vega20_device_ids[] = {
+		0x66A0, 0x66A1, 0x66A2, 0x66A3, 0x66A4, 0x66A7, 0x66AF,
+	};
+
+	const int PPSMC_MSG_DisableSmuFeatures = 0x5; /* vega10 */
+	const int PPSMC_MSG_DisableAllSmuFeatures = 0x7; /* vega12/vega20 */
+	const int SMC_DPM_FEATURES = 0x30F;
+
+	const int mmMM_INDEX = 0x0000;
+	const int mmMM_DATA = 0x0001;
+	const int mmPCIE_INDEX2 = 0x000e;
+	const int mmPCIE_DATA2 = 0x000f;
+
+	const int MP0_BASE = 0x00016000L;
+	const int mmMP0_SMN_C2PMSG_33 = 0x0061 + MP0_BASE;
+	const int mmMP0_SMN_C2PMSG_35 = 0x0063 + MP0_BASE;
+	const int mmMP0_SMN_C2PMSG_64 = 0x0080 + MP0_BASE;
+	const int mmMP0_SMN_C2PMSG_81 = 0x0091 + MP0_BASE;
+	const int mmMP1_SMN_C2PMSG_66 = 0x0282 + MP0_BASE;
+	const int mmMP1_SMN_C2PMSG_82 = 0x0292 + MP0_BASE;
+	const int mmMP1_SMN_C2PMSG_90 = 0x029a + MP0_BASE;
+
+	const int GFX_CTRL_CMD_ID_MODE1_RST = 0x00070000L;
+	const int MP1_Public = 0x03b00000L;
+	const int smnMP1_PUB_CTRL = 0x3010b14;
+	const int MP1_SMN_PUB_CTRL__RESET_MASK = 0x00000001L;
+	int smnMP1_FIRMWARE_FLAGS = 0x3010024;
+	const int MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK = 0x00000001L;
+	const int MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT = 0x0;
+
+	const int mmRCC_DEV0_EPF0_RCC_CONFIG_MEMSIZE = 0x00c3 + 0x00000D20L;
+
+	// this is the case for navi but I'm not sure about vega yet
+	const int scratch_reg_offset = 0x4c;
+	const int ATOM_S3_ASIC_GUI_ENGINE_HUNG = 0x20000000L;
+
+	enum { VEGA10, VEGA12, VEGA20, NAVI } device_type = NAVI;
+
+	u16 cfg;
+	u32 tmp, smu_resp, sol, mp1_intr, psp_bl_ready;
+	resource_size_t mmio_base, mmio_size;
+	uint32_t __iomem *mmio;
+	unsigned int timeout;
+	spinlock_t pcie_lock;
+	int i;
+
+	/*
+	 * if the device has FLR return -ENOTTY indicating that we have no
+	 * device-specific reset method.
+	 */
+	if (pcie_has_flr(dev))
+		return -ENOTTY;
+
+	/* bus resets still cause navi to flake out */
+	dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET;
+
+	/* if we're managed by amdgpu, do not reset */
+	if (dev->driver && !strcmp(dev->driver->name, "amdgpu"))
+		return -ENOTTY;
+
+	if (probe)
+		return 0;
+
+	spin_lock_init(&pcie_lock);
+
+	/* detect device */
+	for (i = 0; i < sizeof vega10_device_ids / sizeof(u16); ++i) {
+		if (dev->device == vega10_device_ids[i]) {
+			device_type = VEGA10;
+			goto done_detect;
+		}
+	}
+	for (i = 0; i < sizeof vega12_device_ids / sizeof(u16); ++i) {
+		if (dev->device == vega12_device_ids[i]) {
+			device_type = VEGA12;
+			goto done_detect;
+		}
+	}
+	for (i = 0; i < sizeof vega20_device_ids / sizeof(u16); ++i) {
+		if (dev->device == vega20_device_ids[i]) {
+			device_type = VEGA20;
+			goto done_detect;
+		}
+	}
+
+done_detect:
+
+	if (device_type != NAVI && device_type != VEGA20) {
+		smnMP1_FIRMWARE_FLAGS = 0x3010028;
+	}
+
+	/* map BAR5 */
+	mmio_base = pci_resource_start(dev, 5);
+	mmio_size = pci_resource_len(dev, 5);
+	mmio = ioremap(mmio_base, mmio_size);
+	if (mmio == NULL) {
+		pci_disable_device(dev);
+		pci_err(dev, "Navi10: cannot iomap device\n");
+		return 0;
+	}
+
+	/* save the PCI state and enable memory access */
+	pci_read_config_word(dev, PCI_COMMAND, &cfg);
+	pci_write_config_word(dev, PCI_COMMAND, cfg | PCI_COMMAND_MEMORY);
+
+	pci_set_power_state(dev, PCI_D0);
+
+#define RREG32(reg)                                                            \
+	({                                                                     \
+		u32 out;                                                       \
+		if ((reg) < mmio_size)                                         \
+			out = readl(mmio + (reg));                             \
+		else {                                                         \
+			writel((reg), mmio + mmMM_INDEX);                      \
+			out = readl(mmio + mmMM_DATA);                         \
+		}                                                              \
+		out;                                                           \
+	})
+
+#define WREG32(reg, v)                                                         \
+	do {                                                                   \
+		if ((reg) < mmio_size)                                         \
+			writel(v, mmio + (reg));                               \
+		else {                                                         \
+			writel((reg), mmio + mmMM_INDEX);                      \
+			writel(v, mmio + mmMM_DATA);                           \
+		}                                                              \
+	} while (0)
+
+#define WREG32_PCIE(reg, v)                                                    \
+	do {                                                                   \
+		unsigned long __flags;                                         \
+		spin_lock_irqsave(&pcie_lock, __flags);                        \
+		WREG32(mmPCIE_INDEX2, reg);                                    \
+		(void)RREG32(mmPCIE_INDEX2);                                   \
+		WREG32(mmPCIE_DATA2, v);                                       \
+		(void)RREG32(mmPCIE_DATA2);                                    \
+		spin_unlock_irqrestore(&pcie_lock, __flags);                   \
+	} while (0)
+
+#define RREG32_PCIE(reg)                                                       \
+	({                                                                     \
+		unsigned long __flags;                                         \
+		u32 __tmp_read;                                                \
+		spin_lock_irqsave(&pcie_lock, __flags);                        \
+		WREG32(mmPCIE_INDEX2, reg);                                    \
+		(void)RREG32(mmPCIE_INDEX2);                                   \
+		__tmp_read = RREG32(mmPCIE_DATA2);                             \
+		spin_unlock_irqrestore(&pcie_lock, __flags);                   \
+		__tmp_read;                                                    \
+	})
+
+#define SMU_WAIT()                                                             \
+	({                                                                     \
+		u32 __tmp;                                                     \
+		for (timeout = 100000;                                         \
+		     timeout &&                                                \
+		     (RREG32(mmMP1_SMN_C2PMSG_90) & 0xFFFFFFFFL) == 0;         \
+		     --timeout)                                                \
+			udelay(1);                                             \
+		if ((__tmp = RREG32(mmMP1_SMN_C2PMSG_90)) != 0x1)              \
+			pci_info(dev, "Navi10: SMU error 0x%x (line %d)\n",    \
+				 __tmp, __LINE__);                             \
+	})
+
+	/* it's important we wait for the SOC to be ready */
+	for (timeout = 100000; timeout; --timeout) {
+		sol = RREG32(mmMP0_SMN_C2PMSG_81);
+		if (sol != 0xFFFFFFFF)
+			break;
+		udelay(1);
+	}
+
+	if (sol == 0xFFFFFFFF) {
+		pci_warn(dev,
+			 "Navi10: Timed out waiting for SOL to be valid\n");
+		/* we will continue anyway because it's possible to do
+		 * a mode 1 reset on navi at least */
+	}
+
+	/*
+	 * okay there's three things we need to check:
+	 * sign-of-life, MP1 intr state (enabled means MP1 is probably live),
+	 * and finally PSP bootloader state (needs to be ready)
+	 */
+	smu_resp = RREG32(mmMP1_SMN_C2PMSG_90);
+	mp1_intr = (RREG32_PCIE(MP1_Public |
+				(smnMP1_FIRMWARE_FLAGS & 0xffffffff)) &
+		    MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
+		   MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT;
+	psp_bl_ready = !!(RREG32(mmMP0_SMN_C2PMSG_35) & 0x80000000L);
+	pci_info(
+		dev,
+		"Navi10: Device type %d, SMU response reg: %x, sol reg: %x, mp1 intr enabled? %s, bl ready? %s\n",
+		device_type, smu_resp, sol, mp1_intr ? "yes" : "no",
+		psp_bl_ready ? "yes" : "no");
+
+	/* check the sign of life indicator */
+	if (sol == 0x0 && !mp1_intr && psp_bl_ready) {
+		/* either already clean or in a state we can't fix */
+		goto out;
+	}
+
+	/* save the state around the reset */
+	pci_info(dev, "Navi10: Clear master\n");
+	pci_clear_master(dev);
+
+	pci_save_state(dev);
+
+	/* this tells the drivers nvram is lost and everything needs to be reset */
+	pci_info(dev, "Navi10: Clearing scratch regs 6 and 7\n");
+	WREG32(scratch_reg_offset + 6, 0);
+	WREG32(scratch_reg_offset + 7, 0);
+
+	/* it only makes sense to reset mp1 if it's running
+	 * XXX: is this even necessary? in early testing, I ran into
+	 * situations where MP1 was alive but not responsive, but in
+	 * later testing I have not been able to replicate this scenario.
+	 */
+	if (smu_resp != 0x01 && mp1_intr && device_type == NAVI) {
+		pci_info(dev, "Navi10: MP1 reset\n");
+		WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff),
+			    1 & MP1_SMN_PUB_CTRL__RESET_MASK);
+		WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff),
+			    1 & ~MP1_SMN_PUB_CTRL__RESET_MASK);
+
+		pci_info(dev, "Navi10: wait for MP1\n");
+		for (timeout = 100000; timeout; --timeout) {
+			tmp = RREG32_PCIE(MP1_Public |
+					  (smnMP1_FIRMWARE_FLAGS & 0xffffffff));
+			if ((tmp &
+			     MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
+			    MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
+				break;
+			udelay(1);
+		}
+
+		if (!timeout &&
+		    !((tmp & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
+		      MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)) {
+			pci_warn(dev,
+				 "Navi10: timed out waiting for MP1 reset\n");
+		}
+
+		SMU_WAIT();
+		smu_resp = RREG32(mmMP1_SMN_C2PMSG_90);
+		pci_info(dev, "Navi10: SMU resp reg: %x\n", tmp);
+	}
+
+	pci_info(dev, "Navi10: begin reset\n");
+
+	/*
+	 * again, this only makes sense if we have an SMU to talk to
+	 * some of these may fail, that's okay. we're just turning off as many
+	 * things as possible
+	 */
+	if (mp1_intr) {
+		SMU_WAIT();
+
+		switch (device_type) {
+		case NAVI:
+			/* stop SMC */
+			pci_info(dev, "Navi10: gfx off\n");
+			WREG32(mmMP1_SMN_C2PMSG_90, 0x00);
+			WREG32(mmMP1_SMN_C2PMSG_82, 0x00);
+			WREG32(mmMP1_SMN_C2PMSG_66, 0x2A);
+			SMU_WAIT();
+
+			/* stop SMC */
+			pci_info(dev, "Navi10: Prep Reset\n");
+			WREG32(mmMP1_SMN_C2PMSG_90, 0x00);
+			WREG32(mmMP1_SMN_C2PMSG_82, 0x00);
+			/* PPSMC_MSG_PrepareMp1ForReset */
+			WREG32(mmMP1_SMN_C2PMSG_66, 0x33);
+			SMU_WAIT();
+			break;
+
+		case VEGA10:
+
+			/*
+		 * frankly, I have no idea if this has to be done in a particular order
+		 * hence this long sequence of bits that comes from the hwmgr destroy
+		 */
+
+#define DISABLE_FEAT(bits)                                                     \
+	do {                                                                   \
+		WREG32(mmMP1_SMN_C2PMSG_90, 0x00);                             \
+		WREG32(mmMP1_SMN_C2PMSG_82, (bits));                           \
+		WREG32(mmMP1_SMN_C2PMSG_66, PPSMC_MSG_DisableSmuFeatures);     \
+		SMU_WAIT();                                                    \
+	} while (0)
+
+			/* disable power containment */
+			pci_info(dev, "Vega10: disable power containment\n");
+			DISABLE_FEAT(1L << 14);
+			DISABLE_FEAT(1L << 15);
+
+			/* disable avfs */
+			pci_info(dev, "Vega10: disable avfs\n");
+			DISABLE_FEAT(1L << 10);
+
+			/* stop dpm */
+			pci_info(dev, "Vega10: disable dpm\n");
+			DISABLE_FEAT(1L << 24);
+			DISABLE_FEAT(SMC_DPM_FEATURES);
+
+			/* disable deep sleep */
+			pci_info(dev, "Vega10: disable deep sleep\n");
+			DISABLE_FEAT(1L << 11);
+			DISABLE_FEAT(1L << 12);
+			DISABLE_FEAT(1L << 13);
+			DISABLE_FEAT(1L << 9);
+
+			/* disable ulv */
+			pci_info(dev, "Vega10: disable ulv\n");
+			DISABLE_FEAT(1L << 6);
+
+			/* disable acg */
+			pci_info(dev, "Vega10: disable acg\n");
+			DISABLE_FEAT(1L << 28);
+
+			/* disable PCC limit */
+			pci_info(dev, "Vega10: disable PCC\n");
+			DISABLE_FEAT(1L << 29);
+
+#undef DISABLE_FEAT
+			break;
+
+		case VEGA12:
+		case VEGA20:
+			pci_info(dev, "Vega12/20: disable GFX\n");
+			WREG32(mmMP1_SMN_C2PMSG_90, 0x00);
+			WREG32(mmMP1_SMN_C2PMSG_82, 0x00);
+			WREG32(mmMP1_SMN_C2PMSG_66,
+			       PPSMC_MSG_DisableAllSmuFeatures);
+			SMU_WAIT();
+			break;
+
+		default:
+			break;
+		}
+	}
+
+#define PSP_WAIT(reg_index, reg_val, mask, err_exit)                                                                         \
+	do {                                                                                                                 \
+		for (timeout = 1000000; timeout; --timeout) {                                                                \
+			tmp = RREG32(reg_index);                                                                             \
+			if ((tmp & mask) == reg_val)                                                                         \
+				break;                                                                                       \
+			udelay(1);                                                                                           \
+		}                                                                                                            \
+		if (((tmp & mask) != reg_val)) {                                                                             \
+			pci_err(dev,                                                                                         \
+				"Navi10: reg %08x (0x%08x, masked 0x%08x) did not reach needed value (0x%08x), (line %d)\n", \
+				reg_index, tmp, (tmp & mask), reg_val,                                                       \
+				__LINE__);                                                                                   \
+			if (err_exit)                                                                                        \
+				goto mode1_out;                                                                              \
+		}                                                                                                            \
+	} while (0)
+
+	pci_info(dev, "Navi10: begin psp mode 1 reset\n");
+
+	/* I don't know if I have the base register right for non-navi cards */
+	if (device_type == NAVI) {
+		/* mark amdgpu_atombios_scratch_regs_engine_hung */
+		tmp = RREG32(scratch_reg_offset + 3);
+		tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+		WREG32(scratch_reg_offset + 3, tmp);
+	}
+
+	/* check validity of PSP before reset */
+	pci_info(dev, "Navi10: PSP wait\n");
+	PSP_WAIT(mmMP0_SMN_C2PMSG_64, 0x80000000, 0x8000FFFF, false);
+
+	/* reset command */
+	pci_info(dev, "Navi10: do mode1 reset\n");
+	WREG32(mmMP0_SMN_C2PMSG_64, GFX_CTRL_CMD_ID_MODE1_RST);
+	msleep(500);
+
+	/* wait for ACK */
+	pci_info(dev, "Navi10: PSP wait\n");
+	PSP_WAIT(mmMP0_SMN_C2PMSG_33, 0x80000000, 0x80000000, true);
+
+	pci_info(dev, "Navi10: psp mode1 succeeded\n");
+
+	/* restore state here and wait */
+	pci_restore_state(dev);
+
+	for (timeout = 100000; timeout; --timeout) {
+		tmp = RREG32(mmRCC_DEV0_EPF0_RCC_CONFIG_MEMSIZE);
+
+		if (tmp != 0xffffffff)
+			break;
+		udelay(1);
+	}
+	pci_info(dev, "Navi10: memsize: %x\n", tmp);
+
+	if (device_type == NAVI) {
+		/* unmark amdgpu_atombios_scratch_regs_engine_hung */
+		tmp = RREG32(scratch_reg_offset + 3);
+		tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+		WREG32(scratch_reg_offset + 3, tmp);
+	}
+
+	/* this takes a long time :( */
+	for (timeout = 100; timeout; --timeout) {
+		/* see if PSP bootloader comes back */
+		if (RREG32(mmMP0_SMN_C2PMSG_35) & 0x80000000L)
+			break;
+
+		pci_info(dev, "Navi10: PSP bootloader flags? %x, timeout: %s\n",
+			 RREG32(mmMP0_SMN_C2PMSG_35), !timeout ? "yes" : "no");
+
+		msleep(100);
+	}
+
+	if (!timeout && !(RREG32(mmMP0_SMN_C2PMSG_35) & 0x80000000L)) {
+		pci_info(
+			dev,
+			"Navi10: timed out waiting for PSP bootloader to respond after reset\n");
+	} else {
+		pci_set_power_state(dev, PCI_D3hot);
+		pci_info(dev, "Navi10: PSP mode1 reset successful\n");
+	}
+
+mode1_out:
+	pci_restore_state(dev);
+
+#undef RREG32
+#undef WREG32
+#undef RREG32_PCIE
+#undef WREG32_PCIE
+#undef PSP_WAIT
+#undef SMU_WAIT
+
+out:
+	/* unmap BAR5 */
+	iounmap(mmio);
+
+	/* restore the state and command register */
+	pci_write_config_word(dev, PCI_COMMAND, cfg);
+	return 0;
+}
+
 static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
-		 reset_intel_82599_sfp_virtfn },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M_VGA,
-		reset_ivb_igd },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA,
-		reset_ivb_igd },
+	  reset_intel_82599_sfp_virtfn },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M_VGA, reset_ivb_igd },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA, reset_ivb_igd },
 	{ PCI_VENDOR_ID_SAMSUNG, 0xa804, nvme_disable_and_flr },
 	{ PCI_VENDOR_ID_INTEL, 0x0953, delay_250ms_after_flr },
-	{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
-		reset_chelsio_generic_dev },
+	{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID, reset_chelsio_generic_dev },
+	{ PCI_VENDOR_ID_ATI, 0x6860, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x6861, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x6862, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x6863, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x6864, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x6867, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x6868, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x6869, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x686a, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x686b, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x686c, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x686d, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x686e, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x686f, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x687f, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x69A0, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x69A1, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x69A2, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x69A3, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x69AF, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x66A0, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x66A1, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x66A2, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x66A3, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x66A4, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x66A7, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x66AF, reset_amd_navi10 },
+	{ 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 },
+	{ PCI_VENDOR_ID_ATI, 0x7340, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x7341, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x7347, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x734F, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x7360, reset_amd_navi10 },
+	{ PCI_VENDOR_ID_ATI, 0x7362, reset_amd_navi10 },
 	{ 0 }
 };
2 Likes