ACPICA: Hardware: Add sleep register hooks
authorLv Zheng <lv.zheng@intel.com>
Wed, 28 Dec 2016 07:28:49 +0000 (15:28 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 2 Jan 2017 22:18:41 +0000 (23:18 +0100)
ACPICA commit ba665dc8e20d9f7730466a659564dd6c557a6cbc

In Linux, para-virtualization implmentation hooks critical register
writes to prevent real hardware operations. This increases divergences
when the sleep registers are cracked in Linux resident ACPICA.

This patch tries to introduce a single OSL to reduce the divergences.

Link: https://github.com/acpica/acpica/commit/ba665dc8
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/acpica/hwesleep.c
drivers/acpi/acpica/hwsleep.c
drivers/acpi/osl.c
include/acpi/acexcep.h
include/acpi/acpiosxf.h
tools/power/acpi/os_specific/service_layers/osunixxf.c

index 3f2fb4b31fdc06779ba43c5a88d9b021f671b697..9023a1b87a54a7e02c510d4bfe99626bbccd6ab5 100644 (file)
@@ -43,7 +43,6 @@
  */
 
 #include <acpi/acpi.h>
-#include <linux/acpi.h>
 #include "accommon.h"
 
 #define _COMPONENT          ACPI_HARDWARE
@@ -103,7 +102,7 @@ void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument)
 acpi_status acpi_hw_extended_sleep(u8 sleep_state)
 {
        acpi_status status;
-       u8 sleep_type_value;
+       u8 sleep_control;
        u64 sleep_status;
 
        ACPI_FUNCTION_TRACE(hw_extended_sleep);
@@ -125,18 +124,6 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state)
 
        acpi_gbl_system_awake_and_running = FALSE;
 
-       /* Flush caches, as per ACPI specification */
-
-       ACPI_FLUSH_CPU_CACHE();
-
-       status = acpi_os_prepare_extended_sleep(sleep_state,
-                                               acpi_gbl_sleep_type_a,
-                                               acpi_gbl_sleep_type_b);
-       if (ACPI_SKIP(status))
-               return_ACPI_STATUS(AE_OK);
-       if (ACPI_FAILURE(status))
-               return_ACPI_STATUS(status);
-
        /*
         * Set the SLP_TYP and SLP_EN bits.
         *
@@ -146,12 +133,22 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state)
        ACPI_DEBUG_PRINT((ACPI_DB_INIT,
                          "Entering sleep state [S%u]\n", sleep_state));
 
-       sleep_type_value =
-           ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
-            ACPI_X_SLEEP_TYPE_MASK);
+       sleep_control = ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
+                        ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE;
+
+       /* Flush caches, as per ACPI specification */
+
+       ACPI_FLUSH_CPU_CACHE();
+
+       status = acpi_os_enter_sleep(sleep_state, sleep_control, 0);
+       if (status == AE_CTRL_TERMINATE) {
+               return_ACPI_STATUS(AE_OK);
+       }
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
 
-       status = acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE),
-                           &acpi_gbl_FADT.sleep_control);
+       status = acpi_write((u64)sleep_control, &acpi_gbl_FADT.sleep_control);
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
index d00c9810845b2f3a2ccf3827674db1fd5678bcf2..563c5d91663f8999e8cf2b9da7da183af4264059 100644 (file)
@@ -43,7 +43,6 @@
  */
 
 #include <acpi/acpi.h>
-#include <linux/acpi.h>
 #include "accommon.h"
 
 #define _COMPONENT          ACPI_HARDWARE
@@ -152,12 +151,14 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
 
        ACPI_FLUSH_CPU_CACHE();
 
-       status = acpi_os_prepare_sleep(sleep_state, pm1a_control,
-                                      pm1b_control);
-       if (ACPI_SKIP(status))
+       status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control);
+       if (status == AE_CTRL_TERMINATE) {
                return_ACPI_STATUS(AE_OK);
-       if (ACPI_FAILURE(status))
+       }
+       if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
+       }
+
        /* Write #2: Write both SLP_TYP + SLP_EN */
 
        status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
index 57fb5f468ac2025ecb80775d420bebc9a867b998..db78d353bab1f94b4d88c8b767b105a1da486d0b 100644 (file)
@@ -1686,7 +1686,7 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control,
        if (rc < 0)
                return AE_ERROR;
        else if (rc > 0)
-               return AE_CTRL_SKIP;
+               return AE_CTRL_TERMINATE;
 
        return AE_OK;
 }
@@ -1697,6 +1697,7 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
        __acpi_os_prepare_sleep = func;
 }
 
