drm/amd/pm: Restore config space after reset
authorjsg <jsg@openbsd.org>
Sat, 15 Jun 2024 03:42:34 +0000 (03:42 +0000)
committerjsg <jsg@openbsd.org>
Sat, 15 Jun 2024 03:42:34 +0000 (03:42 +0000)
From Lijo Lazar
7e12479958532fb7f9ce5160dc7bb08513eef807 in linux-6.6.y/6.6.33
30d1cda8ce31ab49051ff7159280c542a738b23d in mainline linux

sys/dev/pci/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c

index 37902e9..ca4b8f9 100644 (file)
@@ -2041,6 +2041,20 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
        return sizeof(struct gpu_metrics_v1_3);
 }
 
+static void smu_v13_0_6_restore_pci_config(struct smu_context *smu)
+{
+       STUB();
+#if notyet
+       struct amdgpu_device *adev = smu->adev;
+       int i;
+
+       for (i = 0; i < 16; i++)
+               pci_write_config_dword(adev->pdev, i * 4,
+                                      adev->pdev->saved_config_space[i]);
+       pci_restore_msi_state(adev->pdev);
+#endif
+}
+
 static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
 {
        int ret = 0, index;
@@ -2062,6 +2076,20 @@ static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
        /* Restore the config space saved during init */
        amdgpu_device_load_pci_state(adev->pdev);
 
+       /* Certain platforms have switches which assign virtual BAR values to
+        * devices. OS uses the virtual BAR values and device behind the switch
+        * is assgined another BAR value. When device's config space registers
+        * are queried, switch returns the virtual BAR values. When mode-2 reset
+        * is performed, switch is unaware of it, and will continue to return
+        * the same virtual values to the OS.This affects
+        * pci_restore_config_space() API as it doesn't write the value saved if
+        * the current value read from config space is the same as what is
+        * saved. As a workaround, make sure the config space is restored
+        * always.
+        */
+       if (!(adev->flags & AMD_IS_APU))
+               smu_v13_0_6_restore_pci_config(smu);
+
        dev_dbg(smu->adev->dev, "wait for reset ack\n");
        do {
                ret = smu_cmn_wait_for_response(smu);