summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLv Zheng <lv.zheng@intel.com>2016-12-28 02:28:49 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-01-02 17:18:41 -0500
commit0fc5e8f4e4b33ddfa1d1d673fcd420d6e13eb076 (patch)
tree98882708adde1882b7aa110832c85df4b574a307
parentfcfb45531d7ef71a19caaa0a983611ca57ec04fe (diff)
ACPICA: Hardware: Add sleep register hooks
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>
-rw-r--r--drivers/acpi/acpica/hwesleep.c35
-rw-r--r--drivers/acpi/acpica/hwsleep.c11
-rw-r--r--drivers/acpi/osl.c27
-rw-r--r--include/acpi/acexcep.h9
-rw-r--r--include/acpi/acpiosxf.h4
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c22
6 files changed, 76 insertions, 32 deletions
diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c
index 3f2fb4b31fdc..9023a1b87a54 100644
--- a/drivers/acpi/acpica/hwesleep.c
+++ b/drivers/acpi/acpica/hwesleep.c
@@ -43,7 +43,6 @@
43 */ 43 */
44 44
45#include <acpi/acpi.h> 45#include <acpi/acpi.h>
46#include <linux/acpi.h>
47#include "accommon.h" 46#include "accommon.h"
48 47
49#define _COMPONENT ACPI_HARDWARE 48#define _COMPONENT ACPI_HARDWARE
@@ -103,7 +102,7 @@ void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument)
103acpi_status acpi_hw_extended_sleep(u8 sleep_state) 102acpi_status acpi_hw_extended_sleep(u8 sleep_state)
104{ 103{
105 acpi_status status; 104 acpi_status status;
106 u8 sleep_type_value; 105 u8 sleep_control;
107 u64 sleep_status; 106 u64 sleep_status;
108 107
109 ACPI_FUNCTION_TRACE(hw_extended_sleep); 108 ACPI_FUNCTION_TRACE(hw_extended_sleep);
@@ -125,18 +124,6 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state)
125 124
126 acpi_gbl_system_awake_and_running = FALSE; 125 acpi_gbl_system_awake_and_running = FALSE;
127 126
128 /* Flush caches, as per ACPI specification */
129
130 ACPI_FLUSH_CPU_CACHE();
131
132 status = acpi_os_prepare_extended_sleep(sleep_state,
133 acpi_gbl_sleep_type_a,
134 acpi_gbl_sleep_type_b);
135 if (ACPI_SKIP(status))
136 return_ACPI_STATUS(AE_OK);
137 if (ACPI_FAILURE(status))
138 return_ACPI_STATUS(status);
139
140 /* 127 /*
141 * Set the SLP_TYP and SLP_EN bits. 128 * Set the SLP_TYP and SLP_EN bits.
142 * 129 *
@@ -146,12 +133,22 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state)
146 ACPI_DEBUG_PRINT((ACPI_DB_INIT, 133 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
147 "Entering sleep state [S%u]\n", sleep_state)); 134 "Entering sleep state [S%u]\n", sleep_state));
148 135
149 sleep_type_value = 136 sleep_control = ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
150 ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) & 137 ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE;
151 ACPI_X_SLEEP_TYPE_MASK); 138
139 /* Flush caches, as per ACPI specification */
140
141 ACPI_FLUSH_CPU_CACHE();
142
143 status = acpi_os_enter_sleep(sleep_state, sleep_control, 0);
144 if (status == AE_CTRL_TERMINATE) {
145 return_ACPI_STATUS(AE_OK);
146 }
147 if (ACPI_FAILURE(status)) {
148 return_ACPI_STATUS(status);
149 }
152 150
153 status = acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE), 151 status = acpi_write((u64)sleep_control, &acpi_gbl_FADT.sleep_control);
154 &acpi_gbl_FADT.sleep_control);
155 if (ACPI_FAILURE(status)) { 152 if (ACPI_FAILURE(status)) {
156 return_ACPI_STATUS(status); 153 return_ACPI_STATUS(status);
157 } 154 }
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index d00c9810845b..563c5d91663f 100644
--- a/drivers/acpi/acpica/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -43,7 +43,6 @@
43 */ 43 */
44 44
45#include <acpi/acpi.h> 45#include <acpi/acpi.h>
46#include <linux/acpi.h>
47#include "accommon.h" 46#include "accommon.h"
48 47
49#define _COMPONENT ACPI_HARDWARE 48#define _COMPONENT ACPI_HARDWARE
@@ -152,12 +151,14 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
152 151
153 ACPI_FLUSH_CPU_CACHE(); 152 ACPI_FLUSH_CPU_CACHE();
154 153
155 status = acpi_os_prepare_sleep(sleep_state, pm1a_control, 154 status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control);
156 pm1b_control); 155 if (status == AE_CTRL_TERMINATE) {
157 if (ACPI_SKIP(status))
158 return_ACPI_STATUS(AE_OK); 156 return_ACPI_STATUS(AE_OK);
159 if (ACPI_FAILURE(status)) 157 }
158 if (ACPI_FAILURE(status)) {
160 return_ACPI_STATUS(status); 159 return_ACPI_STATUS(status);
160 }
161
161 /* Write #2: Write both SLP_TYP + SLP_EN */ 162 /* Write #2: Write both SLP_TYP + SLP_EN */
162 163
163 status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); 164 status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 57fb5f468ac2..db78d353bab1 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1686,7 +1686,7 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control,
1686 if (rc < 0) 1686 if (rc < 0)
1687 return AE_ERROR; 1687 return AE_ERROR;
1688 else if (rc > 0) 1688 else if (rc > 0)
1689 return AE_CTRL_SKIP; 1689 return AE_CTRL_TERMINATE;
1690 1690
1691 return AE_OK; 1691 return AE_OK;
1692} 1692}
@@ -1697,6 +1697,7 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
1697 __acpi_os_prepare_sleep = func; 1697 __acpi_os_prepare_sleep = func;
1698} 1698}
1699 1699
1700#if (ACPI_REDUCED_HARDWARE)
1700acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, 1701acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
1701 u32 val_b) 1702 u32 val_b)
1702{ 1703{
@@ -1707,13 +1708,35 @@ acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
1707 if (rc < 0) 1708 if (rc < 0)
1708 return AE_ERROR; 1709 return AE_ERROR;
1709 else if (rc > 0) 1710 else if (rc > 0)
1710 return AE_CTRL_SKIP; 1711 return AE_CTRL_TERMINATE;
1711 1712
1712 return AE_OK; 1713 return AE_OK;
1713} 1714}
1715#else
1716acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a,
1717 u32 val_b)
1718{
1719 return AE_OK;
1720}
1721#endif
1714 1722
1715void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, 1723void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state,
1716 u32 val_a, u32 val_b)) 1724 u32 val_a, u32 val_b))
1717{ 1725{
1718 __acpi_os_prepare_extended_sleep = func; 1726 __acpi_os_prepare_extended_sleep = func;
1719} 1727}
1728
1729acpi_status acpi_os_enter_sleep(u8 sleep_state,
1730 u32 reg_a_value, u32 reg_b_value)
1731{
1732 acpi_status status;
1733
1734 if (acpi_gbl_reduced_hardware)
1735 status = acpi_os_prepare_extended_sleep(sleep_state,
1736 reg_a_value,
1737 reg_b_value);
1738 else
1739 status = acpi_os_prepare_sleep(sleep_state,
1740 reg_a_value, reg_b_value);
1741 return status;
1742}
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 2c396344a7a2..1155002761a7 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -91,7 +91,6 @@ struct acpi_exception_info {
91#define ACPI_SUCCESS(a) (!(a)) 91#define ACPI_SUCCESS(a) (!(a))
92#define ACPI_FAILURE(a) (a) 92#define ACPI_FAILURE(a) (a)
93 93
94#define ACPI_SKIP(a) (a == AE_CTRL_SKIP)
95#define AE_OK (acpi_status) 0x0000 94#define AE_OK (acpi_status) 0x0000
96 95
97/* 96/*
@@ -211,11 +210,10 @@ struct acpi_exception_info {
211#define AE_CTRL_TRANSFER EXCEP_CTL (0x0008) 210#define AE_CTRL_TRANSFER EXCEP_CTL (0x0008)
212#define AE_CTRL_BREAK EXCEP_CTL (0x0009) 211#define AE_CTRL_BREAK EXCEP_CTL (0x0009)
213#define AE_CTRL_CONTINUE EXCEP_CTL (0x000A) 212#define AE_CTRL_CONTINUE EXCEP_CTL (0x000A)
214#define AE_CTRL_SKIP EXCEP_CTL (0x000B) 213#define AE_CTRL_PARSE_CONTINUE EXCEP_CTL (0x000B)
215#define AE_CTRL_PARSE_CONTINUE EXCEP_CTL (0x000C) 214#define AE_CTRL_PARSE_PENDING EXCEP_CTL (0x000C)
216#define AE_CTRL_PARSE_PENDING EXCEP_CTL (0x000D)
217 215
218#define AE_CODE_CTRL_MAX 0x000D 216#define AE_CODE_CTRL_MAX 0x000C
219 217
220/* Exception strings for acpi_format_exception */ 218/* Exception strings for acpi_format_exception */
221 219
@@ -378,7 +376,6 @@ static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = {
378 EXCEP_TXT("AE_CTRL_TRANSFER", "Transfer control to called method"), 376 EXCEP_TXT("AE_CTRL_TRANSFER", "Transfer control to called method"),
379 EXCEP_TXT("AE_CTRL_BREAK", "A Break has been executed"), 377 EXCEP_TXT("AE_CTRL_BREAK", "A Break has been executed"),
380 EXCEP_TXT("AE_CTRL_CONTINUE", "A Continue has been executed"), 378 EXCEP_TXT("AE_CTRL_CONTINUE", "A Continue has been executed"),
381 EXCEP_TXT("AE_CTRL_SKIP", "Not currently used"),
382 EXCEP_TXT("AE_CTRL_PARSE_CONTINUE", "Used to skip over bad opcodes"), 379 EXCEP_TXT("AE_CTRL_PARSE_CONTINUE", "Used to skip over bad opcodes"),
383 EXCEP_TXT("AE_CTRL_PARSE_PENDING", "Used to implement AML While loops") 380 EXCEP_TXT("AE_CTRL_PARSE_PENDING", "Used to implement AML While loops")
384}; 381};
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 42ab9b37f33d..e166013b4712 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -333,6 +333,10 @@ u64 acpi_os_get_timer(void);
333acpi_status acpi_os_signal(u32 function, void *info); 333acpi_status acpi_os_signal(u32 function, void *info);
334#endif 334#endif
335 335
336#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_enter_sleep
337acpi_status acpi_os_enter_sleep(u8 sleep_state, u32 rega_value, u32 regb_value);
338#endif
339
336/* 340/*
337 * Debug print routines 341 * Debug print routines
338 */ 342 */
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index 10648aaf6164..e41c2644c347 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -318,6 +318,28 @@ acpi_os_physical_table_override(struct acpi_table_header *existing_table,
318 318
319/****************************************************************************** 319/******************************************************************************
320 * 320 *
321 * FUNCTION: acpi_os_enter_sleep
322 *
323 * PARAMETERS: sleep_state - Which sleep state to enter
324 * rega_value - Register A value
325 * regb_value - Register B value
326 *
327 * RETURN: Status
328 *
329 * DESCRIPTION: A hook before writing sleep registers to enter the sleep
330 * state. Return AE_CTRL_TERMINATE to skip further sleep register
331 * writes.
332 *
333 *****************************************************************************/
334
335acpi_status acpi_os_enter_sleep(u8 sleep_state, u32 rega_value, u32 regb_value)
336{
337
338 return (AE_OK);
339}
340
341/******************************************************************************
342 *
321 * FUNCTION: acpi_os_redirect_output 343 * FUNCTION: acpi_os_redirect_output
322 * 344 *
323 * PARAMETERS: destination - An open file handle/pointer 345 * PARAMETERS: destination - An open file handle/pointer