+#if (ACPI_REDUCED_HARDWARE)
 acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
                                  u32 val_b)
 {
@@ -1707,13 +1708,35 @@ acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
        if (rc < 0)
                return AE_ERROR;
        else if (rc > 0)
-               return AE_CTRL_SKIP;
+               return AE_CTRL_TERMINATE;
 
        return AE_OK;
 }
+#else
+acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
+                                 u32 val_b)
+{
+       return AE_OK;
+}
+#endif
 
 void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
                               u32 val_a, u32 val_b))
 {
        __acpi_os_prepare_extended_sleep = func;
 }
+
+acpi_status acpi_os_enter_sleep(u8 sleep_state,
+                               u32 reg_a_value, u32 reg_b_value)
+{
+       acpi_status status;
+
+       if (acpi_gbl_reduced_hardware)
+               status = acpi_os_prepare_extended_sleep(sleep_state,
+                                                       reg_a_value,
+                                                       reg_b_value);
+       else
+               status = acpi_os_prepare_sleep(sleep_state,
+                                              reg_a_value, reg_b_value);
+       return status;
+}
index 2c396344a7a256c7394f40318a52703b5cc27395..1155002761a7a59db6a53c564094462aea3da851 100644 (file)
@@ -91,7 +91,6 @@ struct acpi_exception_info {
 #define ACPI_SUCCESS(a)                 (!(a))
 #define ACPI_FAILURE(a)                 (a)
 
-#define ACPI_SKIP(a)                    (a == AE_CTRL_SKIP)
 #define AE_OK                           (acpi_status) 0x0000
 
 /*
@@ -211,11 +210,10 @@ struct acpi_exception_info {
 #define AE_CTRL_TRANSFER                EXCEP_CTL (0x0008)
 #define AE_CTRL_BREAK                   EXCEP_CTL (0x0009)
 #define AE_CTRL_CONTINUE                EXCEP_CTL (0x000A)
-#define AE_CTRL_SKIP                    EXCEP_CTL (0x000B)
-#define AE_CTRL_PARSE_CONTINUE          EXCEP_CTL (0x000C)
-#define AE_CTRL_PARSE_PENDING           EXCEP_CTL (0x000D)
+#define AE_CTRL_PARSE_CONTINUE          EXCEP_CTL (0x000B)
+#define AE_CTRL_PARSE_PENDING           EXCEP_CTL (0x000C)
 
-#define AE_CODE_CTRL_MAX                0x000D
+#define AE_CODE_CTRL_MAX                0x000C
 
 /* Exception strings for acpi_format_exception */
 
@@ -378,7 +376,6 @@ static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = {
        EXCEP_TXT("AE_CTRL_TRANSFER", "Transfer control to called method"),
        EXCEP_TXT("AE_CTRL_BREAK", "A Break has been executed"),
        EXCEP_TXT("AE_CTRL_CONTINUE", "A Continue has been executed"),
-       EXCEP_TXT("AE_CTRL_SKIP", "Not currently used"),
        EXCEP_TXT("AE_CTRL_PARSE_CONTINUE", "Used to skip over bad opcodes"),
        EXCEP_TXT("AE_CTRL_PARSE_PENDING", "Used to implement AML While loops")
 };
index 42ab9b37f33d502fa222cf08847e31e28b5809de..e166013b471263b170d199376815e50900cbb25d 100644 (file)
@@ -333,6 +333,10 @@ u64 acpi_os_get_timer(void);
 acpi_status acpi_os_signal(u32 function, void *info);
 #endif
 
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_enter_sleep
+acpi_status acpi_os_enter_sleep(u8 sleep_state, u32 rega_value, u32 regb_value);
+#endif
+
 /*
  * Debug print routines
  */
index 10648aaf616476aa24577a1820f0a8ff4150b513..e41c2644c347531f8c0c0d03bb47afbd5d720a58 100644 (file)
@@ -316,6 +316,28 @@ acpi_os_physical_table_override(struct acpi_table_header *existing_table,
        return (AE_SUPPORT);
 }
 
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_os_enter_sleep
+ *
+ * PARAMETERS:  sleep_state         - Which sleep state to enter
+ *              rega_value          - Register A value
+ *              regb_value          - Register B value
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: A hook before writing sleep registers to enter the sleep
+ *              state. Return AE_CTRL_TERMINATE to skip further sleep register
+ *              writes.
+ *
+ *****************************************************************************/
+
+acpi_status acpi_os_enter_sleep(u8 sleep_state, u32 rega_value, u32 regb_value)
+{
+
+       return (AE_OK);
+}
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_os_redirect_output