drm/xe: Ensure memory eviction on s2idle.
authorRodrigo Vivi <rodrigo.vivi@intel.com>
Tue, 25 Jul 2023 22:11:59 +0000 (18:11 -0400)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 21 Dec 2023 16:39:16 +0000 (11:39 -0500)
On discrete cards we cannot allow the pci subsystem to skip
the regular suspend and we need to unblock the d3cold.

Cc: Anshuman Gupta <anshuman.gupta@intel.com>
Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_pci.c
drivers/gpu/drm/xe/xe_pm.c

index 4cbacc80594bc6751739eaf2eb599cdf228fa4ff..6e31b596683e7fd455f0bb0eeafffe5ec0b7e099 100644 (file)
@@ -30,6 +30,28 @@ enum toggle_d3cold {
        D3COLD_ENABLE,
 };
 
+static void d3cold_toggle(struct pci_dev *pdev, enum toggle_d3cold toggle)
+{
+       struct xe_device *xe = pdev_to_xe_device(pdev);
+       struct pci_dev *root_pdev;
+
+       if (!xe->d3cold.capable)
+               return;
+
+       root_pdev = pcie_find_root_port(pdev);
+       if (!root_pdev)
+               return;
+
+       switch (toggle) {
+       case D3COLD_DISABLE:
+               pci_d3cold_disable(root_pdev);
+               break;
+       case D3COLD_ENABLE:
+               pci_d3cold_enable(root_pdev);
+               break;
+       }
+}
+
 struct xe_subplatform_desc {
        enum xe_subplatform subplatform;
        const char *name;
@@ -697,6 +719,13 @@ static int xe_pci_suspend(struct device *dev)
        if (err)
                return err;
 
+       /*
+        * Enabling D3Cold is needed for S2Idle/S0ix.
+        * It is save to allow here since xe_pm_suspend has evicted
+        * the local memory and the direct complete optimization is disabled.
+        */
+       d3cold_toggle(pdev, D3COLD_ENABLE);
+
        pci_save_state(pdev);
        pci_disable_device(pdev);
 
@@ -712,6 +741,9 @@ static int xe_pci_resume(struct device *dev)
        struct pci_dev *pdev = to_pci_dev(dev);
        int err;
 
+       /* Give back the D3Cold decision to the runtime P M*/
+       d3cold_toggle(pdev, D3COLD_DISABLE);
+
        err = pci_set_power_state(pdev, PCI_D0);
        if (err)
                return err;
@@ -731,28 +763,6 @@ static int xe_pci_resume(struct device *dev)
        return 0;
 }
 
-static void d3cold_toggle(struct pci_dev *pdev, enum toggle_d3cold toggle)
-{
-       struct xe_device *xe = pdev_to_xe_device(pdev);
-       struct pci_dev *root_pdev;
-
-       if (!xe->d3cold.capable)
-               return;
-
-       root_pdev = pcie_find_root_port(pdev);
-       if (!root_pdev)
-               return;
-
-       switch (toggle) {
-       case D3COLD_DISABLE:
-               pci_d3cold_disable(root_pdev);
-               break;
-       case D3COLD_ENABLE:
-               pci_d3cold_enable(root_pdev);
-               break;
-       }
-}
-
 static int xe_pci_runtime_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
index a20a2fb34a7df4209a5f23063937a87d57ecaa11..cdde0d87fd9f4967b1aec7580289dcf6ab36e23b 100644 (file)
@@ -128,6 +128,17 @@ static void xe_pm_runtime_init(struct xe_device *xe)
 {
        struct device *dev = xe->drm.dev;
 
+       /*
+        * Disable the system suspend direct complete optimization.
+        * We need to ensure that the regular device suspend/resume functions
+        * are called since our runtime_pm cannot guarantee local memory
+        * eviction for d3cold.
+        * TODO: Check HDA audio dependencies claimed by i915, and then enforce
+        *       this option to integrated graphics as well.
+        */
+       if (IS_DGFX(xe))
+               dev_pm_set_driver_flags(dev, DPM_FLAG_NO_DIRECT_COMPLETE);
+
        pm_runtime_use_autosuspend(dev);
        pm_runtime_set_autosuspend_delay(dev, 1000);
        pm_runtime_set_active(dev);