Implement some more suspend/resume Linux compat such that inteldrm(4) can
authorkettenis <kettenis@openbsd.org>
Sat, 13 Jul 2024 15:38:21 +0000 (15:38 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 13 Jul 2024 15:38:21 +0000 (15:38 +0000)
achieve RC6 and save a significant amount of power for S0i.

ok jsg@

sys/dev/pci/drm/drm_drv.c
sys/dev/pci/drm/drm_linux.c
sys/dev/pci/drm/i915/gt/intel_gt_pm.c
sys/dev/pci/drm/include/generated/autoconf.h
sys/dev/pci/drm/include/linux/acpi.h
sys/dev/pci/drm/include/linux/suspend.h

index 4193f4c..3cf746c 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/pseudo_fs.h>
 #include <linux/slab.h>
 #include <linux/srcu.h>
+#include <linux/suspend.h>
 
 #include <drm/drm_accel.h>
 #include <drm/drm_cache.h>
@@ -1548,10 +1549,19 @@ drm_activate(struct device *self, int act)
 
        switch (act) {
        case DVACT_QUIESCE:
+#ifdef CONFIG_ACPI
+               if (acpi_softc && acpi_softc->sc_state == ACPI_STATE_S3)
+                       pm_suspend_target_state = PM_SUSPEND_MEM;
+               else
+                       pm_suspend_target_state = PM_SUSPEND_TO_IDLE;
+#else
+               pm_suspend_target_state = PM_SUSPEND_TO_IDLE;
+#endif
                drm_quiesce(dev);
                break;
        case DVACT_WAKEUP:
                drm_wakeup(dev);
+               pm_suspend_target_state = PM_SUSPEND_ON;
                break;
        }
 
index 3204b4a..2d3e919 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: drm_linux.c,v 1.114 2024/06/13 18:05:54 kettenis Exp $        */
+/*     $OpenBSD: drm_linux.c,v 1.115 2024/07/13 15:38:21 kettenis Exp $        */
 /*
  * Copyright (c) 2013 Jonathan Gray <jsg@openbsd.org>
  * Copyright (c) 2015, 2016 Mark Kettenis <kettenis@openbsd.org>
@@ -51,6 +51,7 @@
 #include <linux/kthread.h>
 #include <linux/processor.h>
 #include <linux/sync_file.h>
+#include <linux/suspend.h>
 
 #include <drm/drm_device.h>
 #include <drm/drm_connector.h>
@@ -1345,6 +1346,8 @@ vga_put(struct pci_dev *pdev, int rsrc)
 
 #endif
 
+suspend_state_t pm_suspend_target_state;
+
 /*
  * ACPI types and interfaces.
  */
@@ -1360,6 +1363,8 @@ vga_put(struct pci_dev *pdev, int rsrc)
 #include <dev/acpi/amltypes.h>
 #include <dev/acpi/dsdt.h>
 
+struct acpi_fadt acpi_gbl_FADT;
+
 acpi_status
 acpi_get_table(const char *sig, int instance,
     struct acpi_table_header **hdr)
@@ -2851,6 +2856,13 @@ drm_linux_init(void)
 
        kmap_atomic_va =
            (vaddr_t)km_alloc(PAGE_SIZE, &kv_any, &kp_none, &kd_waitok);
+
+#if NACPI > 0
+       if (acpi_softc) {
+               memcpy(&acpi_gbl_FADT, acpi_softc->sc_fadt,
+                   sizeof(acpi_gbl_FADT));
+       }
+#endif
 }
 
 void
index 8445125..ad361eb 100644 (file)
@@ -326,7 +326,6 @@ void intel_gt_suspend_prepare(struct intel_gt *gt)
        wait_for_suspend(gt);
 }
 
-#ifdef notyet
 static suspend_state_t pm_suspend_target(void)
 {
 #if IS_ENABLED(CONFIG_SUSPEND) && IS_ENABLED(CONFIG_PM_SLEEP)
@@ -335,7 +334,6 @@ static suspend_state_t pm_suspend_target(void)
        return PM_SUSPEND_TO_IDLE;
 #endif
 }
-#endif
 
 void intel_gt_suspend_late(struct intel_gt *gt)
 {
@@ -361,10 +359,8 @@ void intel_gt_suspend_late(struct intel_gt *gt)
         * powermanagement enabled, but we also retain system state and so
         * it remains safe to keep on using our allocated memory.
         */
-#ifdef notyet
        if (pm_suspend_target() == PM_SUSPEND_TO_IDLE)
                return;
-#endif
 
        with_intel_runtime_pm(gt->uncore->rpm, wakeref) {
                intel_rps_disable(&gt->rps);
index adcef50..9c8565e 100644 (file)
@@ -93,5 +93,6 @@
 #endif
 
 #if defined(SUSPEND) || defined(HIBERNATE)
+#define CONFIG_SUSPEND                         1
 #define CONFIG_PM_SLEEP                                1
 #endif
index b10d28e..b15702c 100644 (file)
@@ -88,4 +88,7 @@ int unregister_acpi_notifier(struct notifier_block *);
 
 int acpi_target_system_state(void);
 
+extern struct acpi_fadt acpi_gbl_FADT;
+#define ACPI_FADT_LOW_POWER_S0         (1 << 21)
+
 #endif
index e69de29..223844e 100644 (file)
@@ -0,0 +1,14 @@
+/* Public domain. */
+
+#ifndef _LINUX_SUSPEND_H
+#define _LINUX_SUSPEND_H
+
+typedef int suspend_state_t;
+
+#define PM_SUSPEND_ON          0
+#define PM_SUSPEND_MEM         1
+#define PM_SUSPEND_TO_IDLE     2
+
+extern suspend_state_t pm_suspend_target_state;
+
+#endif