aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpi_extlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpi_extlog.c')
-rw-r--r--drivers/acpi/acpi_extlog.c62
1 files changed, 12 insertions, 50 deletions
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c
index a6869e110ce5..94166680b3a3 100644
--- a/drivers/acpi/acpi_extlog.c
+++ b/drivers/acpi/acpi_extlog.c
@@ -9,7 +9,6 @@
9 9
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/acpi.h> 11#include <linux/acpi.h>
12#include <acpi/acpi_bus.h>
13#include <linux/cper.h> 12#include <linux/cper.h>
14#include <linux/ratelimit.h> 13#include <linux/ratelimit.h>
15#include <asm/cpu.h> 14#include <asm/cpu.h>
@@ -20,11 +19,9 @@
20#define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */ 19#define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */
21 20
22#define EXTLOG_DSM_REV 0x0 21#define EXTLOG_DSM_REV 0x0
23#define EXTLOG_FN_QUERY 0x0
24#define EXTLOG_FN_ADDR 0x1 22#define EXTLOG_FN_ADDR 0x1
25 23
26#define FLAG_OS_OPTIN BIT(0) 24#define FLAG_OS_OPTIN BIT(0)
27#define EXTLOG_QUERY_L1_EXIST BIT(1)
28#define ELOG_ENTRY_VALID (1ULL<<63) 25#define ELOG_ENTRY_VALID (1ULL<<63)
29#define ELOG_ENTRY_LEN 0x1000 26#define ELOG_ENTRY_LEN 0x1000
30 27
@@ -43,7 +40,7 @@ struct extlog_l1_head {
43 u8 rev1[12]; 40 u8 rev1[12];
44}; 41};
45 42
46static u8 extlog_dsm_uuid[] = "663E35AF-CC10-41A4-88EA-5470AF055295"; 43static u8 extlog_dsm_uuid[] __initdata = "663E35AF-CC10-41A4-88EA-5470AF055295";
47 44
48/* L1 table related physical address */ 45/* L1 table related physical address */
49static u64 elog_base; 46static u64 elog_base;
@@ -153,62 +150,27 @@ static int extlog_print(struct notifier_block *nb, unsigned long val,
153 return NOTIFY_DONE; 150 return NOTIFY_DONE;
154} 151}
155 152
156static int extlog_get_dsm(acpi_handle handle, int rev, int func, u64 *ret) 153static bool __init extlog_get_l1addr(void)
157{ 154{
158 struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
159 struct acpi_object_list input;
160 union acpi_object params[4], *obj;
161 u8 uuid[16]; 155 u8 uuid[16];
162 int i; 156 acpi_handle handle;
157 union acpi_object *obj;
163 158
164 acpi_str_to_uuid(extlog_dsm_uuid, uuid); 159 acpi_str_to_uuid(extlog_dsm_uuid, uuid);
165 input.count = 4;
166 input.pointer = params;
167 params[0].type = ACPI_TYPE_BUFFER;
168 params[0].buffer.length = 16;
169 params[0].buffer.pointer = uuid;
170 params[1].type = ACPI_TYPE_INTEGER;
171 params[1].integer.value = rev;
172 params[2].type = ACPI_TYPE_INTEGER;
173 params[2].integer.value = func;
174 params[3].type = ACPI_TYPE_PACKAGE;
175 params[3].package.count = 0;
176 params[3].package.elements = NULL;
177
178 if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf)))
179 return -1;
180
181 *ret = 0;
182 obj = (union acpi_object *)buf.pointer;
183 if (obj->type == ACPI_TYPE_INTEGER) {
184 *ret = obj->integer.value;
185 } else if (obj->type == ACPI_TYPE_BUFFER) {
186 if (obj->buffer.length <= 8) {
187 for (i = 0; i < obj->buffer.length; i++)
188 *ret |= (obj->buffer.pointer[i] << (i * 8));
189 }
190 }
191 kfree(buf.pointer);
192
193 return 0;
194}
195
196static bool extlog_get_l1addr(void)
197{
198 acpi_handle handle;
199 u64 ret;
200 160
201 if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) 161 if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
202 return false; 162 return false;
203 163 if (!acpi_check_dsm(handle, uuid, EXTLOG_DSM_REV, 1 << EXTLOG_FN_ADDR))
204 if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_QUERY, &ret) ||
205 !(ret & EXTLOG_QUERY_L1_EXIST))
206 return false; 164 return false;
207 165 obj = acpi_evaluate_dsm_typed(handle, uuid, EXTLOG_DSM_REV,
208 if (extlog_get_dsm(handle, EXTLOG_DSM_REV, EXTLOG_FN_ADDR, &ret)) 166 EXTLOG_FN_ADDR, NULL, ACPI_TYPE_INTEGER);
167 if (!obj) {
209 return false; 168 return false;
169 } else {
170 l1_dirbase = obj->integer.value;
171 ACPI_FREE(obj);
172 }
210 173
211 l1_dirbase = ret;
212 /* Spec says L1 directory must be 4K aligned, bail out if it isn't */ 174 /* Spec says L1 directory must be 4K aligned, bail out if it isn't */
213 if (l1_dirbase & ((1 << 12) - 1)) { 175 if (l1_dirbase & ((1 << 12) - 1)) {
214 pr_warn(FW_BUG "L1 Directory is invalid at physical %llx\n", 176 pr_warn(FW_BUG "L1 Directory is invalid at physical %llx\n",