diff options
Diffstat (limited to 'drivers/acpi')
52 files changed, 2655 insertions, 829 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index a34a22841002..d0f3265fb85d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -42,6 +42,12 @@ menuconfig ACPI | |||
42 | 42 | ||
43 | if ACPI | 43 | if ACPI |
44 | 44 | ||
45 | config ACPI_LEGACY_TABLES_LOOKUP | ||
46 | bool | ||
47 | |||
48 | config ARCH_MIGHT_HAVE_ACPI_PDC | ||
49 | bool | ||
50 | |||
45 | config ACPI_SLEEP | 51 | config ACPI_SLEEP |
46 | bool | 52 | bool |
47 | depends on SUSPEND || HIBERNATION | 53 | depends on SUSPEND || HIBERNATION |
@@ -370,6 +376,7 @@ config ACPI_EXTLOG | |||
370 | tristate "Extended Error Log support" | 376 | tristate "Extended Error Log support" |
371 | depends on X86_MCE && X86_LOCAL_APIC | 377 | depends on X86_MCE && X86_LOCAL_APIC |
372 | select UEFI_CPER | 378 | select UEFI_CPER |
379 | select RAS | ||
373 | default n | 380 | default n |
374 | help | 381 | help |
375 | Certain usages such as Predictive Failure Analysis (PFA) require | 382 | Certain usages such as Predictive Failure Analysis (PFA) require |
@@ -384,6 +391,7 @@ config ACPI_EXTLOG | |||
384 | 391 | ||
385 | Enhanced MCA Logging allows firmware to provide additional error | 392 | Enhanced MCA Logging allows firmware to provide additional error |
386 | information to system software, synchronous with MCE or CMCI. This | 393 | information to system software, synchronous with MCE or CMCI. This |
387 | driver adds support for that functionality. | 394 | driver adds support for that functionality with corresponding |
395 | tracepoint which carries that information to userspace. | ||
388 | 396 | ||
389 | endif # ACPI | 397 | endif # ACPI |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index ea55e0179f81..505d4d79fe3e 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -36,6 +36,7 @@ acpi-y += scan.o | |||
36 | acpi-y += resource.o | 36 | acpi-y += resource.o |
37 | acpi-y += acpi_processor.o | 37 | acpi-y += acpi_processor.o |
38 | acpi-y += processor_core.o | 38 | acpi-y += processor_core.o |
39 | acpi-$(CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC) += processor_pdc.o | ||
39 | acpi-y += ec.o | 40 | acpi-y += ec.o |
40 | acpi-$(CONFIG_ACPI_DOCK) += dock.o | 41 | acpi-$(CONFIG_ACPI_DOCK) += dock.o |
41 | acpi-y += pci_root.o pci_link.o pci_irq.o | 42 | acpi-y += pci_root.o pci_link.o pci_irq.o |
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index c67f6f5ad611..36b0e61f9c09 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
@@ -30,6 +30,10 @@ | |||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/dmi.h> | 31 | #include <linux/dmi.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
34 | #include <linux/proc_fs.h> | ||
35 | #include <linux/seq_file.h> | ||
36 | #endif | ||
33 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
34 | #include <linux/power_supply.h> | 38 | #include <linux/power_supply.h> |
35 | #include <linux/acpi.h> | 39 | #include <linux/acpi.h> |
@@ -52,6 +56,7 @@ MODULE_AUTHOR("Paul Diefenbaugh"); | |||
52 | MODULE_DESCRIPTION("ACPI AC Adapter Driver"); | 56 | MODULE_DESCRIPTION("ACPI AC Adapter Driver"); |
53 | MODULE_LICENSE("GPL"); | 57 | MODULE_LICENSE("GPL"); |
54 | 58 | ||
59 | |||
55 | static int acpi_ac_add(struct acpi_device *device); | 60 | static int acpi_ac_add(struct acpi_device *device); |
56 | static int acpi_ac_remove(struct acpi_device *device); | 61 | static int acpi_ac_remove(struct acpi_device *device); |
57 | static void acpi_ac_notify(struct acpi_device *device, u32 event); | 62 | static void acpi_ac_notify(struct acpi_device *device, u32 event); |
@@ -67,6 +72,13 @@ static int acpi_ac_resume(struct device *dev); | |||
67 | #endif | 72 | #endif |
68 | static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); | 73 | static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); |
69 | 74 | ||
75 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
76 | extern struct proc_dir_entry *acpi_lock_ac_dir(void); | ||
77 | extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); | ||
78 | static int acpi_ac_open_fs(struct inode *inode, struct file *file); | ||
79 | #endif | ||
80 | |||
81 | |||
70 | static int ac_sleep_before_get_state_ms; | 82 | static int ac_sleep_before_get_state_ms; |
71 | 83 | ||
72 | static struct acpi_driver acpi_ac_driver = { | 84 | static struct acpi_driver acpi_ac_driver = { |
@@ -91,6 +103,16 @@ struct acpi_ac { | |||
91 | 103 | ||
92 | #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) | 104 | #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) |
93 | 105 | ||
106 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
107 | static const struct file_operations acpi_ac_fops = { | ||
108 | .owner = THIS_MODULE, | ||
109 | .open = acpi_ac_open_fs, | ||
110 | .read = seq_read, | ||
111 | .llseek = seq_lseek, | ||
112 | .release = single_release, | ||
113 | }; | ||
114 | #endif | ||
115 | |||
94 | /* -------------------------------------------------------------------------- | 116 | /* -------------------------------------------------------------------------- |
95 | AC Adapter Management | 117 | AC Adapter Management |
96 | -------------------------------------------------------------------------- */ | 118 | -------------------------------------------------------------------------- */ |
@@ -143,6 +165,83 @@ static enum power_supply_property ac_props[] = { | |||
143 | POWER_SUPPLY_PROP_ONLINE, | 165 | POWER_SUPPLY_PROP_ONLINE, |
144 | }; | 166 | }; |
145 | 167 | ||
168 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
169 | /* -------------------------------------------------------------------------- | ||
170 | FS Interface (/proc) | ||
171 | -------------------------------------------------------------------------- */ | ||
172 | |||
173 | static struct proc_dir_entry *acpi_ac_dir; | ||
174 | |||
175 | static int acpi_ac_seq_show(struct seq_file *seq, void *offset) | ||
176 | { | ||
177 | struct acpi_ac *ac = seq->private; | ||
178 | |||
179 | |||
180 | if (!ac) | ||
181 | return 0; | ||
182 | |||
183 | if (acpi_ac_get_state(ac)) { | ||
184 | seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | seq_puts(seq, "state: "); | ||
189 | switch (ac->state) { | ||
190 | case ACPI_AC_STATUS_OFFLINE: | ||
191 | seq_puts(seq, "off-line\n"); | ||
192 | break; | ||
193 | case ACPI_AC_STATUS_ONLINE: | ||
194 | seq_puts(seq, "on-line\n"); | ||
195 | break; | ||
196 | default: | ||
197 | seq_puts(seq, "unknown\n"); | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int acpi_ac_open_fs(struct inode *inode, struct file *file) | ||
205 | { | ||
206 | return single_open(file, acpi_ac_seq_show, PDE_DATA(inode)); | ||
207 | } | ||
208 | |||
209 | static int acpi_ac_add_fs(struct acpi_ac *ac) | ||
210 | { | ||
211 | struct proc_dir_entry *entry = NULL; | ||
212 | |||
213 | printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," | ||
214 | " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); | ||
215 | if (!acpi_device_dir(ac->device)) { | ||
216 | acpi_device_dir(ac->device) = | ||
217 | proc_mkdir(acpi_device_bid(ac->device), acpi_ac_dir); | ||
218 | if (!acpi_device_dir(ac->device)) | ||
219 | return -ENODEV; | ||
220 | } | ||
221 | |||
222 | /* 'state' [R] */ | ||
223 | entry = proc_create_data(ACPI_AC_FILE_STATE, | ||
224 | S_IRUGO, acpi_device_dir(ac->device), | ||
225 | &acpi_ac_fops, ac); | ||
226 | if (!entry) | ||
227 | return -ENODEV; | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int acpi_ac_remove_fs(struct acpi_ac *ac) | ||
232 | { | ||
233 | |||
234 | if (acpi_device_dir(ac->device)) { | ||
235 | remove_proc_entry(ACPI_AC_FILE_STATE, | ||
236 | acpi_device_dir(ac->device)); | ||
237 | remove_proc_entry(acpi_device_bid(ac->device), acpi_ac_dir); | ||
238 | acpi_device_dir(ac->device) = NULL; | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | #endif | ||
244 | |||
146 | /* -------------------------------------------------------------------------- | 245 | /* -------------------------------------------------------------------------- |
147 | Driver Model | 246 | Driver Model |
148 | -------------------------------------------------------------------------- */ | 247 | -------------------------------------------------------------------------- */ |
@@ -243,6 +342,11 @@ static int acpi_ac_add(struct acpi_device *device) | |||
243 | goto end; | 342 | goto end; |
244 | 343 | ||
245 | ac->charger.name = acpi_device_bid(device); | 344 | ac->charger.name = acpi_device_bid(device); |
345 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
346 | result = acpi_ac_add_fs(ac); | ||
347 | if (result) | ||
348 | goto end; | ||
349 | #endif | ||
246 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; | 350 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; |
247 | ac->charger.properties = ac_props; | 351 | ac->charger.properties = ac_props; |
248 | ac->charger.num_properties = ARRAY_SIZE(ac_props); | 352 | ac->charger.num_properties = ARRAY_SIZE(ac_props); |
@@ -258,8 +362,12 @@ static int acpi_ac_add(struct acpi_device *device) | |||
258 | ac->battery_nb.notifier_call = acpi_ac_battery_notify; | 362 | ac->battery_nb.notifier_call = acpi_ac_battery_notify; |
259 | register_acpi_notifier(&ac->battery_nb); | 363 | register_acpi_notifier(&ac->battery_nb); |
260 | end: | 364 | end: |
261 | if (result) | 365 | if (result) { |
366 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
367 | acpi_ac_remove_fs(ac); | ||
368 | #endif | ||
262 | kfree(ac); | 369 | kfree(ac); |
370 | } | ||
263 | 371 | ||
264 | dmi_check_system(ac_dmi_table); | 372 | dmi_check_system(ac_dmi_table); |
265 | return result; | 373 | return result; |
@@ -303,6 +411,10 @@ static int acpi_ac_remove(struct acpi_device *device) | |||
303 | power_supply_unregister(&ac->charger); | 411 | power_supply_unregister(&ac->charger); |
304 | unregister_acpi_notifier(&ac->battery_nb); | 412 | unregister_acpi_notifier(&ac->battery_nb); |
305 | 413 | ||
414 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
415 | acpi_ac_remove_fs(ac); | ||
416 | #endif | ||
417 | |||
306 | kfree(ac); | 418 | kfree(ac); |
307 | 419 | ||
308 | return 0; | 420 | return 0; |
@@ -315,9 +427,20 @@ static int __init acpi_ac_init(void) | |||
315 | if (acpi_disabled) | 427 | if (acpi_disabled) |
316 | return -ENODEV; | 428 | return -ENODEV; |
317 | 429 | ||
430 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
431 | acpi_ac_dir = acpi_lock_ac_dir(); | ||
432 | if (!acpi_ac_dir) | ||
433 | return -ENODEV; | ||
434 | #endif | ||
435 | |||
436 | |||
318 | result = acpi_bus_register_driver(&acpi_ac_driver); | 437 | result = acpi_bus_register_driver(&acpi_ac_driver); |
319 | if (result < 0) | 438 | if (result < 0) { |
439 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
440 | acpi_unlock_ac_dir(acpi_ac_dir); | ||
441 | #endif | ||
320 | return -ENODEV; | 442 | return -ENODEV; |
443 | } | ||
321 | 444 | ||
322 | return 0; | 445 | return 0; |
323 | } | 446 | } |
@@ -325,6 +448,9 @@ static int __init acpi_ac_init(void) | |||
325 | static void __exit acpi_ac_exit(void) | 448 | static void __exit acpi_ac_exit(void) |
326 | { | 449 | { |
327 | acpi_bus_unregister_driver(&acpi_ac_driver); | 450 | acpi_bus_unregister_driver(&acpi_ac_driver); |
451 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
452 | acpi_unlock_ac_dir(acpi_ac_dir); | ||
453 | #endif | ||
328 | } | 454 | } |
329 | module_init(acpi_ac_init); | 455 | module_init(acpi_ac_init); |
330 | module_exit(acpi_ac_exit); | 456 | module_exit(acpi_ac_exit); |
diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c index 185334114d71..b3842ffc19ba 100644 --- a/drivers/acpi/acpi_extlog.c +++ b/drivers/acpi/acpi_extlog.c | |||
@@ -12,10 +12,12 @@ | |||
12 | #include <linux/cper.h> | 12 | #include <linux/cper.h> |
13 | #include <linux/ratelimit.h> | 13 | #include <linux/ratelimit.h> |
14 | #include <linux/edac.h> | 14 | #include <linux/edac.h> |
15 | #include <linux/ras.h> | ||
15 | #include <asm/cpu.h> | 16 | #include <asm/cpu.h> |
16 | #include <asm/mce.h> | 17 | #include <asm/mce.h> |
17 | 18 | ||
18 | #include "apei/apei-internal.h" | 19 | #include "apei/apei-internal.h" |
20 | #include <ras/ras_event.h> | ||
19 | 21 | ||
20 | #define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */ | 22 | #define EXT_ELOG_ENTRY_MASK GENMASK_ULL(51, 0) /* elog entry address mask */ |
21 | 23 | ||
@@ -69,11 +71,11 @@ static u32 l1_percpu_entry; | |||
69 | #define ELOG_ENTRY_ADDR(phyaddr) \ | 71 | #define ELOG_ENTRY_ADDR(phyaddr) \ |
70 | (phyaddr - elog_base + (u8 *)elog_addr) | 72 | (phyaddr - elog_base + (u8 *)elog_addr) |
71 | 73 | ||
72 | static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) | 74 | static struct acpi_hest_generic_status *extlog_elog_entry_check(int cpu, int bank) |
73 | { | 75 | { |
74 | int idx; | 76 | int idx; |
75 | u64 data; | 77 | u64 data; |
76 | struct acpi_generic_status *estatus; | 78 | struct acpi_hest_generic_status *estatus; |
77 | 79 | ||
78 | WARN_ON(cpu < 0); | 80 | WARN_ON(cpu < 0); |
79 | idx = ELOG_IDX(cpu, bank); | 81 | idx = ELOG_IDX(cpu, bank); |
@@ -82,7 +84,7 @@ static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) | |||
82 | return NULL; | 84 | return NULL; |
83 | 85 | ||
84 | data &= EXT_ELOG_ENTRY_MASK; | 86 | data &= EXT_ELOG_ENTRY_MASK; |
85 | estatus = (struct acpi_generic_status *)ELOG_ENTRY_ADDR(data); | 87 | estatus = (struct acpi_hest_generic_status *)ELOG_ENTRY_ADDR(data); |
86 | 88 | ||
87 | /* if no valid data in elog entry, just return */ | 89 | /* if no valid data in elog entry, just return */ |
88 | if (estatus->block_status == 0) | 90 | if (estatus->block_status == 0) |
@@ -92,7 +94,7 @@ static struct acpi_generic_status *extlog_elog_entry_check(int cpu, int bank) | |||
92 | } | 94 | } |
93 | 95 | ||
94 | static void __print_extlog_rcd(const char *pfx, | 96 | static void __print_extlog_rcd(const char *pfx, |
95 | struct acpi_generic_status *estatus, int cpu) | 97 | struct acpi_hest_generic_status *estatus, int cpu) |
96 | { | 98 | { |
97 | static atomic_t seqno; | 99 | static atomic_t seqno; |
98 | unsigned int curr_seqno; | 100 | unsigned int curr_seqno; |
@@ -111,7 +113,7 @@ static void __print_extlog_rcd(const char *pfx, | |||
111 | } | 113 | } |
112 | 114 | ||
113 | static int print_extlog_rcd(const char *pfx, | 115 | static int print_extlog_rcd(const char *pfx, |
114 | struct acpi_generic_status *estatus, int cpu) | 116 | struct acpi_hest_generic_status *estatus, int cpu) |
115 | { | 117 | { |
116 | /* Not more than 2 messages every 5 seconds */ | 118 | /* Not more than 2 messages every 5 seconds */ |
117 | static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); | 119 | static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); |
@@ -137,8 +139,12 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, | |||
137 | struct mce *mce = (struct mce *)data; | 139 | struct mce *mce = (struct mce *)data; |
138 | int bank = mce->bank; | 140 | int bank = mce->bank; |
139 | int cpu = mce->extcpu; | 141 | int cpu = mce->extcpu; |
140 | struct acpi_generic_status *estatus; | 142 | struct acpi_hest_generic_status *estatus, *tmp; |
141 | int rc; | 143 | struct acpi_hest_generic_data *gdata; |
144 | const uuid_le *fru_id = &NULL_UUID_LE; | ||
145 | char *fru_text = ""; | ||
146 | uuid_le *sec_type; | ||
147 | static u32 err_seq; | ||
142 | 148 | ||
143 | estatus = extlog_elog_entry_check(cpu, bank); | 149 | estatus = extlog_elog_entry_check(cpu, bank); |
144 | if (estatus == NULL) | 150 | if (estatus == NULL) |
@@ -148,8 +154,29 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, | |||
148 | /* clear record status to enable BIOS to update it again */ | 154 | /* clear record status to enable BIOS to update it again */ |
149 | estatus->block_status = 0; | 155 | estatus->block_status = 0; |
150 | 156 | ||
151 | rc = print_extlog_rcd(NULL, (struct acpi_generic_status *)elog_buf, cpu); | 157 | tmp = (struct acpi_hest_generic_status *)elog_buf; |
158 | |||
159 | if (!ras_userspace_consumers()) { | ||
160 | print_extlog_rcd(NULL, tmp, cpu); | ||
161 | goto out; | ||
162 | } | ||
163 | |||
164 | /* log event via trace */ | ||
165 | err_seq++; | ||
166 | gdata = (struct acpi_hest_generic_data *)(tmp + 1); | ||
167 | if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID) | ||
168 | fru_id = (uuid_le *)gdata->fru_id; | ||
169 | if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT) | ||
170 | fru_text = gdata->fru_text; | ||
171 | sec_type = (uuid_le *)gdata->section_type; | ||
172 | if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) { | ||
173 | struct cper_sec_mem_err *mem = (void *)(gdata + 1); | ||
174 | if (gdata->error_data_length >= sizeof(*mem)) | ||
175 | trace_extlog_mem_event(mem, err_seq, fru_id, fru_text, | ||
176 | (u8)gdata->error_severity); | ||
177 | } | ||
152 | 178 | ||
179 | out: | ||
153 | return NOTIFY_STOP; | 180 | return NOTIFY_STOP; |
154 | } | 181 | } |
155 | 182 | ||
@@ -196,19 +223,16 @@ static int __init extlog_init(void) | |||
196 | u64 cap; | 223 | u64 cap; |
197 | int rc; | 224 | int rc; |
198 | 225 | ||
226 | rdmsrl(MSR_IA32_MCG_CAP, cap); | ||
227 | |||
228 | if (!(cap & MCG_ELOG_P) || !extlog_get_l1addr()) | ||
229 | return -ENODEV; | ||
230 | |||
199 | if (get_edac_report_status() == EDAC_REPORTING_FORCE) { | 231 | if (get_edac_report_status() == EDAC_REPORTING_FORCE) { |
200 | pr_warn("Not loading eMCA, error reporting force-enabled through EDAC.\n"); | 232 | pr_warn("Not loading eMCA, error reporting force-enabled through EDAC.\n"); |
201 | return -EPERM; | 233 | return -EPERM; |
202 | } | 234 | } |
203 | 235 | ||
204 | rc = -ENODEV; | ||
205 | rdmsrl(MSR_IA32_MCG_CAP, cap); | ||
206 | if (!(cap & MCG_ELOG_P)) | ||
207 | return rc; | ||
208 | |||
209 | if (!extlog_get_l1addr()) | ||
210 | return rc; | ||
211 | |||
212 | rc = -EINVAL; | 236 | rc = -EINVAL; |
213 | /* get L1 header to fetch necessary information */ | 237 | /* get L1 header to fetch necessary information */ |
214 | l1_hdr_size = sizeof(struct extlog_l1_head); | 238 | l1_hdr_size = sizeof(struct extlog_l1_head); |
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 9cb65b0e7597..ce06149088c5 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
@@ -113,6 +113,14 @@ static void lpss_i2c_setup(struct lpss_private_data *pdata) | |||
113 | writel(val, pdata->mmio_base + offset); | 113 | writel(val, pdata->mmio_base + offset); |
114 | } | 114 | } |
115 | 115 | ||
116 | static struct lpss_device_desc wpt_dev_desc = { | ||
117 | .clk_required = true, | ||
118 | .prv_offset = 0x800, | ||
119 | .ltr_required = true, | ||
120 | .clk_divider = true, | ||
121 | .clk_gate = true, | ||
122 | }; | ||
123 | |||
116 | static struct lpss_device_desc lpt_dev_desc = { | 124 | static struct lpss_device_desc lpt_dev_desc = { |
117 | .clk_required = true, | 125 | .clk_required = true, |
118 | .prv_offset = 0x800, | 126 | .prv_offset = 0x800, |
@@ -226,6 +234,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { | |||
226 | { "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) }, | 234 | { "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) }, |
227 | { "INT3437", }, | 235 | { "INT3437", }, |
228 | 236 | ||
237 | { "INT3438", LPSS_ADDR(wpt_dev_desc) }, | ||
238 | |||
229 | { } | 239 | { } |
230 | }; | 240 | }; |
231 | 241 | ||
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 6703c1fd993a..996fa1959eea 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c | |||
@@ -12,8 +12,11 @@ | |||
12 | 12 | ||
13 | #include <linux/acpi.h> | 13 | #include <linux/acpi.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/ctype.h> | ||
15 | 16 | ||
16 | static const struct acpi_device_id acpi_pnp_device_ids[] = { | 17 | static const struct acpi_device_id acpi_pnp_device_ids[] = { |
18 | /* soc_button_array */ | ||
19 | {"PNP0C40"}, | ||
17 | /* pata_isapnp */ | 20 | /* pata_isapnp */ |
18 | {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */ | 21 | {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */ |
19 | /* floppy */ | 22 | /* floppy */ |
@@ -318,11 +321,6 @@ static const struct acpi_device_id acpi_pnp_device_ids[] = { | |||
318 | {""}, | 321 | {""}, |
319 | }; | 322 | }; |
320 | 323 | ||
321 | static bool is_hex_digit(char c) | ||
322 | { | ||
323 | return (c >= 0 && c <= '9') || (c >= 'A' && c <= 'F'); | ||
324 | } | ||
325 | |||
326 | static bool matching_id(char *idstr, char *list_id) | 324 | static bool matching_id(char *idstr, char *list_id) |
327 | { | 325 | { |
328 | int i; | 326 | int i; |
@@ -333,7 +331,7 @@ static bool matching_id(char *idstr, char *list_id) | |||
333 | for (i = 3; i < 7; i++) { | 331 | for (i = 3; i < 7; i++) { |
334 | char c = toupper(idstr[i]); | 332 | char c = toupper(idstr[i]); |
335 | 333 | ||
336 | if (!is_hex_digit(c) | 334 | if (!isxdigit(c) |
337 | || (list_id[i] != 'X' && c != toupper(list_id[i]))) | 335 | || (list_id[i] != 'X' && c != toupper(list_id[i]))) |
338 | return false; | 336 | return false; |
339 | } | 337 | } |
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index 1c085742644f..1fdf5e07a1c7 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c | |||
@@ -268,7 +268,7 @@ static int acpi_processor_get_info(struct acpi_device *device) | |||
268 | pr->apic_id = apic_id; | 268 | pr->apic_id = apic_id; |
269 | 269 | ||
270 | cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); | 270 | cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); |
271 | if (!cpu0_initialized && !acpi_lapic) { | 271 | if (!cpu0_initialized && !acpi_has_cpu_in_madt()) { |
272 | cpu0_initialized = 1; | 272 | cpu0_initialized = 1; |
273 | /* Handle UP system running SMP kernel, with no LAPIC in MADT */ | 273 | /* Handle UP system running SMP kernel, with no LAPIC in MADT */ |
274 | if ((cpu_index == -1) && (num_online_cpus() == 1)) | 274 | if ((cpu_index == -1) && (num_online_cpus() == 1)) |
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 8bb43f06e11f..c1a963581dc0 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for ACPICA Core interpreter | 2 | # Makefile for ACPICA Core interpreter |
3 | # | 3 | # |
4 | 4 | ||
5 | ccflags-y := -Os | 5 | ccflags-y := -Os -DBUILDING_ACPICA |
6 | ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT | 6 | ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT |
7 | 7 | ||
8 | # use acpi.o to put all files here into acpi.o modparam namespace | 8 | # use acpi.o to put all files here into acpi.o modparam namespace |
@@ -157,6 +157,7 @@ acpi-y += \ | |||
157 | uterror.o \ | 157 | uterror.o \ |
158 | uteval.o \ | 158 | uteval.o \ |
159 | utglobal.o \ | 159 | utglobal.o \ |
160 | uthex.o \ | ||
160 | utids.o \ | 161 | utids.o \ |
161 | utinit.o \ | 162 | utinit.o \ |
162 | utlock.o \ | 163 | utlock.o \ |
@@ -175,5 +176,10 @@ acpi-y += \ | |||
175 | utxferror.o \ | 176 | utxferror.o \ |
176 | utxfmutex.o | 177 | utxfmutex.o |
177 | 178 | ||
178 | acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o | 179 | acpi-$(ACPI_FUTURE_USAGE) += \ |
180 | utcache.o \ | ||
181 | utfileio.o \ | ||
182 | utprint.o \ | ||
183 | uttrack.o \ | ||
184 | utuuid.o | ||
179 | 185 | ||
diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h index 8698ffba6f39..3d2c88289da9 100644 --- a/drivers/acpi/acpica/acapps.h +++ b/drivers/acpi/acpica/acapps.h | |||
@@ -79,10 +79,13 @@ | |||
79 | /* Macros for usage messages */ | 79 | /* Macros for usage messages */ |
80 | 80 | ||
81 | #define ACPI_USAGE_HEADER(usage) \ | 81 | #define ACPI_USAGE_HEADER(usage) \ |
82 | printf ("Usage: %s\nOptions:\n", usage); | 82 | acpi_os_printf ("Usage: %s\nOptions:\n", usage); |
83 | |||
84 | #define ACPI_USAGE_TEXT(description) \ | ||
85 | acpi_os_printf (description); | ||
83 | 86 | ||
84 | #define ACPI_OPTION(name, description) \ | 87 | #define ACPI_OPTION(name, description) \ |
85 | printf (" %-18s%s\n", name, description); | 88 | acpi_os_printf (" %-18s%s\n", name, description); |
86 | 89 | ||
87 | #define FILE_SUFFIX_DISASSEMBLY "dsl" | 90 | #define FILE_SUFFIX_DISASSEMBLY "dsl" |
88 | #define ACPI_TABLE_FILE_SUFFIX ".dat" | 91 | #define ACPI_TABLE_FILE_SUFFIX ".dat" |
@@ -102,7 +105,7 @@ extern char *acpi_gbl_optarg; | |||
102 | /* | 105 | /* |
103 | * cmfsize - Common get file size function | 106 | * cmfsize - Common get file size function |
104 | */ | 107 | */ |
105 | u32 cm_get_file_size(FILE * file); | 108 | u32 cm_get_file_size(ACPI_FILE file); |
106 | 109 | ||
107 | #ifndef ACPI_DUMP_APP | 110 | #ifndef ACPI_DUMP_APP |
108 | /* | 111 | /* |
diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 68a91eb0fa48..1d026ff1683f 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h | |||
@@ -233,9 +233,6 @@ acpi_status acpi_db_load_acpi_table(char *filename); | |||
233 | acpi_status | 233 | acpi_status |
234 | acpi_db_get_table_from_file(char *filename, struct acpi_table_header **table); | 234 | acpi_db_get_table_from_file(char *filename, struct acpi_table_header **table); |
235 | 235 | ||
236 | acpi_status | ||
237 | acpi_db_read_table_from_file(char *filename, struct acpi_table_header **table); | ||
238 | |||
239 | /* | 236 | /* |
240 | * dbhistry - debugger HISTORY command | 237 | * dbhistry - debugger HISTORY command |
241 | */ | 238 | */ |
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 115eedcade1e..ebf02cc10a43 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h | |||
@@ -297,7 +297,7 @@ ACPI_GLOBAL(u32, acpi_gbl_trace_dbg_layer); | |||
297 | * | 297 | * |
298 | ****************************************************************************/ | 298 | ****************************************************************************/ |
299 | 299 | ||
300 | ACPI_GLOBAL(u8, acpi_gbl_db_output_flags); | 300 | ACPI_INIT_GLOBAL(u8, acpi_gbl_db_output_flags, ACPI_DB_CONSOLE_OUTPUT); |
301 | 301 | ||
302 | #ifdef ACPI_DISASSEMBLER | 302 | #ifdef ACPI_DISASSEMBLER |
303 | 303 | ||
@@ -362,6 +362,12 @@ ACPI_GLOBAL(u32, acpi_gbl_num_objects); | |||
362 | #ifdef ACPI_APPLICATION | 362 | #ifdef ACPI_APPLICATION |
363 | 363 | ||
364 | ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL); | 364 | ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_debug_file, NULL); |
365 | ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_output_file, NULL); | ||
366 | |||
367 | /* Print buffer */ | ||
368 | |||
369 | ACPI_GLOBAL(acpi_spinlock, acpi_gbl_print_lock); /* For print buffer */ | ||
370 | ACPI_GLOBAL(char, acpi_gbl_print_buffer[1024]); | ||
365 | 371 | ||
366 | #endif /* ACPI_APPLICATION */ | 372 | #endif /* ACPI_APPLICATION */ |
367 | 373 | ||
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 91f801a2e689..1f9aba5fb81f 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
@@ -730,12 +730,13 @@ union acpi_parse_value { | |||
730 | #define ACPI_DASM_STRING 0x02 /* Buffer is a ASCII string */ | 730 | #define ACPI_DASM_STRING 0x02 /* Buffer is a ASCII string */ |
731 | #define ACPI_DASM_UNICODE 0x03 /* Buffer is a Unicode string */ | 731 | #define ACPI_DASM_UNICODE 0x03 /* Buffer is a Unicode string */ |
732 | #define ACPI_DASM_PLD_METHOD 0x04 /* Buffer is a _PLD method bit-packed buffer */ | 732 | #define ACPI_DASM_PLD_METHOD 0x04 /* Buffer is a _PLD method bit-packed buffer */ |
733 | #define ACPI_DASM_EISAID 0x05 /* Integer is an EISAID */ | 733 | #define ACPI_DASM_UUID 0x05 /* Buffer is a UUID/GUID */ |
734 | #define ACPI_DASM_MATCHOP 0x06 /* Parent opcode is a Match() operator */ | 734 | #define ACPI_DASM_EISAID 0x06 /* Integer is an EISAID */ |
735 | #define ACPI_DASM_LNOT_PREFIX 0x07 /* Start of a Lnot_equal (etc.) pair of opcodes */ | 735 | #define ACPI_DASM_MATCHOP 0x07 /* Parent opcode is a Match() operator */ |
736 | #define ACPI_DASM_LNOT_SUFFIX 0x08 /* End of a Lnot_equal (etc.) pair of opcodes */ | 736 | #define ACPI_DASM_LNOT_PREFIX 0x08 /* Start of a Lnot_equal (etc.) pair of opcodes */ |
737 | #define ACPI_DASM_HID_STRING 0x09 /* String is a _HID or _CID */ | 737 | #define ACPI_DASM_LNOT_SUFFIX 0x09 /* End of a Lnot_equal (etc.) pair of opcodes */ |
738 | #define ACPI_DASM_IGNORE 0x0A /* Not used at this time */ | 738 | #define ACPI_DASM_HID_STRING 0x0A /* String is a _HID or _CID */ |
739 | #define ACPI_DASM_IGNORE 0x0B /* Not used at this time */ | ||
739 | 740 | ||
740 | /* | 741 | /* |
741 | * Generic operation (for example: If, While, Store) | 742 | * Generic operation (for example: If, While, Store) |
@@ -1154,4 +1155,9 @@ struct ah_device_id { | |||
1154 | char *description; | 1155 | char *description; |
1155 | }; | 1156 | }; |
1156 | 1157 | ||
1158 | struct ah_uuid { | ||
1159 | char *description; | ||
1160 | char *string; | ||
1161 | }; | ||
1162 | |||
1157 | #endif /* __ACLOCAL_H__ */ | 1163 | #endif /* __ACLOCAL_H__ */ |
diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index bd08817cafd8..bd3908d26c4f 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h | |||
@@ -105,6 +105,11 @@ | |||
105 | * count = 0 (optional) | 105 | * count = 0 (optional) |
106 | * (Used for _DLM) | 106 | * (Used for _DLM) |
107 | * | 107 | * |
108 | * ACPI_PTYPE2_UUID_PAIR: Each subpackage is preceded by a UUID Buffer. The UUID | ||
109 | * defines the format of the package. Zero-length parent package is | ||
110 | * allowed. | ||
111 | * (Used for _DSD) | ||
112 | * | ||
108 | *****************************************************************************/ | 113 | *****************************************************************************/ |
109 | 114 | ||
110 | enum acpi_return_package_types { | 115 | enum acpi_return_package_types { |
@@ -117,7 +122,8 @@ enum acpi_return_package_types { | |||
117 | ACPI_PTYPE2_FIXED = 7, | 122 | ACPI_PTYPE2_FIXED = 7, |
118 | ACPI_PTYPE2_MIN = 8, | 123 | ACPI_PTYPE2_MIN = 8, |
119 | ACPI_PTYPE2_REV_FIXED = 9, | 124 | ACPI_PTYPE2_REV_FIXED = 9, |
120 | ACPI_PTYPE2_FIX_VAR = 10 | 125 | ACPI_PTYPE2_FIX_VAR = 10, |
126 | ACPI_PTYPE2_UUID_PAIR = 11 | ||
121 | }; | 127 | }; |
122 | 128 | ||
123 | /* Support macros for users of the predefined info table */ | 129 | /* Support macros for users of the predefined info table */ |
@@ -364,6 +370,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { | |||
364 | {{"_CBA", METHOD_0ARGS, | 370 | {{"_CBA", METHOD_0ARGS, |
365 | METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* See PCI firmware spec 3.0 */ | 371 | METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* See PCI firmware spec 3.0 */ |
366 | 372 | ||
373 | {{"_CCA", METHOD_0ARGS, | ||
374 | METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, /* ACPI 5.1 */ | ||
375 | |||
367 | {{"_CDM", METHOD_0ARGS, | 376 | {{"_CDM", METHOD_0ARGS, |
368 | METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, | 377 | METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, |
369 | 378 | ||
@@ -436,6 +445,11 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { | |||
436 | {{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER), | 445 | {{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER), |
437 | METHOD_NO_RETURN_VALUE}}, | 446 | METHOD_NO_RETURN_VALUE}}, |
438 | 447 | ||
448 | {{"_DSD", METHOD_0ARGS, | ||
449 | METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */ | ||
450 | PACKAGE_INFO(ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1, | ||
451 | ACPI_RTYPE_PACKAGE, 1, 0), | ||
452 | |||
439 | {{"_DSM", | 453 | {{"_DSM", |
440 | METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, | 454 | METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, |
441 | ACPI_TYPE_PACKAGE), | 455 | ACPI_TYPE_PACKAGE), |
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 1e256c5bda20..486d342e74b6 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h | |||
@@ -95,7 +95,6 @@ extern const char *acpi_gbl_pt_decode[]; | |||
95 | #ifdef ACPI_ASL_COMPILER | 95 | #ifdef ACPI_ASL_COMPILER |
96 | 96 | ||
97 | #include <stdio.h> | 97 | #include <stdio.h> |
98 | extern FILE *acpi_gbl_output_file; | ||
99 | 98 | ||
100 | #define ACPI_MSG_REDIRECT_BEGIN \ | 99 | #define ACPI_MSG_REDIRECT_BEGIN \ |
101 | FILE *output_file = acpi_gbl_output_file; \ | 100 | FILE *output_file = acpi_gbl_output_file; \ |
@@ -195,6 +194,8 @@ char *acpi_ut_get_event_name(u32 event_id); | |||
195 | 194 | ||
196 | char acpi_ut_hex_to_ascii_char(u64 integer, u32 position); | 195 | char acpi_ut_hex_to_ascii_char(u64 integer, u32 position); |
197 | 196 | ||
197 | u8 acpi_ut_ascii_char_to_hex(int hex_char); | ||
198 | |||
198 | u8 acpi_ut_valid_object_type(acpi_object_type type); | 199 | u8 acpi_ut_valid_object_type(acpi_object_type type); |
199 | 200 | ||
200 | /* | 201 | /* |
@@ -211,6 +212,8 @@ void acpi_ut_subsystem_shutdown(void); | |||
211 | 212 | ||
212 | acpi_size acpi_ut_strlen(const char *string); | 213 | acpi_size acpi_ut_strlen(const char *string); |
213 | 214 | ||
215 | char *acpi_ut_strchr(const char *string, int ch); | ||
216 | |||
214 | char *acpi_ut_strcpy(char *dst_string, const char *src_string); | 217 | char *acpi_ut_strcpy(char *dst_string, const char *src_string); |
215 | 218 | ||
216 | char *acpi_ut_strncpy(char *dst_string, | 219 | char *acpi_ut_strncpy(char *dst_string, |
@@ -257,7 +260,7 @@ extern const u8 _acpi_ctype[]; | |||
257 | #define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) | 260 | #define ACPI_IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD)) |
258 | #define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) | 261 | #define ACPI_IS_UPPER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP)) |
259 | #define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) | 262 | #define ACPI_IS_LOWER(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO)) |
260 | #define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU)) | 263 | #define ACPI_IS_PRINT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_XS | _ACPI_PU)) |
261 | #define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) | 264 | #define ACPI_IS_ALPHA(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) |
262 | 265 | ||
263 | #endif /* !ACPI_USE_SYSTEM_CLIBRARY */ | 266 | #endif /* !ACPI_USE_SYSTEM_CLIBRARY */ |
@@ -352,6 +355,13 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id); | |||
352 | 355 | ||
353 | void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset); | 356 | void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset); |
354 | 357 | ||
358 | #ifdef ACPI_APPLICATION | ||
359 | void | ||
360 | acpi_ut_dump_buffer_to_file(ACPI_FILE file, | ||
361 | u8 *buffer, | ||
362 | u32 count, u32 display, u32 base_offset); | ||
363 | #endif | ||
364 | |||
355 | void acpi_ut_report_error(char *module_name, u32 line_number); | 365 | void acpi_ut_report_error(char *module_name, u32 line_number); |
356 | 366 | ||
357 | void acpi_ut_report_info(char *module_name, u32 line_number); | 367 | void acpi_ut_report_info(char *module_name, u32 line_number); |
@@ -394,6 +404,14 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, | |||
394 | u8 method_count, u8 *out_values); | 404 | u8 method_count, u8 *out_values); |
395 | 405 | ||
396 | /* | 406 | /* |
407 | * utfileio - file operations | ||
408 | */ | ||
409 | #ifdef ACPI_APPLICATION | ||
410 | acpi_status | ||
411 | acpi_ut_read_table_from_file(char *filename, struct acpi_table_header **table); | ||
412 | #endif | ||
413 | |||
414 | /* | ||
397 | * utids - device ID support | 415 | * utids - device ID support |
398 | */ | 416 | */ |
399 | acpi_status | 417 | acpi_status |
@@ -743,4 +761,30 @@ const struct ah_predefined_name *acpi_ah_match_predefined_name(char *nameseg); | |||
743 | 761 | ||
744 | const struct ah_device_id *acpi_ah_match_hardware_id(char *hid); | 762 | const struct ah_device_id *acpi_ah_match_hardware_id(char *hid); |
745 | 763 | ||
764 | const char *acpi_ah_match_uuid(u8 *data); | ||
765 | |||
766 | /* | ||
767 | * utprint - printf/vprintf output functions | ||
768 | */ | ||
769 | const char *acpi_ut_scan_number(const char *string, u64 *number_ptr); | ||
770 | |||
771 | const char *acpi_ut_print_number(char *string, u64 number); | ||
772 | |||
773 | int | ||
774 | acpi_ut_vsnprintf(char *string, | ||
775 | acpi_size size, const char *format, va_list args); | ||
776 | |||
777 | int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...); | ||
778 | |||
779 | #ifdef ACPI_APPLICATION | ||
780 | int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args); | ||
781 | |||
782 | int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...); | ||
783 | #endif | ||
784 | |||
785 | /* | ||
786 | * utuuid -- UUID support functions | ||
787 | */ | ||
788 | void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer); | ||
789 | |||
746 | #endif /* _ACUTILS_H */ | 790 | #endif /* _ACUTILS_H */ |
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 48f70013b488..e4ba4dec86af 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
@@ -698,21 +698,6 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, | |||
698 | } | 698 | } |
699 | 699 | ||
700 | /* | 700 | /* |
701 | * If edge-triggered, clear the GPE status bit now. Note that | ||
702 | * level-triggered events are cleared after the GPE is serviced. | ||
703 | */ | ||
704 | if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == | ||
705 | ACPI_GPE_EDGE_TRIGGERED) { | ||
706 | status = acpi_hw_clear_gpe(gpe_event_info); | ||
707 | if (ACPI_FAILURE(status)) { | ||
708 | ACPI_EXCEPTION((AE_INFO, status, | ||
709 | "Unable to clear GPE %02X", | ||
710 | gpe_number)); | ||
711 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
712 | } | ||
713 | } | ||
714 | |||
715 | /* | ||
716 | * Always disable the GPE so that it does not keep firing before | 701 | * Always disable the GPE so that it does not keep firing before |
717 | * any asynchronous activity completes (either from the execution | 702 | * any asynchronous activity completes (either from the execution |
718 | * of a GPE method or an asynchronous GPE handler.) | 703 | * of a GPE method or an asynchronous GPE handler.) |
@@ -729,6 +714,23 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device, | |||
729 | } | 714 | } |
730 | 715 | ||
731 | /* | 716 | /* |
717 | * If edge-triggered, clear the GPE status bit now. Note that | ||
718 | * level-triggered events are cleared after the GPE is serviced. | ||
719 | */ | ||
720 | if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == | ||
721 | ACPI_GPE_EDGE_TRIGGERED) { | ||
722 | status = acpi_hw_clear_gpe(gpe_event_info); | ||
723 | if (ACPI_FAILURE(status)) { | ||
724 | ACPI_EXCEPTION((AE_INFO, status, | ||
725 | "Unable to clear GPE %02X", | ||
726 | gpe_number)); | ||
727 | (void)acpi_hw_low_set_gpe(gpe_event_info, | ||
728 | ACPI_GPE_CONDITIONAL_ENABLE); | ||
729 | return_UINT32(ACPI_INTERRUPT_NOT_HANDLED); | ||
730 | } | ||
731 | } | ||
732 | |||
733 | /* | ||
732 | * Dispatch the GPE to either an installed handler or the control | 734 | * Dispatch the GPE to either an installed handler or the control |
733 | * method associated with this GPE (_Lxx or _Exx). If a handler | 735 | * method associated with this GPE (_Lxx or _Exx). If a handler |
734 | * exists, we invoke it and do not attempt to run the method. | 736 | * exists, we invoke it and do not attempt to run the method. |
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index cb534faf5369..0cf159cc6e6d 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c | |||
@@ -126,11 +126,19 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) | |||
126 | 126 | ||
127 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 127 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
128 | 128 | ||
129 | /* Ensure that we have a valid GPE number */ | 129 | /* |
130 | 130 | * Ensure that we have a valid GPE number and that there is some way | |
131 | * of handling the GPE (handler or a GPE method). In other words, we | ||
132 | * won't allow a valid GPE to be enabled if there is no way to handle it. | ||
133 | */ | ||
131 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 134 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
132 | if (gpe_event_info) { | 135 | if (gpe_event_info) { |
133 | status = acpi_ev_add_gpe_reference(gpe_event_info); | 136 | if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != |
137 | ACPI_GPE_DISPATCH_NONE) { | ||
138 | status = acpi_ev_add_gpe_reference(gpe_event_info); | ||
139 | } else { | ||
140 | status = AE_NO_HANDLER; | ||
141 | } | ||
134 | } | 142 | } |
135 | 143 | ||
136 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 144 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
@@ -179,6 +187,53 @@ ACPI_EXPORT_SYMBOL(acpi_disable_gpe) | |||
179 | 187 | ||
180 | /******************************************************************************* | 188 | /******************************************************************************* |
181 | * | 189 | * |
190 | * FUNCTION: acpi_mark_gpe_for_wake | ||
191 | * | ||
192 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
193 | * gpe_number - GPE level within the GPE block | ||
194 | * | ||
195 | * RETURN: Status | ||
196 | * | ||
197 | * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply | ||
198 | * sets the ACPI_GPE_CAN_WAKE flag. | ||
199 | * | ||
200 | * Some potential callers of acpi_setup_gpe_for_wake may know in advance that | ||
201 | * there won't be any notify handlers installed for device wake notifications | ||
202 | * from the given GPE (one example is a button GPE in Linux). For these cases, | ||
203 | * acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake. | ||
204 | * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to | ||
205 | * setup implicit wake notification for it (since there's no handler method). | ||
206 | * | ||
207 | ******************************************************************************/ | ||
208 | acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number) | ||
209 | { | ||
210 | struct acpi_gpe_event_info *gpe_event_info; | ||
211 | acpi_status status = AE_BAD_PARAMETER; | ||
212 | acpi_cpu_flags flags; | ||
213 | |||
214 | ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake); | ||
215 | |||
216 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
217 | |||
218 | /* Ensure that we have a valid GPE number */ | ||
219 | |||
220 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
221 | if (gpe_event_info) { | ||
222 | |||
223 | /* Mark the GPE as a possible wake event */ | ||
224 | |||
225 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | ||
226 | status = AE_OK; | ||
227 | } | ||
228 | |||
229 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
230 | return_ACPI_STATUS(status); | ||
231 | } | ||
232 | |||
233 | ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake) | ||
234 | |||
235 | /******************************************************************************* | ||
236 | * | ||
182 | * FUNCTION: acpi_setup_gpe_for_wake | 237 | * FUNCTION: acpi_setup_gpe_for_wake |
183 | * | 238 | * |
184 | * PARAMETERS: wake_device - Device associated with the GPE (via _PRW) | 239 | * PARAMETERS: wake_device - Device associated with the GPE (via _PRW) |
diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index 4cfc3d3b5c97..6fbfad47518c 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c | |||
@@ -75,6 +75,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
75 | u32 level, u32 index) | 75 | u32 level, u32 index) |
76 | { | 76 | { |
77 | u32 i; | 77 | u32 i; |
78 | u32 timer; | ||
78 | 79 | ||
79 | ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); | 80 | ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); |
80 | 81 | ||
@@ -86,11 +87,19 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
86 | } | 87 | } |
87 | 88 | ||
88 | /* | 89 | /* |
90 | * We will emit the current timer value (in microseconds) with each | ||
91 | * debug output. Only need the lower 26 bits. This allows for 67 | ||
92 | * million microseconds or 67 seconds before rollover. | ||
93 | */ | ||
94 | timer = ((u32)acpi_os_get_timer() / 10); /* (100 nanoseconds to microseconds) */ | ||
95 | timer &= 0x03FFFFFF; | ||
96 | |||
97 | /* | ||
89 | * Print line header as long as we are not in the middle of an | 98 | * Print line header as long as we are not in the middle of an |
90 | * object display | 99 | * object display |
91 | */ | 100 | */ |
92 | if (!((level > 0) && index == 0)) { | 101 | if (!((level > 0) && index == 0)) { |
93 | acpi_os_printf("[ACPI Debug] %*s", level, " "); | 102 | acpi_os_printf("[ACPI Debug %.8u] %*s", timer, level, " "); |
94 | } | 103 | } |
95 | 104 | ||
96 | /* Display the index for package output only */ | 105 | /* Display the index for package output only */ |
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 925202acc3e4..0f23c3f2678e 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c | |||
@@ -494,7 +494,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, | |||
494 | } | 494 | } |
495 | } | 495 | } |
496 | 496 | ||
497 | acpi_os_printf("\n", next); | 497 | acpi_os_printf("\n"); |
498 | break; | 498 | break; |
499 | 499 | ||
500 | case ACPI_EXD_HDLR_LIST: | 500 | case ACPI_EXD_HDLR_LIST: |
@@ -528,7 +528,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, | |||
528 | } | 528 | } |
529 | } | 529 | } |
530 | 530 | ||
531 | acpi_os_printf("\n", next); | 531 | acpi_os_printf("\n"); |
532 | break; | 532 | break; |
533 | 533 | ||
534 | case ACPI_EXD_RGN_LIST: | 534 | case ACPI_EXD_RGN_LIST: |
@@ -562,7 +562,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, | |||
562 | } | 562 | } |
563 | } | 563 | } |
564 | 564 | ||
565 | acpi_os_printf("\n", next); | 565 | acpi_os_printf("\n"); |
566 | break; | 566 | break; |
567 | 567 | ||
568 | case ACPI_EXD_NODE: | 568 | case ACPI_EXD_NODE: |
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 12878e1982f7..6907ce0c704c 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c | |||
@@ -56,7 +56,7 @@ acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length); | |||
56 | 56 | ||
57 | /******************************************************************************* | 57 | /******************************************************************************* |
58 | * | 58 | * |
59 | * FUNCTION: acpi_get_serial_access_bytes | 59 | * FUNCTION: acpi_ex_get_serial_access_length |
60 | * | 60 | * |
61 | * PARAMETERS: accessor_type - The type of the protocol indicated by region | 61 | * PARAMETERS: accessor_type - The type of the protocol indicated by region |
62 | * field access attributes | 62 | * field access attributes |
@@ -103,7 +103,7 @@ acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length) | |||
103 | case AML_FIELD_ATTRIB_BLOCK_CALL: | 103 | case AML_FIELD_ATTRIB_BLOCK_CALL: |
104 | default: | 104 | default: |
105 | 105 | ||
106 | length = ACPI_GSBUS_BUFFER_SIZE; | 106 | length = ACPI_GSBUS_BUFFER_SIZE - 2; |
107 | break; | 107 | break; |
108 | } | 108 | } |
109 | 109 | ||
@@ -186,12 +186,11 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, | |||
186 | access_length); | 186 | access_length); |
187 | 187 | ||
188 | /* | 188 | /* |
189 | * Add additional 2 bytes for modeled generic_serial_bus data buffer: | 189 | * Add additional 2 bytes for the generic_serial_bus data buffer: |
190 | * typedef struct { | 190 | * |
191 | * BYTEStatus; // Byte 0 of the data buffer | 191 | * Status; (Byte 0 of the data buffer) |
192 | * BYTELength; // Byte 1 of the data buffer | 192 | * Length; (Byte 1 of the data buffer) |
193 | * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, | 193 | * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer) |
194 | * } | ||
195 | */ | 194 | */ |
196 | length += 2; | 195 | length += 2; |
197 | function = ACPI_READ | (accessor_type << 16); | 196 | function = ACPI_READ | (accessor_type << 16); |
@@ -368,12 +367,11 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
368 | access_length); | 367 | access_length); |
369 | 368 | ||
370 | /* | 369 | /* |
371 | * Add additional 2 bytes for modeled generic_serial_bus data buffer: | 370 | * Add additional 2 bytes for the generic_serial_bus data buffer: |
372 | * typedef struct { | 371 | * |
373 | * BYTEStatus; // Byte 0 of the data buffer | 372 | * Status; (Byte 0 of the data buffer) |
374 | * BYTELength; // Byte 1 of the data buffer | 373 | * Length; (Byte 1 of the data buffer) |
375 | * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, | 374 | * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer) |
376 | * } | ||
377 | */ | 375 | */ |
378 | length += 2; | 376 | length += 2; |
379 | function = ACPI_WRITE | (accessor_type << 16); | 377 | function = ACPI_WRITE | (accessor_type << 16); |
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index e0fd9b4978cd..a4c34d2c556b 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c | |||
@@ -278,8 +278,9 @@ acpi_status acpi_hw_clear_acpi_status(void) | |||
278 | 278 | ||
279 | acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); | 279 | acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); |
280 | 280 | ||
281 | if (ACPI_FAILURE(status)) | 281 | if (ACPI_FAILURE(status)) { |
282 | goto exit; | 282 | goto exit; |
283 | } | ||
283 | 284 | ||
284 | /* Clear the GPE Bits in all GPE registers in all GPE blocks */ | 285 | /* Clear the GPE Bits in all GPE registers in all GPE blocks */ |
285 | 286 | ||
diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index fe54a8c73b8c..a42ee9d6970d 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c | |||
@@ -237,6 +237,16 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) | |||
237 | (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) { | 237 | (node->object->common.type != ACPI_TYPE_LOCAL_DATA)) { |
238 | node->object = node->object->common.next_object; | 238 | node->object = node->object->common.next_object; |
239 | } | 239 | } |
240 | |||
241 | /* | ||
242 | * Detach the object from any data objects (which are still held by | ||
243 | * the namespace node) | ||
244 | */ | ||
245 | if (obj_desc->common.next_object && | ||
246 | ((obj_desc->common.next_object)->common.type == | ||
247 | ACPI_TYPE_LOCAL_DATA)) { | ||
248 | obj_desc->common.next_object = NULL; | ||
249 | } | ||
240 | } | 250 | } |
241 | 251 | ||
242 | /* Reset the node type to untyped */ | 252 | /* Reset the node type to untyped */ |
diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c index 3c1699740653..038ea887f562 100644 --- a/drivers/acpi/acpica/utbuffer.c +++ b/drivers/acpi/acpica/utbuffer.c | |||
@@ -199,3 +199,131 @@ acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id) | |||
199 | 199 | ||
200 | acpi_ut_dump_buffer(buffer, count, display, 0); | 200 | acpi_ut_dump_buffer(buffer, count, display, 0); |
201 | } | 201 | } |
202 | |||
203 | #ifdef ACPI_APPLICATION | ||
204 | /******************************************************************************* | ||
205 | * | ||
206 | * FUNCTION: acpi_ut_dump_buffer_to_file | ||
207 | * | ||
208 | * PARAMETERS: file - File descriptor | ||
209 | * buffer - Buffer to dump | ||
210 | * count - Amount to dump, in bytes | ||
211 | * display - BYTE, WORD, DWORD, or QWORD display: | ||
212 | * DB_BYTE_DISPLAY | ||
213 | * DB_WORD_DISPLAY | ||
214 | * DB_DWORD_DISPLAY | ||
215 | * DB_QWORD_DISPLAY | ||
216 | * base_offset - Beginning buffer offset (display only) | ||
217 | * | ||
218 | * RETURN: None | ||
219 | * | ||
220 | * DESCRIPTION: Generic dump buffer in both hex and ascii to a file. | ||
221 | * | ||
222 | ******************************************************************************/ | ||
223 | |||
224 | void | ||
225 | acpi_ut_dump_buffer_to_file(ACPI_FILE file, | ||
226 | u8 *buffer, u32 count, u32 display, u32 base_offset) | ||
227 | { | ||
228 | u32 i = 0; | ||
229 | u32 j; | ||
230 | u32 temp32; | ||
231 | u8 buf_char; | ||
232 | |||
233 | if (!buffer) { | ||
234 | acpi_ut_file_printf(file, | ||
235 | "Null Buffer Pointer in DumpBuffer!\n"); | ||
236 | return; | ||
237 | } | ||
238 | |||
239 | if ((count < 4) || (count & 0x01)) { | ||
240 | display = DB_BYTE_DISPLAY; | ||
241 | } | ||
242 | |||
243 | /* Nasty little dump buffer routine! */ | ||
244 | |||
245 | while (i < count) { | ||
246 | |||
247 | /* Print current offset */ | ||
248 | |||
249 | acpi_ut_file_printf(file, "%6.4X: ", (base_offset + i)); | ||
250 | |||
251 | /* Print 16 hex chars */ | ||
252 | |||
253 | for (j = 0; j < 16;) { | ||
254 | if (i + j >= count) { | ||
255 | |||
256 | /* Dump fill spaces */ | ||
257 | |||
258 | acpi_ut_file_printf(file, "%*s", | ||
259 | ((display * 2) + 1), " "); | ||
260 | j += display; | ||
261 | continue; | ||
262 | } | ||
263 | |||
264 | switch (display) { | ||
265 | case DB_BYTE_DISPLAY: | ||
266 | default: /* Default is BYTE display */ | ||
267 | |||
268 | acpi_ut_file_printf(file, "%02X ", | ||
269 | buffer[(acpi_size) i + j]); | ||
270 | break; | ||
271 | |||
272 | case DB_WORD_DISPLAY: | ||
273 | |||
274 | ACPI_MOVE_16_TO_32(&temp32, | ||
275 | &buffer[(acpi_size) i + j]); | ||
276 | acpi_ut_file_printf(file, "%04X ", temp32); | ||
277 | break; | ||
278 | |||
279 | case DB_DWORD_DISPLAY: | ||
280 | |||
281 | ACPI_MOVE_32_TO_32(&temp32, | ||
282 | &buffer[(acpi_size) i + j]); | ||
283 | acpi_ut_file_printf(file, "%08X ", temp32); | ||
284 | break; | ||
285 | |||
286 | case DB_QWORD_DISPLAY: | ||
287 | |||
288 | ACPI_MOVE_32_TO_32(&temp32, | ||
289 | &buffer[(acpi_size) i + j]); | ||
290 | acpi_ut_file_printf(file, "%08X", temp32); | ||
291 | |||
292 | ACPI_MOVE_32_TO_32(&temp32, | ||
293 | &buffer[(acpi_size) i + j + | ||
294 | 4]); | ||
295 | acpi_ut_file_printf(file, "%08X ", temp32); | ||
296 | break; | ||
297 | } | ||
298 | |||
299 | j += display; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * Print the ASCII equivalent characters but watch out for the bad | ||
304 | * unprintable ones (printable chars are 0x20 through 0x7E) | ||
305 | */ | ||
306 | acpi_ut_file_printf(file, " "); | ||
307 | for (j = 0; j < 16; j++) { | ||
308 | if (i + j >= count) { | ||
309 | acpi_ut_file_printf(file, "\n"); | ||
310 | return; | ||
311 | } | ||
312 | |||
313 | buf_char = buffer[(acpi_size) i + j]; | ||
314 | if (ACPI_IS_PRINT(buf_char)) { | ||
315 | acpi_ut_file_printf(file, "%c", buf_char); | ||
316 | } else { | ||
317 | acpi_ut_file_printf(file, "."); | ||
318 | } | ||
319 | } | ||
320 | |||
321 | /* Done with that line. */ | ||
322 | |||
323 | acpi_ut_file_printf(file, "\n"); | ||
324 | i += 16; | ||
325 | } | ||
326 | |||
327 | return; | ||
328 | } | ||
329 | #endif | ||
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 270c16464dd9..ff601c0f7c7a 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c | |||
@@ -1001,5 +1001,11 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, | |||
1001 | status = acpi_ut_copy_simple_object(source_desc, *dest_desc); | 1001 | status = acpi_ut_copy_simple_object(source_desc, *dest_desc); |
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | /* Delete the allocated object if copy failed */ | ||
1005 | |||
1006 | if (ACPI_FAILURE(status)) { | ||
1007 | acpi_ut_remove_reference(*dest_desc); | ||
1008 | } | ||
1009 | |||
1004 | return_ACPI_STATUS(status); | 1010 | return_ACPI_STATUS(status); |
1005 | } | 1011 | } |
diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 21a20ac5b1e1..e516254c63b2 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c | |||
@@ -561,3 +561,29 @@ acpi_ut_ptr_exit(u32 line_number, | |||
561 | } | 561 | } |
562 | 562 | ||
563 | #endif | 563 | #endif |
564 | |||
565 | #ifdef ACPI_APPLICATION | ||
566 | /******************************************************************************* | ||
567 | * | ||
568 | * FUNCTION: acpi_log_error | ||
569 | * | ||
570 | * PARAMETERS: format - Printf format field | ||
571 | * ... - Optional printf arguments | ||
572 | * | ||
573 | * RETURN: None | ||
574 | * | ||
575 | * DESCRIPTION: Print error message to the console, used by applications. | ||
576 | * | ||
577 | ******************************************************************************/ | ||
578 | |||
579 | void ACPI_INTERNAL_VAR_XFACE acpi_log_error(const char *format, ...) | ||
580 | { | ||
581 | va_list args; | ||
582 | |||
583 | va_start(args, format); | ||
584 | (void)acpi_ut_file_vprintf(ACPI_FILE_ERR, format, args); | ||
585 | va_end(args); | ||
586 | } | ||
587 | |||
588 | ACPI_EXPORT_SYMBOL(acpi_log_error) | ||
589 | #endif | ||
diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index 90ec37c473c6..40e923e675fc 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c | |||
@@ -88,33 +88,6 @@ const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES] = { | |||
88 | 88 | ||
89 | /******************************************************************************* | 89 | /******************************************************************************* |
90 | * | 90 | * |
91 | * FUNCTION: acpi_ut_hex_to_ascii_char | ||
92 | * | ||
93 | * PARAMETERS: integer - Contains the hex digit | ||
94 | * position - bit position of the digit within the | ||
95 | * integer (multiple of 4) | ||
96 | * | ||
97 | * RETURN: The converted Ascii character | ||
98 | * | ||
99 | * DESCRIPTION: Convert a hex digit to an Ascii character | ||
100 | * | ||
101 | ******************************************************************************/ | ||
102 | |||
103 | /* Hex to ASCII conversion table */ | ||
104 | |||
105 | static const char acpi_gbl_hex_to_ascii[] = { | ||
106 | '0', '1', '2', '3', '4', '5', '6', '7', | ||
107 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | ||
108 | }; | ||
109 | |||
110 | char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) | ||
111 | { | ||
112 | |||
113 | return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); | ||
114 | } | ||
115 | |||
116 | /******************************************************************************* | ||
117 | * | ||
118 | * FUNCTION: acpi_ut_get_region_name | 91 | * FUNCTION: acpi_ut_get_region_name |
119 | * | 92 | * |
120 | * PARAMETERS: Space ID - ID for the region | 93 | * PARAMETERS: Space ID - ID for the region |
@@ -475,7 +448,8 @@ static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = { | |||
475 | /* 09 */ "Device PLD Check", | 448 | /* 09 */ "Device PLD Check", |
476 | /* 0A */ "Reserved", | 449 | /* 0A */ "Reserved", |
477 | /* 0B */ "System Locality Update", | 450 | /* 0B */ "System Locality Update", |
478 | /* 0C */ "Shutdown Request" | 451 | /* 0C */ "Shutdown Request", |
452 | /* 0D */ "System Resource Affinity Update" | ||
479 | }; | 453 | }; |
480 | 454 | ||
481 | static const char *acpi_gbl_device_notify[4] = { | 455 | static const char *acpi_gbl_device_notify[4] = { |
@@ -502,7 +476,7 @@ static const char *acpi_gbl_thermal_notify[4] = { | |||
502 | const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type) | 476 | const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type) |
503 | { | 477 | { |
504 | 478 | ||
505 | /* 00 - 0C are common to all object types */ | 479 | /* 00 - 0D are common to all object types */ |
506 | 480 | ||
507 | if (notify_value <= ACPI_NOTIFY_MAX) { | 481 | if (notify_value <= ACPI_NOTIFY_MAX) { |
508 | return (acpi_gbl_generic_notify[notify_value]); | 482 | return (acpi_gbl_generic_notify[notify_value]); |
diff --git a/drivers/acpi/acpica/utfileio.c b/drivers/acpi/acpica/utfileio.c new file mode 100644 index 000000000000..4e263a8cc6f0 --- /dev/null +++ b/drivers/acpi/acpica/utfileio.c | |||
@@ -0,0 +1,331 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Module Name: utfileio - simple file I/O routines | ||
4 | * | ||
5 | ******************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | #include "actables.h" | ||
47 | #include "acapps.h" | ||
48 | |||
49 | #ifdef ACPI_ASL_COMPILER | ||
50 | #include "aslcompiler.h" | ||
51 | #endif | ||
52 | |||
53 | #define _COMPONENT ACPI_CA_DEBUGGER | ||
54 | ACPI_MODULE_NAME("utfileio") | ||
55 | |||
56 | #ifdef ACPI_APPLICATION | ||
57 | /* Local prototypes */ | ||
58 | static acpi_status | ||
59 | acpi_ut_check_text_mode_corruption(u8 *table, | ||
60 | u32 table_length, u32 file_length); | ||
61 | |||
62 | static acpi_status | ||
63 | acpi_ut_read_table(FILE * fp, | ||
64 | struct acpi_table_header **table, u32 *table_length); | ||
65 | |||
66 | /******************************************************************************* | ||
67 | * | ||
68 | * FUNCTION: acpi_ut_check_text_mode_corruption | ||
69 | * | ||
70 | * PARAMETERS: table - Table buffer | ||
71 | * table_length - Length of table from the table header | ||
72 | * file_length - Length of the file that contains the table | ||
73 | * | ||
74 | * RETURN: Status | ||
75 | * | ||
76 | * DESCRIPTION: Check table for text mode file corruption where all linefeed | ||
77 | * characters (LF) have been replaced by carriage return linefeed | ||
78 | * pairs (CR/LF). | ||
79 | * | ||
80 | ******************************************************************************/ | ||
81 | |||
82 | static acpi_status | ||
83 | acpi_ut_check_text_mode_corruption(u8 *table, u32 table_length, u32 file_length) | ||
84 | { | ||
85 | u32 i; | ||
86 | u32 pairs = 0; | ||
87 | |||
88 | if (table_length != file_length) { | ||
89 | ACPI_WARNING((AE_INFO, | ||
90 | "File length (0x%X) is not the same as the table length (0x%X)", | ||
91 | file_length, table_length)); | ||
92 | } | ||
93 | |||
94 | /* Scan entire table to determine if each LF has been prefixed with a CR */ | ||
95 | |||
96 | for (i = 1; i < file_length; i++) { | ||
97 | if (table[i] == 0x0A) { | ||
98 | if (table[i - 1] != 0x0D) { | ||
99 | |||
100 | /* The LF does not have a preceding CR, table not corrupted */ | ||
101 | |||
102 | return (AE_OK); | ||
103 | } else { | ||
104 | /* Found a CR/LF pair */ | ||
105 | |||
106 | pairs++; | ||
107 | } | ||
108 | i++; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (!pairs) { | ||
113 | return (AE_OK); | ||
114 | } | ||
115 | |||
116 | /* | ||
117 | * Entire table scanned, each CR is part of a CR/LF pair -- | ||
118 | * meaning that the table was treated as a text file somewhere. | ||
119 | * | ||
120 | * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the | ||
121 | * original table are left untouched by the text conversion process -- | ||
122 | * meaning that we cannot simply replace CR/LF pairs with LFs. | ||
123 | */ | ||
124 | acpi_os_printf("Table has been corrupted by text mode conversion\n"); | ||
125 | acpi_os_printf("All LFs (%u) were changed to CR/LF pairs\n", pairs); | ||
126 | acpi_os_printf("Table cannot be repaired!\n"); | ||
127 | return (AE_BAD_VALUE); | ||
128 | } | ||
129 | |||
130 | /******************************************************************************* | ||
131 | * | ||
132 | * FUNCTION: acpi_ut_read_table | ||
133 | * | ||
134 | * PARAMETERS: fp - File that contains table | ||
135 | * table - Return value, buffer with table | ||
136 | * table_length - Return value, length of table | ||
137 | * | ||
138 | * RETURN: Status | ||
139 | * | ||
140 | * DESCRIPTION: Load the DSDT from the file pointer | ||
141 | * | ||
142 | ******************************************************************************/ | ||
143 | |||
144 | static acpi_status | ||
145 | acpi_ut_read_table(FILE * fp, | ||
146 | struct acpi_table_header **table, u32 *table_length) | ||
147 | { | ||
148 | struct acpi_table_header table_header; | ||
149 | u32 actual; | ||
150 | acpi_status status; | ||
151 | u32 file_size; | ||
152 | u8 standard_header = TRUE; | ||
153 | s32 count; | ||
154 | |||
155 | /* Get the file size */ | ||
156 | |||
157 | file_size = cm_get_file_size(fp); | ||
158 | if (file_size == ACPI_UINT32_MAX) { | ||
159 | return (AE_ERROR); | ||
160 | } | ||
161 | |||
162 | if (file_size < 4) { | ||
163 | return (AE_BAD_HEADER); | ||
164 | } | ||
165 | |||
166 | /* Read the signature */ | ||
167 | |||
168 | fseek(fp, 0, SEEK_SET); | ||
169 | |||
170 | count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp); | ||
171 | if (count != sizeof(struct acpi_table_header)) { | ||
172 | acpi_os_printf("Could not read the table header\n"); | ||
173 | return (AE_BAD_HEADER); | ||
174 | } | ||
175 | |||
176 | /* The RSDP table does not have standard ACPI header */ | ||
177 | |||
178 | if (ACPI_VALIDATE_RSDP_SIG(table_header.signature)) { | ||
179 | *table_length = file_size; | ||
180 | standard_header = FALSE; | ||
181 | } else { | ||
182 | |||
183 | #if 0 | ||
184 | /* Validate the table header/length */ | ||
185 | |||
186 | status = acpi_tb_validate_table_header(&table_header); | ||
187 | if (ACPI_FAILURE(status)) { | ||
188 | acpi_os_printf("Table header is invalid!\n"); | ||
189 | return (status); | ||
190 | } | ||
191 | #endif | ||
192 | |||
193 | /* File size must be at least as long as the Header-specified length */ | ||
194 | |||
195 | if (table_header.length > file_size) { | ||
196 | acpi_os_printf | ||
197 | ("TableHeader length [0x%X] greater than the input file size [0x%X]\n", | ||
198 | table_header.length, file_size); | ||
199 | |||
200 | #ifdef ACPI_ASL_COMPILER | ||
201 | status = fl_check_for_ascii(fp, NULL, FALSE); | ||
202 | if (ACPI_SUCCESS(status)) { | ||
203 | acpi_os_printf | ||
204 | ("File appears to be ASCII only, must be binary\n"); | ||
205 | } | ||
206 | #endif | ||
207 | return (AE_BAD_HEADER); | ||
208 | } | ||
209 | #ifdef ACPI_OBSOLETE_CODE | ||
210 | /* We only support a limited number of table types */ | ||
211 | |||
212 | if (!ACPI_COMPARE_NAME | ||
213 | ((char *)table_header.signature, ACPI_SIG_DSDT) | ||
214 | && !ACPI_COMPARE_NAME((char *)table_header.signature, | ||
215 | ACPI_SIG_PSDT) | ||
216 | && !ACPI_COMPARE_NAME((char *)table_header.signature, | ||
217 | ACPI_SIG_SSDT)) { | ||
218 | acpi_os_printf | ||
219 | ("Table signature [%4.4s] is invalid or not supported\n", | ||
220 | (char *)table_header.signature); | ||
221 | ACPI_DUMP_BUFFER(&table_header, | ||
222 | sizeof(struct acpi_table_header)); | ||
223 | return (AE_ERROR); | ||
224 | } | ||
225 | #endif | ||
226 | |||
227 | *table_length = table_header.length; | ||
228 | } | ||
229 | |||
230 | /* Allocate a buffer for the table */ | ||
231 | |||
232 | *table = acpi_os_allocate((size_t) file_size); | ||
233 | if (!*table) { | ||
234 | acpi_os_printf | ||
235 | ("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n", | ||
236 | table_header.signature, *table_length); | ||
237 | return (AE_NO_MEMORY); | ||
238 | } | ||
239 | |||
240 | /* Get the rest of the table */ | ||
241 | |||
242 | fseek(fp, 0, SEEK_SET); | ||
243 | actual = fread(*table, 1, (size_t) file_size, fp); | ||
244 | if (actual == file_size) { | ||
245 | if (standard_header) { | ||
246 | |||
247 | /* Now validate the checksum */ | ||
248 | |||
249 | status = acpi_tb_verify_checksum((void *)*table, | ||
250 | ACPI_CAST_PTR(struct | ||
251 | acpi_table_header, | ||
252 | *table)-> | ||
253 | length); | ||
254 | |||
255 | if (status == AE_BAD_CHECKSUM) { | ||
256 | status = | ||
257 | acpi_ut_check_text_mode_corruption((u8 *) | ||
258 | *table, | ||
259 | file_size, | ||
260 | (*table)-> | ||
261 | length); | ||
262 | return (status); | ||
263 | } | ||
264 | } | ||
265 | return (AE_OK); | ||
266 | } | ||
267 | |||
268 | if (actual > 0) { | ||
269 | acpi_os_printf("Warning - reading table, asked for %X got %X\n", | ||
270 | file_size, actual); | ||
271 | return (AE_OK); | ||
272 | } | ||
273 | |||
274 | acpi_os_printf("Error - could not read the table file\n"); | ||
275 | acpi_os_free(*table); | ||
276 | *table = NULL; | ||
277 | *table_length = 0; | ||
278 | return (AE_ERROR); | ||
279 | } | ||
280 | |||
281 | /******************************************************************************* | ||
282 | * | ||
283 | * FUNCTION: acpi_ut_read_table_from_file | ||
284 | * | ||
285 | * PARAMETERS: filename - File where table is located | ||
286 | * table - Where a pointer to the table is returned | ||
287 | * | ||
288 | * RETURN: Status | ||
289 | * | ||
290 | * DESCRIPTION: Get an ACPI table from a file | ||
291 | * | ||
292 | ******************************************************************************/ | ||
293 | |||
294 | acpi_status | ||
295 | acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table) | ||
296 | { | ||
297 | FILE *file; | ||
298 | u32 file_size; | ||
299 | u32 table_length; | ||
300 | acpi_status status = AE_ERROR; | ||
301 | |||
302 | /* Open the file, get current size */ | ||
303 | |||
304 | file = fopen(filename, "rb"); | ||
305 | if (!file) { | ||
306 | perror("Could not open input file"); | ||
307 | return (status); | ||
308 | } | ||
309 | |||
310 | file_size = cm_get_file_size(file); | ||
311 | if (file_size == ACPI_UINT32_MAX) { | ||
312 | goto exit; | ||
313 | } | ||
314 | |||
315 | /* Get the entire file */ | ||
316 | |||
317 | fprintf(stderr, | ||
318 | "Loading Acpi table from file %10s - Length %.8u (%06X)\n", | ||
319 | filename, file_size, file_size); | ||
320 | |||
321 | status = acpi_ut_read_table(file, table, &table_length); | ||
322 | if (ACPI_FAILURE(status)) { | ||
323 | acpi_os_printf("Could not get table from the file\n"); | ||
324 | } | ||
325 | |||
326 | exit: | ||
327 | fclose(file); | ||
328 | return (status); | ||
329 | } | ||
330 | |||
331 | #endif | ||
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index d69be3cb3fae..77ceac715f28 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c | |||
@@ -214,152 +214,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] = | |||
214 | }; | 214 | }; |
215 | #endif /* !ACPI_REDUCED_HARDWARE */ | 215 | #endif /* !ACPI_REDUCED_HARDWARE */ |
216 | 216 | ||
217 | /******************************************************************************* | ||
218 | * | ||
219 | * FUNCTION: acpi_ut_init_globals | ||
220 | * | ||
221 | * PARAMETERS: None | ||
222 | * | ||
223 | * RETURN: Status | ||
224 | * | ||
225 | * DESCRIPTION: Initialize ACPICA globals. All globals that require specific | ||
226 | * initialization should be initialized here. This allows for | ||
227 | * a warm restart. | ||
228 | * | ||
229 | ******************************************************************************/ | ||
230 | |||
231 | acpi_status acpi_ut_init_globals(void) | ||
232 | { | ||
233 | acpi_status status; | ||
234 | u32 i; | ||
235 | |||
236 | ACPI_FUNCTION_TRACE(ut_init_globals); | ||
237 | |||
238 | /* Create all memory caches */ | ||
239 | |||
240 | status = acpi_ut_create_caches(); | ||
241 | if (ACPI_FAILURE(status)) { | ||
242 | return_ACPI_STATUS(status); | ||
243 | } | ||
244 | |||
245 | /* Address Range lists */ | ||
246 | |||
247 | for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { | ||
248 | acpi_gbl_address_range_list[i] = NULL; | ||
249 | } | ||
250 | |||
251 | /* Mutex locked flags */ | ||
252 | |||
253 | for (i = 0; i < ACPI_NUM_MUTEX; i++) { | ||
254 | acpi_gbl_mutex_info[i].mutex = NULL; | ||
255 | acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; | ||
256 | acpi_gbl_mutex_info[i].use_count = 0; | ||
257 | } | ||
258 | |||
259 | for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { | ||
260 | acpi_gbl_owner_id_mask[i] = 0; | ||
261 | } | ||
262 | |||
263 | /* Last owner_ID is never valid */ | ||
264 | |||
265 | acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; | ||
266 | |||
267 | /* Event counters */ | ||
268 | |||
269 | acpi_method_count = 0; | ||
270 | acpi_sci_count = 0; | ||
271 | acpi_gpe_count = 0; | ||
272 | |||
273 | for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { | ||
274 | acpi_fixed_event_count[i] = 0; | ||
275 | } | ||
276 | |||
277 | #if (!ACPI_REDUCED_HARDWARE) | ||
278 | |||
279 | /* GPE/SCI support */ | ||
280 | |||
281 | acpi_gbl_all_gpes_initialized = FALSE; | ||
282 | acpi_gbl_gpe_xrupt_list_head = NULL; | ||
283 | acpi_gbl_gpe_fadt_blocks[0] = NULL; | ||
284 | acpi_gbl_gpe_fadt_blocks[1] = NULL; | ||
285 | acpi_current_gpe_count = 0; | ||
286 | |||
287 | acpi_gbl_global_event_handler = NULL; | ||
288 | acpi_gbl_sci_handler_list = NULL; | ||
289 | |||
290 | #endif /* !ACPI_REDUCED_HARDWARE */ | ||
291 | |||
292 | /* Global handlers */ | ||
293 | |||
294 | acpi_gbl_global_notify[0].handler = NULL; | ||
295 | acpi_gbl_global_notify[1].handler = NULL; | ||
296 | acpi_gbl_exception_handler = NULL; | ||
297 | acpi_gbl_init_handler = NULL; | ||
298 | acpi_gbl_table_handler = NULL; | ||
299 | acpi_gbl_interface_handler = NULL; | ||
300 | |||
301 | /* Global Lock support */ | ||
302 | |||
303 | acpi_gbl_global_lock_semaphore = NULL; | ||
304 | acpi_gbl_global_lock_mutex = NULL; | ||
305 | acpi_gbl_global_lock_acquired = FALSE; | ||
306 | acpi_gbl_global_lock_handle = 0; | ||
307 | acpi_gbl_global_lock_present = FALSE; | ||
308 | |||
309 | /* Miscellaneous variables */ | ||
310 | |||
311 | acpi_gbl_DSDT = NULL; | ||
312 | acpi_gbl_cm_single_step = FALSE; | ||
313 | acpi_gbl_shutdown = FALSE; | ||
314 | acpi_gbl_ns_lookup_count = 0; | ||
315 | acpi_gbl_ps_find_count = 0; | ||
316 | acpi_gbl_acpi_hardware_present = TRUE; | ||
317 | acpi_gbl_last_owner_id_index = 0; | ||
318 | acpi_gbl_next_owner_id_offset = 0; | ||
319 | acpi_gbl_trace_dbg_level = 0; | ||
320 | acpi_gbl_trace_dbg_layer = 0; | ||
321 | acpi_gbl_debugger_configuration = DEBUGGER_THREADING; | ||
322 | acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; | ||
323 | acpi_gbl_osi_mutex = NULL; | ||
324 | acpi_gbl_reg_methods_executed = FALSE; | ||
325 | |||
326 | /* Hardware oriented */ | ||
327 | |||
328 | acpi_gbl_events_initialized = FALSE; | ||
329 | acpi_gbl_system_awake_and_running = TRUE; | ||
330 | |||
331 | /* Namespace */ | ||
332 | |||
333 | acpi_gbl_module_code_list = NULL; | ||
334 | acpi_gbl_root_node = NULL; | ||
335 | acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; | ||
336 | acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; | ||
337 | acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; | ||
338 | acpi_gbl_root_node_struct.parent = NULL; | ||
339 | acpi_gbl_root_node_struct.child = NULL; | ||
340 | acpi_gbl_root_node_struct.peer = NULL; | ||
341 | acpi_gbl_root_node_struct.object = NULL; | ||
342 | |||
343 | #ifdef ACPI_DISASSEMBLER | ||
344 | acpi_gbl_external_list = NULL; | ||
345 | acpi_gbl_num_external_methods = 0; | ||
346 | acpi_gbl_resolved_external_methods = 0; | ||
347 | #endif | ||
348 | |||
349 | #ifdef ACPI_DEBUG_OUTPUT | ||
350 | acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); | ||
351 | #endif | ||
352 | |||
353 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS | ||
354 | acpi_gbl_display_final_mem_stats = FALSE; | ||
355 | acpi_gbl_disable_mem_tracking = FALSE; | ||
356 | #endif | ||
357 | |||
358 | ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE); | ||
359 | |||
360 | return_ACPI_STATUS(AE_OK); | ||
361 | } | ||
362 | |||
363 | /* Public globals */ | 217 | /* Public globals */ |
364 | 218 | ||
365 | ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) | 219 | ACPI_EXPORT_SYMBOL(acpi_gbl_FADT) |
diff --git a/drivers/acpi/acpica/uthex.c b/drivers/acpi/acpica/uthex.c new file mode 100644 index 000000000000..9afa9441b183 --- /dev/null +++ b/drivers/acpi/acpica/uthex.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: uthex -- Hex/ASCII support functions | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | |||
47 | #define _COMPONENT ACPI_COMPILER | ||
48 | ACPI_MODULE_NAME("uthex") | ||
49 | |||
50 | /* Hex to ASCII conversion table */ | ||
51 | static char acpi_gbl_hex_to_ascii[] = { | ||
52 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', | ||
53 | 'E', 'F' | ||
54 | }; | ||
55 | |||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_ut_hex_to_ascii_char | ||
59 | * | ||
60 | * PARAMETERS: integer - Contains the hex digit | ||
61 | * position - bit position of the digit within the | ||
62 | * integer (multiple of 4) | ||
63 | * | ||
64 | * RETURN: The converted Ascii character | ||
65 | * | ||
66 | * DESCRIPTION: Convert a hex digit to an Ascii character | ||
67 | * | ||
68 | ******************************************************************************/ | ||
69 | |||
70 | char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) | ||
71 | { | ||
72 | |||
73 | return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]); | ||
74 | } | ||
75 | |||
76 | /******************************************************************************* | ||
77 | * | ||
78 | * FUNCTION: acpi_ut_hex_char_to_value | ||
79 | * | ||
80 | * PARAMETERS: ascii_char - Hex character in Ascii | ||
81 | * | ||
82 | * RETURN: The binary value of the ascii/hex character | ||
83 | * | ||
84 | * DESCRIPTION: Perform ascii-to-hex translation | ||
85 | * | ||
86 | ******************************************************************************/ | ||
87 | |||
88 | u8 acpi_ut_ascii_char_to_hex(int hex_char) | ||
89 | { | ||
90 | |||
91 | if (hex_char <= 0x39) { | ||
92 | return ((u8)(hex_char - 0x30)); | ||
93 | } | ||
94 | |||
95 | if (hex_char <= 0x46) { | ||
96 | return ((u8)(hex_char - 0x37)); | ||
97 | } | ||
98 | |||
99 | return ((u8)(hex_char - 0x57)); | ||
100 | } | ||
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index 5f56fc49021e..77120ec9ea86 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c | |||
@@ -102,6 +102,151 @@ static void acpi_ut_free_gpe_lists(void) | |||
102 | } | 102 | } |
103 | #endif /* !ACPI_REDUCED_HARDWARE */ | 103 | #endif /* !ACPI_REDUCED_HARDWARE */ |
104 | 104 | ||
105 | /******************************************************************************* | ||
106 | * | ||
107 | * FUNCTION: acpi_ut_init_globals | ||
108 | * | ||
109 | * PARAMETERS: None | ||
110 | * | ||
111 | * RETURN: Status | ||
112 | * | ||
113 | * DESCRIPTION: Initialize ACPICA globals. All globals that require specific | ||
114 | * initialization should be initialized here. This allows for | ||
115 | * a warm restart. | ||
116 | * | ||
117 | ******************************************************************************/ | ||
118 | |||
119 | acpi_status acpi_ut_init_globals(void) | ||
120 | { | ||
121 | acpi_status status; | ||
122 | u32 i; | ||
123 | |||
124 | ACPI_FUNCTION_TRACE(ut_init_globals); | ||
125 | |||
126 | /* Create all memory caches */ | ||
127 | |||
128 | status = acpi_ut_create_caches(); | ||
129 | if (ACPI_FAILURE(status)) { | ||
130 | return_ACPI_STATUS(status); | ||
131 | } | ||
132 | |||
133 | /* Address Range lists */ | ||
134 | |||
135 | for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { | ||
136 | acpi_gbl_address_range_list[i] = NULL; | ||
137 | } | ||
138 | |||
139 | /* Mutex locked flags */ | ||
140 | |||
141 | for (i = 0; i < ACPI_NUM_MUTEX; i++) { | ||
142 | acpi_gbl_mutex_info[i].mutex = NULL; | ||
143 | acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED; | ||
144 | acpi_gbl_mutex_info[i].use_count = 0; | ||
145 | } | ||
146 | |||
147 | for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { | ||
148 | acpi_gbl_owner_id_mask[i] = 0; | ||
149 | } | ||
150 | |||
151 | /* Last owner_ID is never valid */ | ||
152 | |||
153 | acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; | ||
154 | |||
155 | /* Event counters */ | ||
156 | |||
157 | acpi_method_count = 0; | ||
158 | acpi_sci_count = 0; | ||
159 | acpi_gpe_count = 0; | ||
160 | |||
161 | for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { | ||
162 | acpi_fixed_event_count[i] = 0; | ||
163 | } | ||
164 | |||
165 | #if (!ACPI_REDUCED_HARDWARE) | ||
166 | |||
167 | /* GPE/SCI support */ | ||
168 | |||
169 | acpi_gbl_all_gpes_initialized = FALSE; | ||
170 | acpi_gbl_gpe_xrupt_list_head = NULL; | ||
171 | acpi_gbl_gpe_fadt_blocks[0] = NULL; | ||
172 | acpi_gbl_gpe_fadt_blocks[1] = NULL; | ||
173 | acpi_current_gpe_count = 0; | ||
174 | |||
175 | acpi_gbl_global_event_handler = NULL; | ||
176 | acpi_gbl_sci_handler_list = NULL; | ||
177 | |||
178 | #endif /* !ACPI_REDUCED_HARDWARE */ | ||
179 | |||
180 | /* Global handlers */ | ||
181 | |||
182 | acpi_gbl_global_notify[0].handler = NULL; | ||
183 | acpi_gbl_global_notify[1].handler = NULL; | ||
184 | acpi_gbl_exception_handler = NULL; | ||
185 | acpi_gbl_init_handler = NULL; | ||
186 | acpi_gbl_table_handler = NULL; | ||
187 | acpi_gbl_interface_handler = NULL; | ||
188 | |||
189 | /* Global Lock support */ | ||
190 | |||
191 | acpi_gbl_global_lock_semaphore = NULL; | ||
192 | acpi_gbl_global_lock_mutex = NULL; | ||
193 | acpi_gbl_global_lock_acquired = FALSE; | ||
194 | acpi_gbl_global_lock_handle = 0; | ||
195 | acpi_gbl_global_lock_present = FALSE; | ||
196 | |||
197 | /* Miscellaneous variables */ | ||
198 | |||
199 | acpi_gbl_DSDT = NULL; | ||
200 | acpi_gbl_cm_single_step = FALSE; | ||
201 | acpi_gbl_shutdown = FALSE; | ||
202 | acpi_gbl_ns_lookup_count = 0; | ||
203 | acpi_gbl_ps_find_count = 0; | ||
204 | acpi_gbl_acpi_hardware_present = TRUE; | ||
205 | acpi_gbl_last_owner_id_index = 0; | ||
206 | acpi_gbl_next_owner_id_offset = 0; | ||
207 | acpi_gbl_trace_dbg_level = 0; | ||
208 | acpi_gbl_trace_dbg_layer = 0; | ||
209 | acpi_gbl_debugger_configuration = DEBUGGER_THREADING; | ||
210 | acpi_gbl_osi_mutex = NULL; | ||
211 | acpi_gbl_reg_methods_executed = FALSE; | ||
212 | |||
213 | /* Hardware oriented */ | ||
214 | |||
215 | acpi_gbl_events_initialized = FALSE; | ||
216 | acpi_gbl_system_awake_and_running = TRUE; | ||
217 | |||
218 | /* Namespace */ | ||
219 | |||
220 | acpi_gbl_module_code_list = NULL; | ||
221 | acpi_gbl_root_node = NULL; | ||
222 | acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; | ||
223 | acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; | ||
224 | acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE; | ||
225 | acpi_gbl_root_node_struct.parent = NULL; | ||
226 | acpi_gbl_root_node_struct.child = NULL; | ||
227 | acpi_gbl_root_node_struct.peer = NULL; | ||
228 | acpi_gbl_root_node_struct.object = NULL; | ||
229 | |||
230 | #ifdef ACPI_DISASSEMBLER | ||
231 | acpi_gbl_external_list = NULL; | ||
232 | acpi_gbl_num_external_methods = 0; | ||
233 | acpi_gbl_resolved_external_methods = 0; | ||
234 | #endif | ||
235 | |||
236 | #ifdef ACPI_DEBUG_OUTPUT | ||
237 | acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); | ||
238 | #endif | ||
239 | |||
240 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS | ||
241 | acpi_gbl_display_final_mem_stats = FALSE; | ||
242 | acpi_gbl_disable_mem_tracking = FALSE; | ||
243 | #endif | ||
244 | |||
245 | ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = FALSE); | ||
246 | |||
247 | return_ACPI_STATUS(AE_OK); | ||
248 | } | ||
249 | |||
105 | /****************************************************************************** | 250 | /****************************************************************************** |
106 | * | 251 | * |
107 | * FUNCTION: acpi_ut_terminate | 252 | * FUNCTION: acpi_ut_terminate |
diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c new file mode 100644 index 000000000000..0ce3f5a0dd67 --- /dev/null +++ b/drivers/acpi/acpica/utprint.c | |||
@@ -0,0 +1,664 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: utprint - Formatted printing routines | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | |||
47 | #define _COMPONENT ACPI_UTILITIES | ||
48 | ACPI_MODULE_NAME("utprint") | ||
49 | |||
50 | #define ACPI_FORMAT_SIGN 0x01 | ||
51 | #define ACPI_FORMAT_SIGN_PLUS 0x02 | ||
52 | #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04 | ||
53 | #define ACPI_FORMAT_ZERO 0x08 | ||
54 | #define ACPI_FORMAT_LEFT 0x10 | ||
55 | #define ACPI_FORMAT_UPPER 0x20 | ||
56 | #define ACPI_FORMAT_PREFIX 0x40 | ||
57 | /* Local prototypes */ | ||
58 | static acpi_size | ||
59 | acpi_ut_bound_string_length(const char *string, acpi_size count); | ||
60 | |||
61 | static char *acpi_ut_bound_string_output(char *string, const char *end, char c); | ||
62 | |||
63 | static char *acpi_ut_format_number(char *string, | ||
64 | char *end, | ||
65 | u64 number, | ||
66 | u8 base, s32 width, s32 precision, u8 type); | ||
67 | |||
68 | static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper); | ||
69 | |||
70 | /* Module globals */ | ||
71 | |||
72 | static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef"; | ||
73 | static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF"; | ||
74 | |||
75 | /******************************************************************************* | ||
76 | * | ||
77 | * FUNCTION: acpi_ut_bound_string_length | ||
78 | * | ||
79 | * PARAMETERS: string - String with boundary | ||
80 | * count - Boundary of the string | ||
81 | * | ||
82 | * RETURN: Length of the string. Less than or equal to Count. | ||
83 | * | ||
84 | * DESCRIPTION: Calculate the length of a string with boundary. | ||
85 | * | ||
86 | ******************************************************************************/ | ||
87 | |||
88 | static acpi_size | ||
89 | acpi_ut_bound_string_length(const char *string, acpi_size count) | ||
90 | { | ||
91 | u32 length = 0; | ||
92 | |||
93 | while (*string && count) { | ||
94 | length++; | ||
95 | string++; | ||
96 | count--; | ||
97 | } | ||
98 | |||
99 | return (length); | ||
100 | } | ||
101 | |||
102 | /******************************************************************************* | ||
103 | * | ||
104 | * FUNCTION: acpi_ut_bound_string_output | ||
105 | * | ||
106 | * PARAMETERS: string - String with boundary | ||
107 | * end - Boundary of the string | ||
108 | * c - Character to be output to the string | ||
109 | * | ||
110 | * RETURN: Updated position for next valid character | ||
111 | * | ||
112 | * DESCRIPTION: Output a character into a string with boundary check. | ||
113 | * | ||
114 | ******************************************************************************/ | ||
115 | |||
116 | static char *acpi_ut_bound_string_output(char *string, const char *end, char c) | ||
117 | { | ||
118 | |||
119 | if (string < end) { | ||
120 | *string = c; | ||
121 | } | ||
122 | |||
123 | ++string; | ||
124 | return (string); | ||
125 | } | ||
126 | |||
127 | /******************************************************************************* | ||
128 | * | ||
129 | * FUNCTION: acpi_ut_put_number | ||
130 | * | ||
131 | * PARAMETERS: string - Buffer to hold reverse-ordered string | ||
132 | * number - Integer to be converted | ||
133 | * base - Base of the integer | ||
134 | * upper - Whether or not using upper cased digits | ||
135 | * | ||
136 | * RETURN: Updated position for next valid character | ||
137 | * | ||
138 | * DESCRIPTION: Convert an integer into a string, note that, the string holds a | ||
139 | * reversed ordered number without the trailing zero. | ||
140 | * | ||
141 | ******************************************************************************/ | ||
142 | |||
143 | static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper) | ||
144 | { | ||
145 | const char *digits; | ||
146 | u64 digit_index; | ||
147 | char *pos; | ||
148 | |||
149 | pos = string; | ||
150 | digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits; | ||
151 | |||
152 | if (number == 0) { | ||
153 | *(pos++) = '0'; | ||
154 | } else { | ||
155 | while (number) { | ||
156 | (void)acpi_ut_divide(number, base, &number, | ||
157 | &digit_index); | ||
158 | *(pos++) = digits[digit_index]; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | /* *(Pos++) = '0'; */ | ||
163 | return (pos); | ||
164 | } | ||
165 | |||
166 | /******************************************************************************* | ||
167 | * | ||
168 | * FUNCTION: acpi_ut_scan_number | ||
169 | * | ||
170 | * PARAMETERS: string - String buffer | ||
171 | * number_ptr - Where the number is returned | ||
172 | * | ||
173 | * RETURN: Updated position for next valid character | ||
174 | * | ||
175 | * DESCRIPTION: Scan a string for a decimal integer. | ||
176 | * | ||
177 | ******************************************************************************/ | ||
178 | |||
179 | const char *acpi_ut_scan_number(const char *string, u64 *number_ptr) | ||
180 | { | ||
181 | u64 number = 0; | ||
182 | |||
183 | while (ACPI_IS_DIGIT(*string)) { | ||
184 | number *= 10; | ||
185 | number += *(string++) - '0'; | ||
186 | } | ||
187 | |||
188 | *number_ptr = number; | ||
189 | return (string); | ||
190 | } | ||
191 | |||
192 | /******************************************************************************* | ||
193 | * | ||
194 | * FUNCTION: acpi_ut_print_number | ||
195 | * | ||
196 | * PARAMETERS: string - String buffer | ||
197 | * number - The number to be converted | ||
198 | * | ||
199 | * RETURN: Updated position for next valid character | ||
200 | * | ||
201 | * DESCRIPTION: Print a decimal integer into a string. | ||
202 | * | ||
203 | ******************************************************************************/ | ||
204 | |||
205 | const char *acpi_ut_print_number(char *string, u64 number) | ||
206 | { | ||
207 | char ascii_string[20]; | ||
208 | const char *pos1; | ||
209 | char *pos2; | ||
210 | |||
211 | pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE); | ||
212 | pos2 = string; | ||
213 | |||
214 | while (pos1 != ascii_string) { | ||
215 | *(pos2++) = *(--pos1); | ||
216 | } | ||
217 | |||
218 | *pos2 = 0; | ||
219 | return (string); | ||
220 | } | ||
221 | |||
222 | /******************************************************************************* | ||
223 | * | ||
224 | * FUNCTION: acpi_ut_format_number | ||
225 | * | ||
226 | * PARAMETERS: string - String buffer with boundary | ||
227 | * end - Boundary of the string | ||
228 | * number - The number to be converted | ||
229 | * base - Base of the integer | ||
230 | * width - Field width | ||
231 | * precision - Precision of the integer | ||
232 | * type - Special printing flags | ||
233 | * | ||
234 | * RETURN: Updated position for next valid character | ||
235 | * | ||
236 | * DESCRIPTION: Print an integer into a string with any base and any precision. | ||
237 | * | ||
238 | ******************************************************************************/ | ||
239 | |||
240 | static char *acpi_ut_format_number(char *string, | ||
241 | char *end, | ||
242 | u64 number, | ||
243 | u8 base, s32 width, s32 precision, u8 type) | ||
244 | { | ||
245 | char *pos; | ||
246 | char sign; | ||
247 | char zero; | ||
248 | u8 need_prefix; | ||
249 | u8 upper; | ||
250 | s32 i; | ||
251 | char reversed_string[66]; | ||
252 | |||
253 | /* Parameter validation */ | ||
254 | |||
255 | if (base < 2 || base > 16) { | ||
256 | return (NULL); | ||
257 | } | ||
258 | |||
259 | if (type & ACPI_FORMAT_LEFT) { | ||
260 | type &= ~ACPI_FORMAT_ZERO; | ||
261 | } | ||
262 | |||
263 | need_prefix = ((type & ACPI_FORMAT_PREFIX) | ||
264 | && base != 10) ? TRUE : FALSE; | ||
265 | upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; | ||
266 | zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' '; | ||
267 | |||
268 | /* Calculate size according to sign and prefix */ | ||
269 | |||
270 | sign = '\0'; | ||
271 | if (type & ACPI_FORMAT_SIGN) { | ||
272 | if ((s64) number < 0) { | ||
273 | sign = '-'; | ||
274 | number = -(s64) number; | ||
275 | width--; | ||
276 | } else if (type & ACPI_FORMAT_SIGN_PLUS) { | ||
277 | sign = '+'; | ||
278 | width--; | ||
279 | } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) { | ||
280 | sign = ' '; | ||
281 | width--; | ||
282 | } | ||
283 | } | ||
284 | if (need_prefix) { | ||
285 | width--; | ||
286 | if (base == 16) { | ||
287 | width--; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | /* Generate full string in reverse order */ | ||
292 | |||
293 | pos = acpi_ut_put_number(reversed_string, number, base, upper); | ||
294 | i = ACPI_PTR_DIFF(pos, reversed_string); | ||
295 | |||
296 | /* Printing 100 using %2d gives "100", not "00" */ | ||
297 | |||
298 | if (i > precision) { | ||
299 | precision = i; | ||
300 | } | ||
301 | |||
302 | width -= precision; | ||
303 | |||
304 | /* Output the string */ | ||
305 | |||
306 | if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) { | ||
307 | while (--width >= 0) { | ||
308 | string = acpi_ut_bound_string_output(string, end, ' '); | ||
309 | } | ||
310 | } | ||
311 | if (sign) { | ||
312 | string = acpi_ut_bound_string_output(string, end, sign); | ||
313 | } | ||
314 | if (need_prefix) { | ||
315 | string = acpi_ut_bound_string_output(string, end, '0'); | ||
316 | if (base == 16) { | ||
317 | string = acpi_ut_bound_string_output(string, end, | ||
318 | upper ? 'X' : 'x'); | ||
319 | } | ||
320 | } | ||
321 | if (!(type & ACPI_FORMAT_LEFT)) { | ||
322 | while (--width >= 0) { | ||
323 | string = acpi_ut_bound_string_output(string, end, zero); | ||
324 | } | ||
325 | } | ||
326 | |||
327 | while (i <= --precision) { | ||
328 | string = acpi_ut_bound_string_output(string, end, '0'); | ||
329 | } | ||
330 | while (--i >= 0) { | ||
331 | string = acpi_ut_bound_string_output(string, end, | ||
332 | reversed_string[i]); | ||
333 | } | ||
334 | while (--width >= 0) { | ||
335 | string = acpi_ut_bound_string_output(string, end, ' '); | ||
336 | } | ||
337 | |||
338 | return (string); | ||
339 | } | ||
340 | |||
341 | /******************************************************************************* | ||
342 | * | ||
343 | * FUNCTION: acpi_ut_vsnprintf | ||
344 | * | ||
345 | * PARAMETERS: string - String with boundary | ||
346 | * size - Boundary of the string | ||
347 | * format - Standard printf format | ||
348 | * args - Argument list | ||
349 | * | ||
350 | * RETURN: Number of bytes actually written. | ||
351 | * | ||
352 | * DESCRIPTION: Formatted output to a string using argument list pointer. | ||
353 | * | ||
354 | ******************************************************************************/ | ||
355 | |||
356 | int | ||
357 | acpi_ut_vsnprintf(char *string, | ||
358 | acpi_size size, const char *format, va_list args) | ||
359 | { | ||
360 | u8 base = 10; | ||
361 | u8 type = 0; | ||
362 | s32 width = -1; | ||
363 | s32 precision = -1; | ||
364 | char qualifier = 0; | ||
365 | u64 number; | ||
366 | char *pos; | ||
367 | char *end; | ||
368 | char c; | ||
369 | const char *s; | ||
370 | const void *p; | ||
371 | s32 length; | ||
372 | int i; | ||
373 | |||
374 | pos = string; | ||
375 | end = string + size; | ||
376 | |||
377 | for (; *format; ++format) { | ||
378 | if (*format != '%') { | ||
379 | pos = acpi_ut_bound_string_output(pos, end, *format); | ||
380 | continue; | ||
381 | } | ||
382 | |||
383 | /* Process sign */ | ||
384 | |||
385 | do { | ||
386 | ++format; | ||
387 | if (*format == '#') { | ||
388 | type |= ACPI_FORMAT_PREFIX; | ||
389 | } else if (*format == '0') { | ||
390 | type |= ACPI_FORMAT_ZERO; | ||
391 | } else if (*format == '+') { | ||
392 | type |= ACPI_FORMAT_SIGN_PLUS; | ||
393 | } else if (*format == ' ') { | ||
394 | type |= ACPI_FORMAT_SIGN_PLUS_SPACE; | ||
395 | } else if (*format == '-') { | ||
396 | type |= ACPI_FORMAT_LEFT; | ||
397 | } else { | ||
398 | break; | ||
399 | } | ||
400 | } while (1); | ||
401 | |||
402 | /* Process width */ | ||
403 | |||
404 | width = -1; | ||
405 | if (ACPI_IS_DIGIT(*format)) { | ||
406 | format = acpi_ut_scan_number(format, &number); | ||
407 | width = (s32) number; | ||
408 | } else if (*format == '*') { | ||
409 | ++format; | ||
410 | width = va_arg(args, int); | ||
411 | if (width < 0) { | ||
412 | width = -width; | ||
413 | type |= ACPI_FORMAT_LEFT; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | /* Process precision */ | ||
418 | |||
419 | precision = -1; | ||
420 | if (*format == '.') { | ||
421 | ++format; | ||
422 | if (ACPI_IS_DIGIT(*format)) { | ||
423 | format = acpi_ut_scan_number(format, &number); | ||
424 | precision = (s32) number; | ||
425 | } else if (*format == '*') { | ||
426 | ++format; | ||
427 | precision = va_arg(args, int); | ||
428 | } | ||
429 | if (precision < 0) { | ||
430 | precision = 0; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | /* Process qualifier */ | ||
435 | |||
436 | qualifier = -1; | ||
437 | if (*format == 'h' || *format == 'l' || *format == 'L') { | ||
438 | qualifier = *format; | ||
439 | ++format; | ||
440 | |||
441 | if (qualifier == 'l' && *format == 'l') { | ||
442 | qualifier = 'L'; | ||
443 | ++format; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | switch (*format) { | ||
448 | case '%': | ||
449 | |||
450 | pos = acpi_ut_bound_string_output(pos, end, '%'); | ||
451 | continue; | ||
452 | |||
453 | case 'c': | ||
454 | |||
455 | if (!(type & ACPI_FORMAT_LEFT)) { | ||
456 | while (--width > 0) { | ||
457 | pos = | ||
458 | acpi_ut_bound_string_output(pos, | ||
459 | end, | ||
460 | ' '); | ||
461 | } | ||
462 | } | ||
463 | |||
464 | c = (char)va_arg(args, int); | ||
465 | pos = acpi_ut_bound_string_output(pos, end, c); | ||
466 | |||
467 | while (--width > 0) { | ||
468 | pos = | ||
469 | acpi_ut_bound_string_output(pos, end, ' '); | ||
470 | } | ||
471 | continue; | ||
472 | |||
473 | case 's': | ||
474 | |||
475 | s = va_arg(args, char *); | ||
476 | if (!s) { | ||
477 | s = "<NULL>"; | ||
478 | } | ||
479 | length = acpi_ut_bound_string_length(s, precision); | ||
480 | if (!(type & ACPI_FORMAT_LEFT)) { | ||
481 | while (length < width--) { | ||
482 | pos = | ||
483 | acpi_ut_bound_string_output(pos, | ||
484 | end, | ||
485 | ' '); | ||
486 | } | ||
487 | } | ||
488 | for (i = 0; i < length; ++i) { | ||
489 | pos = acpi_ut_bound_string_output(pos, end, *s); | ||
490 | ++s; | ||
491 | } | ||
492 | while (length < width--) { | ||
493 | pos = | ||
494 | acpi_ut_bound_string_output(pos, end, ' '); | ||
495 | } | ||
496 | continue; | ||
497 | |||
498 | case 'o': | ||
499 | |||
500 | base = 8; | ||
501 | break; | ||
502 | |||
503 | case 'X': | ||
504 | |||
505 | type |= ACPI_FORMAT_UPPER; | ||
506 | |||
507 | case 'x': | ||
508 | |||
509 | base = 16; | ||
510 | break; | ||
511 | |||
512 | case 'd': | ||
513 | case 'i': | ||
514 | |||
515 | type |= ACPI_FORMAT_SIGN; | ||
516 | |||
517 | case 'u': | ||
518 | |||
519 | break; | ||
520 | |||
521 | case 'p': | ||
522 | |||
523 | if (width == -1) { | ||
524 | width = 2 * sizeof(void *); | ||
525 | type |= ACPI_FORMAT_ZERO; | ||
526 | } | ||
527 | |||
528 | p = va_arg(args, void *); | ||
529 | pos = acpi_ut_format_number(pos, end, | ||
530 | ACPI_TO_INTEGER(p), 16, | ||
531 | width, precision, type); | ||
532 | continue; | ||
533 | |||
534 | default: | ||
535 | |||
536 | pos = acpi_ut_bound_string_output(pos, end, '%'); | ||
537 | if (*format) { | ||
538 | pos = | ||
539 | acpi_ut_bound_string_output(pos, end, | ||
540 | *format); | ||
541 | } else { | ||
542 | --format; | ||
543 | } | ||
544 | continue; | ||
545 | } | ||
546 | |||
547 | if (qualifier == 'L') { | ||
548 | number = va_arg(args, u64); | ||
549 | if (type & ACPI_FORMAT_SIGN) { | ||
550 | number = (s64) number; | ||
551 | } | ||
552 | } else if (qualifier == 'l') { | ||
553 | number = va_arg(args, unsigned long); | ||
554 | if (type & ACPI_FORMAT_SIGN) { | ||
555 | number = (s32) number; | ||
556 | } | ||
557 | } else if (qualifier == 'h') { | ||
558 | number = (u16)va_arg(args, int); | ||
559 | if (type & ACPI_FORMAT_SIGN) { | ||
560 | number = (s16) number; | ||
561 | } | ||
562 | } else { | ||
563 | number = va_arg(args, unsigned int); | ||
564 | if (type & ACPI_FORMAT_SIGN) { | ||
565 | number = (signed int)number; | ||
566 | } | ||
567 | } | ||
568 | |||
569 | pos = acpi_ut_format_number(pos, end, number, base, | ||
570 | width, precision, type); | ||
571 | } | ||
572 | |||
573 | if (size > 0) { | ||
574 | if (pos < end) { | ||
575 | *pos = '\0'; | ||
576 | } else { | ||
577 | end[-1] = '\0'; | ||
578 | } | ||
579 | } | ||
580 | |||
581 | return (ACPI_PTR_DIFF(pos, string)); | ||
582 | } | ||
583 | |||
584 | /******************************************************************************* | ||
585 | * | ||
586 | * FUNCTION: acpi_ut_snprintf | ||
587 | * | ||
588 | * PARAMETERS: string - String with boundary | ||
589 | * size - Boundary of the string | ||
590 | * Format, ... - Standard printf format | ||
591 | * | ||
592 | * RETURN: Number of bytes actually written. | ||
593 | * | ||
594 | * DESCRIPTION: Formatted output to a string. | ||
595 | * | ||
596 | ******************************************************************************/ | ||
597 | |||
598 | int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...) | ||
599 | { | ||
600 | va_list args; | ||
601 | int length; | ||
602 | |||
603 | va_start(args, format); | ||
604 | length = acpi_ut_vsnprintf(string, size, format, args); | ||
605 | va_end(args); | ||
606 | |||
607 | return (length); | ||
608 | } | ||
609 | |||
610 | #ifdef ACPI_APPLICATION | ||
611 | /******************************************************************************* | ||
612 | * | ||
613 | * FUNCTION: acpi_ut_file_vprintf | ||
614 | * | ||
615 | * PARAMETERS: file - File descriptor | ||
616 | * format - Standard printf format | ||
617 | * args - Argument list | ||
618 | * | ||
619 | * RETURN: Number of bytes actually written. | ||
620 | * | ||
621 | * DESCRIPTION: Formatted output to a file using argument list pointer. | ||
622 | * | ||
623 | ******************************************************************************/ | ||
624 | |||
625 | int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args) | ||
626 | { | ||
627 | acpi_cpu_flags flags; | ||
628 | int length; | ||
629 | |||
630 | flags = acpi_os_acquire_lock(acpi_gbl_print_lock); | ||
631 | length = acpi_ut_vsnprintf(acpi_gbl_print_buffer, | ||
632 | sizeof(acpi_gbl_print_buffer), format, args); | ||
633 | |||
634 | (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1); | ||
635 | acpi_os_release_lock(acpi_gbl_print_lock, flags); | ||
636 | |||
637 | return (length); | ||
638 | } | ||
639 | |||
640 | /******************************************************************************* | ||
641 | * | ||
642 | * FUNCTION: acpi_ut_file_printf | ||
643 | * | ||
644 | * PARAMETERS: file - File descriptor | ||
645 | * Format, ... - Standard printf format | ||
646 | * | ||
647 | * RETURN: Number of bytes actually written. | ||
648 | * | ||
649 | * DESCRIPTION: Formatted output to a file. | ||
650 | * | ||
651 | ******************************************************************************/ | ||
652 | |||
653 | int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...) | ||
654 | { | ||
655 | va_list args; | ||
656 | int length; | ||
657 | |||
658 | va_start(args, format); | ||
659 | length = acpi_ut_file_vprintf(file, format, args); | ||
660 | va_end(args); | ||
661 | |||
662 | return (length); | ||
663 | } | ||
664 | #endif | ||
diff --git a/drivers/acpi/acpica/utuuid.c b/drivers/acpi/acpica/utuuid.c new file mode 100644 index 000000000000..4dc33130f134 --- /dev/null +++ b/drivers/acpi/acpica/utuuid.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: utuuid -- UUID support functions | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2014, Intel Corp. | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions, and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
19 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
20 | * including a substantially similar Disclaimer requirement for further | ||
21 | * binary redistribution. | ||
22 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
23 | * of any contributors may be used to endorse or promote products derived | ||
24 | * from this software without specific prior written permission. | ||
25 | * | ||
26 | * Alternatively, this software may be distributed under the terms of the | ||
27 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
28 | * Software Foundation. | ||
29 | * | ||
30 | * NO WARRANTY | ||
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
41 | * POSSIBILITY OF SUCH DAMAGES. | ||
42 | */ | ||
43 | |||
44 | #include <acpi/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | |||
47 | #define _COMPONENT ACPI_COMPILER | ||
48 | ACPI_MODULE_NAME("utuuid") | ||
49 | |||
50 | /* | ||
51 | * UUID support functions. | ||
52 | * | ||
53 | * This table is used to convert an input UUID ascii string to a 16 byte | ||
54 | * buffer and the reverse. The table maps a UUID buffer index 0-15 to | ||
55 | * the index within the 36-byte UUID string where the associated 2-byte | ||
56 | * hex value can be found. | ||
57 | * | ||
58 | * 36-byte UUID strings are of the form: | ||
59 | * aabbccdd-eeff-gghh-iijj-kkllmmnnoopp | ||
60 | * Where aa-pp are one byte hex numbers, made up of two hex digits | ||
61 | * | ||
62 | * Note: This table is basically the inverse of the string-to-offset table | ||
63 | * found in the ACPI spec in the description of the to_UUID macro. | ||
64 | */ | ||
65 | const u8 acpi_gbl_map_to_uuid_offset[UUID_BUFFER_LENGTH] = { | ||
66 | 6, 4, 2, 0, 11, 9, 16, 14, 19, 21, 24, 26, 28, 30, 32, 34 | ||
67 | }; | ||
68 | |||
69 | /******************************************************************************* | ||
70 | * | ||
71 | * FUNCTION: acpi_ut_convert_string_to_uuid | ||
72 | * | ||
73 | * PARAMETERS: in_string - 36-byte formatted UUID string | ||
74 | * uuid_buffer - Where the 16-byte UUID buffer is returned | ||
75 | * | ||
76 | * RETURN: None. Output data is returned in the uuid_buffer | ||
77 | * | ||
78 | * DESCRIPTION: Convert a 36-byte formatted UUID string to 16-byte UUID buffer | ||
79 | * | ||
80 | ******************************************************************************/ | ||
81 | |||
82 | void acpi_ut_convert_string_to_uuid(char *in_string, u8 *uuid_buffer) | ||
83 | { | ||
84 | u32 i; | ||
85 | |||
86 | for (i = 0; i < UUID_BUFFER_LENGTH; i++) { | ||
87 | uuid_buffer[i] = | ||
88 | (acpi_ut_ascii_char_to_hex | ||
89 | (in_string[acpi_gbl_map_to_uuid_offset[i]]) << 4); | ||
90 | |||
91 | uuid_buffer[i] |= | ||
92 | acpi_ut_ascii_char_to_hex(in_string | ||
93 | [acpi_gbl_map_to_uuid_offset[i] + | ||
94 | 1]); | ||
95 | } | ||
96 | } | ||
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index c4dac7150960..b0140c8fc733 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig | |||
@@ -1,9 +1,15 @@ | |||
1 | config HAVE_ACPI_APEI | ||
2 | bool | ||
3 | |||
4 | config HAVE_ACPI_APEI_NMI | ||
5 | bool | ||
6 | |||
1 | config ACPI_APEI | 7 | config ACPI_APEI |
2 | bool "ACPI Platform Error Interface (APEI)" | 8 | bool "ACPI Platform Error Interface (APEI)" |
3 | select MISC_FILESYSTEMS | 9 | select MISC_FILESYSTEMS |
4 | select PSTORE | 10 | select PSTORE |
5 | select UEFI_CPER | 11 | select UEFI_CPER |
6 | depends on X86 | 12 | depends on HAVE_ACPI_APEI |
7 | help | 13 | help |
8 | APEI allows to report errors (for example from the chipset) | 14 | APEI allows to report errors (for example from the chipset) |
9 | to the operating system. This improves NMI handling | 15 | to the operating system. This improves NMI handling |
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 8678dfe5366b..2cd7bdd6c8b3 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -745,6 +745,19 @@ struct dentry *apei_get_debugfs_dir(void) | |||
745 | } | 745 | } |
746 | EXPORT_SYMBOL_GPL(apei_get_debugfs_dir); | 746 | EXPORT_SYMBOL_GPL(apei_get_debugfs_dir); |
747 | 747 | ||
748 | int __weak arch_apei_enable_cmcff(struct acpi_hest_header *hest_hdr, | ||
749 | void *data) | ||
750 | { | ||
751 | return 1; | ||
752 | } | ||
753 | EXPORT_SYMBOL_GPL(arch_apei_enable_cmcff); | ||
754 | |||
755 | void __weak arch_apei_report_mem_error(int sev, | ||
756 | struct cper_sec_mem_err *mem_err) | ||
757 | { | ||
758 | } | ||
759 | EXPORT_SYMBOL_GPL(arch_apei_report_mem_error); | ||
760 | |||
748 | int apei_osc_setup(void) | 761 | int apei_osc_setup(void) |
749 | { | 762 | { |
750 | static u8 whea_uuid_str[] = "ed855e0c-6c90-47bf-a62a-26de0fc5ad5c"; | 763 | static u8 whea_uuid_str[] = "ed855e0c-6c90-47bf-a62a-26de0fc5ad5c"; |
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index e5bcd919d4e6..16129c78b489 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h | |||
@@ -121,11 +121,11 @@ struct dentry; | |||
121 | struct dentry *apei_get_debugfs_dir(void); | 121 | struct dentry *apei_get_debugfs_dir(void); |
122 | 122 | ||
123 | #define apei_estatus_for_each_section(estatus, section) \ | 123 | #define apei_estatus_for_each_section(estatus, section) \ |
124 | for (section = (struct acpi_generic_data *)(estatus + 1); \ | 124 | for (section = (struct acpi_hest_generic_data *)(estatus + 1); \ |
125 | (void *)section - (void *)estatus < estatus->data_length; \ | 125 | (void *)section - (void *)estatus < estatus->data_length; \ |
126 | section = (void *)(section+1) + section->error_data_length) | 126 | section = (void *)(section+1) + section->error_data_length) |
127 | 127 | ||
128 | static inline u32 cper_estatus_len(struct acpi_generic_status *estatus) | 128 | static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus) |
129 | { | 129 | { |
130 | if (estatus->raw_data_length) | 130 | if (estatus->raw_data_length) |
131 | return estatus->raw_data_offset + \ | 131 | return estatus->raw_data_offset + \ |
@@ -135,9 +135,9 @@ static inline u32 cper_estatus_len(struct acpi_generic_status *estatus) | |||
135 | } | 135 | } |
136 | 136 | ||
137 | void cper_estatus_print(const char *pfx, | 137 | void cper_estatus_print(const char *pfx, |
138 | const struct acpi_generic_status *estatus); | 138 | const struct acpi_hest_generic_status *estatus); |
139 | int cper_estatus_check_header(const struct acpi_generic_status *estatus); | 139 | int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus); |
140 | int cper_estatus_check(const struct acpi_generic_status *estatus); | 140 | int cper_estatus_check(const struct acpi_hest_generic_status *estatus); |
141 | 141 | ||
142 | int apei_osc_setup(void); | 142 | int apei_osc_setup(void); |
143 | #endif | 143 | #endif |
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index dab7cb7349df..fc5f780bb61d 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -47,11 +47,11 @@ | |||
47 | #include <linux/genalloc.h> | 47 | #include <linux/genalloc.h> |
48 | #include <linux/pci.h> | 48 | #include <linux/pci.h> |
49 | #include <linux/aer.h> | 49 | #include <linux/aer.h> |
50 | #include <linux/nmi.h> | ||
50 | 51 | ||
51 | #include <acpi/ghes.h> | 52 | #include <acpi/ghes.h> |
52 | #include <asm/mce.h> | 53 | #include <acpi/apei.h> |
53 | #include <asm/tlbflush.h> | 54 | #include <asm/tlbflush.h> |
54 | #include <asm/nmi.h> | ||
55 | 55 | ||
56 | #include "apei-internal.h" | 56 | #include "apei-internal.h" |
57 | 57 | ||
@@ -74,20 +74,18 @@ | |||
74 | #define GHES_ESTATUS_CACHE_LEN(estatus_len) \ | 74 | #define GHES_ESTATUS_CACHE_LEN(estatus_len) \ |
75 | (sizeof(struct ghes_estatus_cache) + (estatus_len)) | 75 | (sizeof(struct ghes_estatus_cache) + (estatus_len)) |
76 | #define GHES_ESTATUS_FROM_CACHE(estatus_cache) \ | 76 | #define GHES_ESTATUS_FROM_CACHE(estatus_cache) \ |
77 | ((struct acpi_generic_status *) \ | 77 | ((struct acpi_hest_generic_status *) \ |
78 | ((struct ghes_estatus_cache *)(estatus_cache) + 1)) | 78 | ((struct ghes_estatus_cache *)(estatus_cache) + 1)) |
79 | 79 | ||
80 | #define GHES_ESTATUS_NODE_LEN(estatus_len) \ | 80 | #define GHES_ESTATUS_NODE_LEN(estatus_len) \ |
81 | (sizeof(struct ghes_estatus_node) + (estatus_len)) | 81 | (sizeof(struct ghes_estatus_node) + (estatus_len)) |
82 | #define GHES_ESTATUS_FROM_NODE(estatus_node) \ | 82 | #define GHES_ESTATUS_FROM_NODE(estatus_node) \ |
83 | ((struct acpi_generic_status *) \ | 83 | ((struct acpi_hest_generic_status *) \ |
84 | ((struct ghes_estatus_node *)(estatus_node) + 1)) | 84 | ((struct ghes_estatus_node *)(estatus_node) + 1)) |
85 | 85 | ||
86 | bool ghes_disable; | 86 | bool ghes_disable; |
87 | module_param_named(disable, ghes_disable, bool, 0); | 87 | module_param_named(disable, ghes_disable, bool, 0); |
88 | 88 | ||
89 | static int ghes_panic_timeout __read_mostly = 30; | ||
90 | |||
91 | /* | 89 | /* |
92 | * All error sources notified with SCI shares one notifier function, | 90 | * All error sources notified with SCI shares one notifier function, |
93 | * so they need to be linked and checked one by one. This is applied | 91 | * so they need to be linked and checked one by one. This is applied |
@@ -97,16 +95,9 @@ static int ghes_panic_timeout __read_mostly = 30; | |||
97 | * list changing, not for traversing. | 95 | * list changing, not for traversing. |
98 | */ | 96 | */ |
99 | static LIST_HEAD(ghes_sci); | 97 | static LIST_HEAD(ghes_sci); |
100 | static LIST_HEAD(ghes_nmi); | ||
101 | static DEFINE_MUTEX(ghes_list_mutex); | 98 | static DEFINE_MUTEX(ghes_list_mutex); |
102 | 99 | ||
103 | /* | 100 | /* |
104 | * NMI may be triggered on any CPU, so ghes_nmi_lock is used for | ||
105 | * mutual exclusion. | ||
106 | */ | ||
107 | static DEFINE_RAW_SPINLOCK(ghes_nmi_lock); | ||
108 | |||
109 | /* | ||
110 | * Because the memory area used to transfer hardware error information | 101 | * Because the memory area used to transfer hardware error information |
111 | * from BIOS to Linux can be determined only in NMI, IRQ or timer | 102 | * from BIOS to Linux can be determined only in NMI, IRQ or timer |
112 | * handler, but general ioremap can not be used in atomic context, so | 103 | * handler, but general ioremap can not be used in atomic context, so |
@@ -114,12 +105,16 @@ static DEFINE_RAW_SPINLOCK(ghes_nmi_lock); | |||
114 | */ | 105 | */ |
115 | 106 | ||
116 | /* | 107 | /* |
117 | * Two virtual pages are used, one for NMI context, the other for | 108 | * Two virtual pages are used, one for IRQ/PROCESS context, the other for |
118 | * IRQ/PROCESS context | 109 | * NMI context (optionally). |
119 | */ | 110 | */ |
120 | #define GHES_IOREMAP_PAGES 2 | 111 | #ifdef CONFIG_HAVE_ACPI_APEI_NMI |
121 | #define GHES_IOREMAP_NMI_PAGE(base) (base) | 112 | #define GHES_IOREMAP_PAGES 2 |
122 | #define GHES_IOREMAP_IRQ_PAGE(base) ((base) + PAGE_SIZE) | 113 | #else |
114 | #define GHES_IOREMAP_PAGES 1 | ||
115 | #endif | ||
116 | #define GHES_IOREMAP_IRQ_PAGE(base) (base) | ||
117 | #define GHES_IOREMAP_NMI_PAGE(base) ((base) + PAGE_SIZE) | ||
123 | 118 | ||
124 | /* virtual memory area for atomic ioremap */ | 119 | /* virtual memory area for atomic ioremap */ |
125 | static struct vm_struct *ghes_ioremap_area; | 120 | static struct vm_struct *ghes_ioremap_area; |
@@ -130,18 +125,8 @@ static struct vm_struct *ghes_ioremap_area; | |||
130 | static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi); | 125 | static DEFINE_RAW_SPINLOCK(ghes_ioremap_lock_nmi); |
131 | static DEFINE_SPINLOCK(ghes_ioremap_lock_irq); | 126 | static DEFINE_SPINLOCK(ghes_ioremap_lock_irq); |
132 | 127 | ||
133 | /* | ||
134 | * printk is not safe in NMI context. So in NMI handler, we allocate | ||
135 | * required memory from lock-less memory allocator | ||
136 | * (ghes_estatus_pool), save estatus into it, put them into lock-less | ||
137 | * list (ghes_estatus_llist), then delay printk into IRQ context via | ||
138 | * irq_work (ghes_proc_irq_work). ghes_estatus_size_request record | ||
139 | * required pool size by all NMI error source. | ||
140 | */ | ||
141 | static struct gen_pool *ghes_estatus_pool; | 128 | static struct gen_pool *ghes_estatus_pool; |
142 | static unsigned long ghes_estatus_pool_size_request; | 129 | static unsigned long ghes_estatus_pool_size_request; |
143 | static struct llist_head ghes_estatus_llist; | ||
144 | static struct irq_work ghes_proc_irq_work; | ||
145 | 130 | ||
146 | struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE]; | 131 | struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE]; |
147 | static atomic_t ghes_estatus_cache_alloced; | 132 | static atomic_t ghes_estatus_cache_alloced; |
@@ -192,7 +177,7 @@ static void ghes_iounmap_nmi(void __iomem *vaddr_ptr) | |||
192 | 177 | ||
193 | BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base)); | 178 | BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_NMI_PAGE(base)); |
194 | unmap_kernel_range_noflush(vaddr, PAGE_SIZE); | 179 | unmap_kernel_range_noflush(vaddr, PAGE_SIZE); |
195 | __flush_tlb_one(vaddr); | 180 | arch_apei_flush_tlb_one(vaddr); |
196 | } | 181 | } |
197 | 182 | ||
198 | static void ghes_iounmap_irq(void __iomem *vaddr_ptr) | 183 | static void ghes_iounmap_irq(void __iomem *vaddr_ptr) |
@@ -202,7 +187,7 @@ static void ghes_iounmap_irq(void __iomem *vaddr_ptr) | |||
202 | 187 | ||
203 | BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base)); | 188 | BUG_ON(vaddr != (unsigned long)GHES_IOREMAP_IRQ_PAGE(base)); |
204 | unmap_kernel_range_noflush(vaddr, PAGE_SIZE); | 189 | unmap_kernel_range_noflush(vaddr, PAGE_SIZE); |
205 | __flush_tlb_one(vaddr); | 190 | arch_apei_flush_tlb_one(vaddr); |
206 | } | 191 | } |
207 | 192 | ||
208 | static int ghes_estatus_pool_init(void) | 193 | static int ghes_estatus_pool_init(void) |
@@ -249,11 +234,6 @@ static int ghes_estatus_pool_expand(unsigned long len) | |||
249 | return 0; | 234 | return 0; |
250 | } | 235 | } |
251 | 236 | ||
252 | static void ghes_estatus_pool_shrink(unsigned long len) | ||
253 | { | ||
254 | ghes_estatus_pool_size_request -= PAGE_ALIGN(len); | ||
255 | } | ||
256 | |||
257 | static struct ghes *ghes_new(struct acpi_hest_generic *generic) | 237 | static struct ghes *ghes_new(struct acpi_hest_generic *generic) |
258 | { | 238 | { |
259 | struct ghes *ghes; | 239 | struct ghes *ghes; |
@@ -408,7 +388,7 @@ static void ghes_clear_estatus(struct ghes *ghes) | |||
408 | ghes->flags &= ~GHES_TO_CLEAR; | 388 | ghes->flags &= ~GHES_TO_CLEAR; |
409 | } | 389 | } |
410 | 390 | ||
411 | static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) | 391 | static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev) |
412 | { | 392 | { |
413 | #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE | 393 | #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE |
414 | unsigned long pfn; | 394 | unsigned long pfn; |
@@ -441,10 +421,10 @@ static void ghes_handle_memory_failure(struct acpi_generic_data *gdata, int sev) | |||
441 | } | 421 | } |
442 | 422 | ||
443 | static void ghes_do_proc(struct ghes *ghes, | 423 | static void ghes_do_proc(struct ghes *ghes, |
444 | const struct acpi_generic_status *estatus) | 424 | const struct acpi_hest_generic_status *estatus) |
445 | { | 425 | { |
446 | int sev, sec_sev; | 426 | int sev, sec_sev; |
447 | struct acpi_generic_data *gdata; | 427 | struct acpi_hest_generic_data *gdata; |
448 | 428 | ||
449 | sev = ghes_severity(estatus->error_severity); | 429 | sev = ghes_severity(estatus->error_severity); |
450 | apei_estatus_for_each_section(estatus, gdata) { | 430 | apei_estatus_for_each_section(estatus, gdata) { |
@@ -455,9 +435,7 @@ static void ghes_do_proc(struct ghes *ghes, | |||
455 | mem_err = (struct cper_sec_mem_err *)(gdata+1); | 435 | mem_err = (struct cper_sec_mem_err *)(gdata+1); |
456 | ghes_edac_report_mem_error(ghes, sev, mem_err); | 436 | ghes_edac_report_mem_error(ghes, sev, mem_err); |
457 | 437 | ||
458 | #ifdef CONFIG_X86_MCE | 438 | arch_apei_report_mem_error(sev, mem_err); |
459 | apei_mce_report_mem_error(sev, mem_err); | ||
460 | #endif | ||
461 | ghes_handle_memory_failure(gdata, sev); | 439 | ghes_handle_memory_failure(gdata, sev); |
462 | } | 440 | } |
463 | #ifdef CONFIG_ACPI_APEI_PCIEAER | 441 | #ifdef CONFIG_ACPI_APEI_PCIEAER |
@@ -498,7 +476,7 @@ static void ghes_do_proc(struct ghes *ghes, | |||
498 | 476 | ||
499 | static void __ghes_print_estatus(const char *pfx, | 477 | static void __ghes_print_estatus(const char *pfx, |
500 | const struct acpi_hest_generic *generic, | 478 | const struct acpi_hest_generic *generic, |
501 | const struct acpi_generic_status *estatus) | 479 | const struct acpi_hest_generic_status *estatus) |
502 | { | 480 | { |
503 | static atomic_t seqno; | 481 | static atomic_t seqno; |
504 | unsigned int curr_seqno; | 482 | unsigned int curr_seqno; |
@@ -520,7 +498,7 @@ static void __ghes_print_estatus(const char *pfx, | |||
520 | 498 | ||
521 | static int ghes_print_estatus(const char *pfx, | 499 | static int ghes_print_estatus(const char *pfx, |
522 | const struct acpi_hest_generic *generic, | 500 | const struct acpi_hest_generic *generic, |
523 | const struct acpi_generic_status *estatus) | 501 | const struct acpi_hest_generic_status *estatus) |
524 | { | 502 | { |
525 | /* Not more than 2 messages every 5 seconds */ | 503 | /* Not more than 2 messages every 5 seconds */ |
526 | static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); | 504 | static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); |
@@ -542,13 +520,13 @@ static int ghes_print_estatus(const char *pfx, | |||
542 | * GHES error status reporting throttle, to report more kinds of | 520 | * GHES error status reporting throttle, to report more kinds of |
543 | * errors, instead of just most frequently occurred errors. | 521 | * errors, instead of just most frequently occurred errors. |
544 | */ | 522 | */ |
545 | static int ghes_estatus_cached(struct acpi_generic_status *estatus) | 523 | static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus) |
546 | { | 524 | { |
547 | u32 len; | 525 | u32 len; |
548 | int i, cached = 0; | 526 | int i, cached = 0; |
549 | unsigned long long now; | 527 | unsigned long long now; |
550 | struct ghes_estatus_cache *cache; | 528 | struct ghes_estatus_cache *cache; |
551 | struct acpi_generic_status *cache_estatus; | 529 | struct acpi_hest_generic_status *cache_estatus; |
552 | 530 | ||
553 | len = cper_estatus_len(estatus); | 531 | len = cper_estatus_len(estatus); |
554 | rcu_read_lock(); | 532 | rcu_read_lock(); |
@@ -573,12 +551,12 @@ static int ghes_estatus_cached(struct acpi_generic_status *estatus) | |||
573 | 551 | ||
574 | static struct ghes_estatus_cache *ghes_estatus_cache_alloc( | 552 | static struct ghes_estatus_cache *ghes_estatus_cache_alloc( |
575 | struct acpi_hest_generic *generic, | 553 | struct acpi_hest_generic *generic, |
576 | struct acpi_generic_status *estatus) | 554 | struct acpi_hest_generic_status *estatus) |
577 | { | 555 | { |
578 | int alloced; | 556 | int alloced; |
579 | u32 len, cache_len; | 557 | u32 len, cache_len; |
580 | struct ghes_estatus_cache *cache; | 558 | struct ghes_estatus_cache *cache; |
581 | struct acpi_generic_status *cache_estatus; | 559 | struct acpi_hest_generic_status *cache_estatus; |
582 | 560 | ||
583 | alloced = atomic_add_return(1, &ghes_estatus_cache_alloced); | 561 | alloced = atomic_add_return(1, &ghes_estatus_cache_alloced); |
584 | if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) { | 562 | if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) { |
@@ -621,7 +599,7 @@ static void ghes_estatus_cache_rcu_free(struct rcu_head *head) | |||
621 | 599 | ||
622 | static void ghes_estatus_cache_add( | 600 | static void ghes_estatus_cache_add( |
623 | struct acpi_hest_generic *generic, | 601 | struct acpi_hest_generic *generic, |
624 | struct acpi_generic_status *estatus) | 602 | struct acpi_hest_generic_status *estatus) |
625 | { | 603 | { |
626 | int i, slot = -1, count; | 604 | int i, slot = -1, count; |
627 | unsigned long long now, duration, period, max_period = 0; | 605 | unsigned long long now, duration, period, max_period = 0; |
@@ -734,6 +712,32 @@ static int ghes_notify_sci(struct notifier_block *this, | |||
734 | return ret; | 712 | return ret; |
735 | } | 713 | } |
736 | 714 | ||
715 | static struct notifier_block ghes_notifier_sci = { | ||
716 | .notifier_call = ghes_notify_sci, | ||
717 | }; | ||
718 | |||
719 | #ifdef CONFIG_HAVE_ACPI_APEI_NMI | ||
720 | /* | ||
721 | * printk is not safe in NMI context. So in NMI handler, we allocate | ||
722 | * required memory from lock-less memory allocator | ||
723 | * (ghes_estatus_pool), save estatus into it, put them into lock-less | ||
724 | * list (ghes_estatus_llist), then delay printk into IRQ context via | ||
725 | * irq_work (ghes_proc_irq_work). ghes_estatus_size_request record | ||
726 | * required pool size by all NMI error source. | ||
727 | */ | ||
728 | static struct llist_head ghes_estatus_llist; | ||
729 | static struct irq_work ghes_proc_irq_work; | ||
730 | |||
731 | /* | ||
732 | * NMI may be triggered on any CPU, so ghes_nmi_lock is used for | ||
733 | * mutual exclusion. | ||
734 | */ | ||
735 | static DEFINE_RAW_SPINLOCK(ghes_nmi_lock); | ||
736 | |||
737 | static LIST_HEAD(ghes_nmi); | ||
738 | |||
739 | static int ghes_panic_timeout __read_mostly = 30; | ||
740 | |||
737 | static struct llist_node *llist_nodes_reverse(struct llist_node *llnode) | 741 | static struct llist_node *llist_nodes_reverse(struct llist_node *llnode) |
738 | { | 742 | { |
739 | struct llist_node *next, *tail = NULL; | 743 | struct llist_node *next, *tail = NULL; |
@@ -753,7 +757,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) | |||
753 | struct llist_node *llnode, *next; | 757 | struct llist_node *llnode, *next; |
754 | struct ghes_estatus_node *estatus_node; | 758 | struct ghes_estatus_node *estatus_node; |
755 | struct acpi_hest_generic *generic; | 759 | struct acpi_hest_generic *generic; |
756 | struct acpi_generic_status *estatus; | 760 | struct acpi_hest_generic_status *estatus; |
757 | u32 len, node_len; | 761 | u32 len, node_len; |
758 | 762 | ||
759 | llnode = llist_del_all(&ghes_estatus_llist); | 763 | llnode = llist_del_all(&ghes_estatus_llist); |
@@ -786,7 +790,7 @@ static void ghes_print_queued_estatus(void) | |||
786 | struct llist_node *llnode; | 790 | struct llist_node *llnode; |
787 | struct ghes_estatus_node *estatus_node; | 791 | struct ghes_estatus_node *estatus_node; |
788 | struct acpi_hest_generic *generic; | 792 | struct acpi_hest_generic *generic; |
789 | struct acpi_generic_status *estatus; | 793 | struct acpi_hest_generic_status *estatus; |
790 | u32 len, node_len; | 794 | u32 len, node_len; |
791 | 795 | ||
792 | llnode = llist_del_all(&ghes_estatus_llist); | 796 | llnode = llist_del_all(&ghes_estatus_llist); |
@@ -845,7 +849,7 @@ static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) | |||
845 | #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG | 849 | #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG |
846 | u32 len, node_len; | 850 | u32 len, node_len; |
847 | struct ghes_estatus_node *estatus_node; | 851 | struct ghes_estatus_node *estatus_node; |
848 | struct acpi_generic_status *estatus; | 852 | struct acpi_hest_generic_status *estatus; |
849 | #endif | 853 | #endif |
850 | if (!(ghes->flags & GHES_TO_CLEAR)) | 854 | if (!(ghes->flags & GHES_TO_CLEAR)) |
851 | continue; | 855 | continue; |
@@ -877,10 +881,6 @@ out: | |||
877 | return ret; | 881 | return ret; |
878 | } | 882 | } |
879 | 883 | ||
880 | static struct notifier_block ghes_notifier_sci = { | ||
881 | .notifier_call = ghes_notify_sci, | ||
882 | }; | ||
883 | |||
884 | static unsigned long ghes_esource_prealloc_size( | 884 | static unsigned long ghes_esource_prealloc_size( |
885 | const struct acpi_hest_generic *generic) | 885 | const struct acpi_hest_generic *generic) |
886 | { | 886 | { |
@@ -896,11 +896,71 @@ static unsigned long ghes_esource_prealloc_size( | |||
896 | return prealloc_size; | 896 | return prealloc_size; |
897 | } | 897 | } |
898 | 898 | ||
899 | static void ghes_estatus_pool_shrink(unsigned long len) | ||
900 | { | ||
901 | ghes_estatus_pool_size_request -= PAGE_ALIGN(len); | ||
902 | } | ||
903 | |||
904 | static void ghes_nmi_add(struct ghes *ghes) | ||
905 | { | ||
906 | unsigned long len; | ||
907 | |||
908 | len = ghes_esource_prealloc_size(ghes->generic); | ||
909 | ghes_estatus_pool_expand(len); | ||
910 | mutex_lock(&ghes_list_mutex); | ||
911 | if (list_empty(&ghes_nmi)) | ||
912 | register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0, "ghes"); | ||
913 | list_add_rcu(&ghes->list, &ghes_nmi); | ||
914 | mutex_unlock(&ghes_list_mutex); | ||
915 | } | ||
916 | |||
917 | static void ghes_nmi_remove(struct ghes *ghes) | ||
918 | { | ||
919 | unsigned long len; | ||
920 | |||
921 | mutex_lock(&ghes_list_mutex); | ||
922 | list_del_rcu(&ghes->list); | ||
923 | if (list_empty(&ghes_nmi)) | ||
924 | unregister_nmi_handler(NMI_LOCAL, "ghes"); | ||
925 | mutex_unlock(&ghes_list_mutex); | ||
926 | /* | ||
927 | * To synchronize with NMI handler, ghes can only be | ||
928 | * freed after NMI handler finishes. | ||
929 | */ | ||
930 | synchronize_rcu(); | ||
931 | len = ghes_esource_prealloc_size(ghes->generic); | ||
932 | ghes_estatus_pool_shrink(len); | ||
933 | } | ||
934 | |||
935 | static void ghes_nmi_init_cxt(void) | ||
936 | { | ||
937 | init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq); | ||
938 | } | ||
939 | #else /* CONFIG_HAVE_ACPI_APEI_NMI */ | ||
940 | static inline void ghes_nmi_add(struct ghes *ghes) | ||
941 | { | ||
942 | pr_err(GHES_PFX "ID: %d, trying to add NMI notification which is not supported!\n", | ||
943 | ghes->generic->header.source_id); | ||
944 | BUG(); | ||
945 | } | ||
946 | |||
947 | static inline void ghes_nmi_remove(struct ghes *ghes) | ||
948 | { | ||
949 | pr_err(GHES_PFX "ID: %d, trying to remove NMI notification which is not supported!\n", | ||
950 | ghes->generic->header.source_id); | ||
951 | BUG(); | ||
952 | } | ||
953 | |||
954 | static inline void ghes_nmi_init_cxt(void) | ||
955 | { | ||
956 | } | ||
957 | #endif /* CONFIG_HAVE_ACPI_APEI_NMI */ | ||
958 | |||
899 | static int ghes_probe(struct platform_device *ghes_dev) | 959 | static int ghes_probe(struct platform_device *ghes_dev) |
900 | { | 960 | { |
901 | struct acpi_hest_generic *generic; | 961 | struct acpi_hest_generic *generic; |
902 | struct ghes *ghes = NULL; | 962 | struct ghes *ghes = NULL; |
903 | unsigned long len; | 963 | |
904 | int rc = -EINVAL; | 964 | int rc = -EINVAL; |
905 | 965 | ||
906 | generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data; | 966 | generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data; |
@@ -911,7 +971,13 @@ static int ghes_probe(struct platform_device *ghes_dev) | |||
911 | case ACPI_HEST_NOTIFY_POLLED: | 971 | case ACPI_HEST_NOTIFY_POLLED: |
912 | case ACPI_HEST_NOTIFY_EXTERNAL: | 972 | case ACPI_HEST_NOTIFY_EXTERNAL: |
913 | case ACPI_HEST_NOTIFY_SCI: | 973 | case ACPI_HEST_NOTIFY_SCI: |
974 | break; | ||
914 | case ACPI_HEST_NOTIFY_NMI: | 975 | case ACPI_HEST_NOTIFY_NMI: |
976 | if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) { | ||
977 | pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n", | ||
978 | generic->header.source_id); | ||
979 | goto err; | ||
980 | } | ||
915 | break; | 981 | break; |
916 | case ACPI_HEST_NOTIFY_LOCAL: | 982 | case ACPI_HEST_NOTIFY_LOCAL: |
917 | pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n", | 983 | pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n", |
@@ -925,7 +991,7 @@ static int ghes_probe(struct platform_device *ghes_dev) | |||
925 | 991 | ||
926 | rc = -EIO; | 992 | rc = -EIO; |
927 | if (generic->error_block_length < | 993 | if (generic->error_block_length < |
928 | sizeof(struct acpi_generic_status)) { | 994 | sizeof(struct acpi_hest_generic_status)) { |
929 | pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n", | 995 | pr_warning(FW_BUG GHES_PFX "Invalid error block length: %u for generic hardware error source: %d\n", |
930 | generic->error_block_length, | 996 | generic->error_block_length, |
931 | generic->header.source_id); | 997 | generic->header.source_id); |
@@ -972,14 +1038,7 @@ static int ghes_probe(struct platform_device *ghes_dev) | |||
972 | mutex_unlock(&ghes_list_mutex); | 1038 | mutex_unlock(&ghes_list_mutex); |
973 | break; | 1039 | break; |
974 | case ACPI_HEST_NOTIFY_NMI: | 1040 | case ACPI_HEST_NOTIFY_NMI: |
975 | len = ghes_esource_prealloc_size(generic); | 1041 | ghes_nmi_add(ghes); |
976 | ghes_estatus_pool_expand(len); | ||
977 | mutex_lock(&ghes_list_mutex); | ||
978 | if (list_empty(&ghes_nmi)) | ||
979 | register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0, | ||
980 | "ghes"); | ||
981 | list_add_rcu(&ghes->list, &ghes_nmi); | ||
982 | mutex_unlock(&ghes_list_mutex); | ||
983 | break; | 1042 | break; |
984 | default: | 1043 | default: |
985 | BUG(); | 1044 | BUG(); |
@@ -1001,7 +1060,6 @@ static int ghes_remove(struct platform_device *ghes_dev) | |||
1001 | { | 1060 | { |
1002 | struct ghes *ghes; | 1061 | struct ghes *ghes; |
1003 | struct acpi_hest_generic *generic; | 1062 | struct acpi_hest_generic *generic; |
1004 | unsigned long len; | ||
1005 | 1063 | ||
1006 | ghes = platform_get_drvdata(ghes_dev); | 1064 | ghes = platform_get_drvdata(ghes_dev); |
1007 | generic = ghes->generic; | 1065 | generic = ghes->generic; |
@@ -1022,18 +1080,7 @@ static int ghes_remove(struct platform_device *ghes_dev) | |||
1022 | mutex_unlock(&ghes_list_mutex); | 1080 | mutex_unlock(&ghes_list_mutex); |
1023 | break; | 1081 | break; |
1024 | case ACPI_HEST_NOTIFY_NMI: | 1082 | case ACPI_HEST_NOTIFY_NMI: |
1025 | mutex_lock(&ghes_list_mutex); | 1083 | ghes_nmi_remove(ghes); |
1026 | list_del_rcu(&ghes->list); | ||
1027 | if (list_empty(&ghes_nmi)) | ||
1028 | unregister_nmi_handler(NMI_LOCAL, "ghes"); | ||
1029 | mutex_unlock(&ghes_list_mutex); | ||
1030 | /* | ||
1031 | * To synchronize with NMI handler, ghes can only be | ||
1032 | * freed after NMI handler finishes. | ||
1033 | */ | ||
1034 | synchronize_rcu(); | ||
1035 | len = ghes_esource_prealloc_size(generic); | ||
1036 | ghes_estatus_pool_shrink(len); | ||
1037 | break; | 1084 | break; |
1038 | default: | 1085 | default: |
1039 | BUG(); | 1086 | BUG(); |
@@ -1077,7 +1124,7 @@ static int __init ghes_init(void) | |||
1077 | return -EINVAL; | 1124 | return -EINVAL; |
1078 | } | 1125 | } |
1079 | 1126 | ||
1080 | init_irq_work(&ghes_proc_irq_work, ghes_proc_in_irq); | 1127 | ghes_nmi_init_cxt(); |
1081 | 1128 | ||
1082 | rc = ghes_ioremap_init(); | 1129 | rc = ghes_ioremap_init(); |
1083 | if (rc) | 1130 | if (rc) |
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index f5e37f32c71f..06e9b411a0a2 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/io.h> | 36 | #include <linux/io.h> |
37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
38 | #include <acpi/apei.h> | 38 | #include <acpi/apei.h> |
39 | #include <asm/mce.h> | ||
40 | 39 | ||
41 | #include "apei-internal.h" | 40 | #include "apei-internal.h" |
42 | 41 | ||
@@ -128,33 +127,7 @@ EXPORT_SYMBOL_GPL(apei_hest_parse); | |||
128 | */ | 127 | */ |
129 | static int __init hest_parse_cmc(struct acpi_hest_header *hest_hdr, void *data) | 128 | static int __init hest_parse_cmc(struct acpi_hest_header *hest_hdr, void *data) |
130 | { | 129 | { |
131 | #ifdef CONFIG_X86_MCE | 130 | return arch_apei_enable_cmcff(hest_hdr, data); |
132 | int i; | ||
133 | struct acpi_hest_ia_corrected *cmc; | ||
134 | struct acpi_hest_ia_error_bank *mc_bank; | ||
135 | |||
136 | if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK) | ||
137 | return 0; | ||
138 | |||
139 | cmc = (struct acpi_hest_ia_corrected *)hest_hdr; | ||
140 | if (!cmc->enabled) | ||
141 | return 0; | ||
142 | |||
143 | /* | ||
144 | * We expect HEST to provide a list of MC banks that report errors | ||
145 | * in firmware first mode. Otherwise, return non-zero value to | ||
146 | * indicate that we are done parsing HEST. | ||
147 | */ | ||
148 | if (!(cmc->flags & ACPI_HEST_FIRMWARE_FIRST) || !cmc->num_hardware_banks) | ||
149 | return 1; | ||
150 | |||
151 | pr_info(HEST_PFX "Enabling Firmware First mode for corrected errors.\n"); | ||
152 | |||
153 | mc_bank = (struct acpi_hest_ia_error_bank *)(cmc + 1); | ||
154 | for (i = 0; i < cmc->num_hardware_banks; i++, mc_bank++) | ||
155 | mce_disable_bank(mc_bank->bank_number); | ||
156 | #endif | ||
157 | return 1; | ||
158 | } | 131 | } |
159 | 132 | ||
160 | struct ghes_arr { | 133 | struct ghes_arr { |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 0d7116f34b95..48bcf38a0ea8 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -534,6 +534,20 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
534 | " invalid.\n"); | 534 | " invalid.\n"); |
535 | } | 535 | } |
536 | 536 | ||
537 | /* | ||
538 | * When fully charged, some batteries wrongly report | ||
539 | * capacity_now = design_capacity instead of = full_charge_capacity | ||
540 | */ | ||
541 | if (battery->capacity_now > battery->full_charge_capacity | ||
542 | && battery->full_charge_capacity != ACPI_BATTERY_VALUE_UNKNOWN) { | ||
543 | battery->capacity_now = battery->full_charge_capacity; | ||
544 | if (battery->capacity_now != battery->design_capacity) | ||
545 | printk_once(KERN_WARNING FW_BUG | ||
546 | "battery: reported current charge level (%d) " | ||
547 | "is higher than reported maximum charge level (%d).\n", | ||
548 | battery->capacity_now, battery->full_charge_capacity); | ||
549 | } | ||
550 | |||
537 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) | 551 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) |
538 | && battery->capacity_now >= 0 && battery->capacity_now <= 100) | 552 | && battery->capacity_now >= 0 && battery->capacity_now <= 100) |
539 | battery->capacity_now = (battery->capacity_now * | 553 | battery->capacity_now = (battery->capacity_now * |
@@ -1151,6 +1165,28 @@ static struct dmi_system_id bat_dmi_table[] = { | |||
1151 | {}, | 1165 | {}, |
1152 | }; | 1166 | }; |
1153 | 1167 | ||
1168 | /* | ||
1169 | * Some machines'(E,G Lenovo Z480) ECs are not stable | ||
1170 | * during boot up and this causes battery driver fails to be | ||
1171 | * probed due to failure of getting battery information | ||
1172 | * from EC sometimes. After several retries, the operation | ||
1173 | * may work. So add retry code here and 20ms sleep between | ||
1174 | * every retries. | ||
1175 | */ | ||
1176 | static int acpi_battery_update_retry(struct acpi_battery *battery) | ||
1177 | { | ||
1178 | int retry, ret; | ||
1179 | |||
1180 | for (retry = 5; retry; retry--) { | ||
1181 | ret = acpi_battery_update(battery, false); | ||
1182 | if (!ret) | ||
1183 | break; | ||
1184 | |||
1185 | msleep(20); | ||
1186 | } | ||
1187 | return ret; | ||
1188 | } | ||
1189 | |||
1154 | static int acpi_battery_add(struct acpi_device *device) | 1190 | static int acpi_battery_add(struct acpi_device *device) |
1155 | { | 1191 | { |
1156 | int result = 0; | 1192 | int result = 0; |
@@ -1169,9 +1205,11 @@ static int acpi_battery_add(struct acpi_device *device) | |||
1169 | mutex_init(&battery->sysfs_lock); | 1205 | mutex_init(&battery->sysfs_lock); |
1170 | if (acpi_has_method(battery->device->handle, "_BIX")) | 1206 | if (acpi_has_method(battery->device->handle, "_BIX")) |
1171 | set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); | 1207 | set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); |
1172 | result = acpi_battery_update(battery, false); | 1208 | |
1209 | result = acpi_battery_update_retry(battery); | ||
1173 | if (result) | 1210 | if (result) |
1174 | goto fail; | 1211 | goto fail; |
1212 | |||
1175 | #ifdef CONFIG_ACPI_PROCFS_POWER | 1213 | #ifdef CONFIG_ACPI_PROCFS_POWER |
1176 | result = acpi_battery_add_fs(device); | 1214 | result = acpi_battery_add_fs(device); |
1177 | #endif | 1215 | #endif |
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 3d8413d02a97..36eb42e3b0bb 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c | |||
@@ -247,75 +247,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { | |||
247 | }, | 247 | }, |
248 | 248 | ||
249 | /* | 249 | /* |
250 | * The following machines have broken backlight support when reporting | 250 | * These machines will power on immediately after shutdown when |
251 | * the Windows 2012 OSI, so disable it until their support is fixed. | 251 | * reporting the Windows 2012 OSI. |
252 | */ | 252 | */ |
253 | { | 253 | { |
254 | .callback = dmi_disable_osi_win8, | 254 | .callback = dmi_disable_osi_win8, |
255 | .ident = "ASUS Zenbook Prime UX31A", | ||
256 | .matches = { | ||
257 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
258 | DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"), | ||
259 | }, | ||
260 | }, | ||
261 | { | ||
262 | .callback = dmi_disable_osi_win8, | ||
263 | .ident = "ThinkPad Edge E530", | ||
264 | .matches = { | ||
265 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
266 | DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), | ||
267 | }, | ||
268 | }, | ||
269 | { | ||
270 | .callback = dmi_disable_osi_win8, | ||
271 | .ident = "ThinkPad Edge E530", | ||
272 | .matches = { | ||
273 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
274 | DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), | ||
275 | }, | ||
276 | }, | ||
277 | { | ||
278 | .callback = dmi_disable_osi_win8, | ||
279 | .ident = "ThinkPad Edge E530", | ||
280 | .matches = { | ||
281 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
282 | DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), | ||
283 | }, | ||
284 | }, | ||
285 | { | ||
286 | .callback = dmi_disable_osi_win8, | ||
287 | .ident = "Acer Aspire V5-573G", | ||
288 | .matches = { | ||
289 | DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), | ||
290 | DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), | ||
291 | }, | ||
292 | }, | ||
293 | { | ||
294 | .callback = dmi_disable_osi_win8, | ||
295 | .ident = "Acer Aspire V5-572G", | ||
296 | .matches = { | ||
297 | DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), | ||
298 | DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), | ||
299 | }, | ||
300 | }, | ||
301 | { | ||
302 | .callback = dmi_disable_osi_win8, | ||
303 | .ident = "ThinkPad T431s", | ||
304 | .matches = { | ||
305 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
306 | DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), | ||
307 | }, | ||
308 | }, | ||
309 | { | ||
310 | .callback = dmi_disable_osi_win8, | ||
311 | .ident = "ThinkPad T430", | ||
312 | .matches = { | ||
313 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
314 | DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), | ||
315 | }, | ||
316 | }, | ||
317 | { | ||
318 | .callback = dmi_disable_osi_win8, | ||
319 | .ident = "Dell Inspiron 7737", | 255 | .ident = "Dell Inspiron 7737", |
320 | .matches = { | 256 | .matches = { |
321 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 257 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c5bc8cfe09fa..8581f5b84f48 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -477,9 +477,6 @@ static int __init acpi_bus_init_irq(void) | |||
477 | return 0; | 477 | return 0; |
478 | } | 478 | } |
479 | 479 | ||
480 | u8 acpi_gbl_permanent_mmap; | ||
481 | |||
482 | |||
483 | void __init acpi_early_init(void) | 480 | void __init acpi_early_init(void) |
484 | { | 481 | { |
485 | acpi_status status; | 482 | acpi_status status; |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index db35594d4df7..6d5d1832a588 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -79,11 +79,13 @@ static int acpi_button_remove(struct acpi_device *device); | |||
79 | static void acpi_button_notify(struct acpi_device *device, u32 event); | 79 | static void acpi_button_notify(struct acpi_device *device, u32 event); |
80 | 80 | ||
81 | #ifdef CONFIG_PM_SLEEP | 81 | #ifdef CONFIG_PM_SLEEP |
82 | static int acpi_button_suspend(struct device *dev); | ||
82 | static int acpi_button_resume(struct device *dev); | 83 | static int acpi_button_resume(struct device *dev); |
83 | #else | 84 | #else |
85 | #define acpi_button_suspend NULL | ||
84 | #define acpi_button_resume NULL | 86 | #define acpi_button_resume NULL |
85 | #endif | 87 | #endif |
86 | static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume); | 88 | static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume); |
87 | 89 | ||
88 | static struct acpi_driver acpi_button_driver = { | 90 | static struct acpi_driver acpi_button_driver = { |
89 | .name = "button", | 91 | .name = "button", |
@@ -102,6 +104,7 @@ struct acpi_button { | |||
102 | struct input_dev *input; | 104 | struct input_dev *input; |
103 | char phys[32]; /* for input device */ | 105 | char phys[32]; /* for input device */ |
104 | unsigned long pushed; | 106 | unsigned long pushed; |
107 | bool suspended; | ||
105 | }; | 108 | }; |
106 | 109 | ||
107 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); | 110 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); |
@@ -293,15 +296,19 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) | |||
293 | if (button->type == ACPI_BUTTON_TYPE_LID) { | 296 | if (button->type == ACPI_BUTTON_TYPE_LID) { |
294 | acpi_lid_send_state(device); | 297 | acpi_lid_send_state(device); |
295 | } else { | 298 | } else { |
296 | int keycode = test_bit(KEY_SLEEP, input->keybit) ? | 299 | int keycode; |
297 | KEY_SLEEP : KEY_POWER; | 300 | |
301 | pm_wakeup_event(&device->dev, 0); | ||
302 | if (button->suspended) | ||
303 | break; | ||
298 | 304 | ||
305 | keycode = test_bit(KEY_SLEEP, input->keybit) ? | ||
306 | KEY_SLEEP : KEY_POWER; | ||
299 | input_report_key(input, keycode, 1); | 307 | input_report_key(input, keycode, 1); |
300 | input_sync(input); | 308 | input_sync(input); |
301 | input_report_key(input, keycode, 0); | 309 | input_report_key(input, keycode, 0); |
302 | input_sync(input); | 310 | input_sync(input); |
303 | 311 | ||
304 | pm_wakeup_event(&device->dev, 0); | ||
305 | acpi_bus_generate_netlink_event( | 312 | acpi_bus_generate_netlink_event( |
306 | device->pnp.device_class, | 313 | device->pnp.device_class, |
307 | dev_name(&device->dev), | 314 | dev_name(&device->dev), |
@@ -316,11 +323,21 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) | |||
316 | } | 323 | } |
317 | 324 | ||
318 | #ifdef CONFIG_PM_SLEEP | 325 | #ifdef CONFIG_PM_SLEEP |
326 | static int acpi_button_suspend(struct device *dev) | ||
327 | { | ||
328 | struct acpi_device *device = to_acpi_device(dev); | ||
329 | struct acpi_button *button = acpi_driver_data(device); | ||
330 | |||
331 | button->suspended = true; | ||
332 | return 0; | ||
333 | } | ||
334 | |||
319 | static int acpi_button_resume(struct device *dev) | 335 | static int acpi_button_resume(struct device *dev) |
320 | { | 336 | { |
321 | struct acpi_device *device = to_acpi_device(dev); | 337 | struct acpi_device *device = to_acpi_device(dev); |
322 | struct acpi_button *button = acpi_driver_data(device); | 338 | struct acpi_button *button = acpi_driver_data(device); |
323 | 339 | ||
340 | button->suspended = false; | ||
324 | if (button->type == ACPI_BUTTON_TYPE_LID) | 341 | if (button->type == ACPI_BUTTON_TYPE_LID) |
325 | return acpi_lid_send_state(device); | 342 | return acpi_lid_send_state(device); |
326 | return 0; | 343 | return 0; |
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 49a51277f81d..67075f800e34 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
@@ -367,29 +367,61 @@ EXPORT_SYMBOL(acpi_bus_power_manageable); | |||
367 | #ifdef CONFIG_PM | 367 | #ifdef CONFIG_PM |
368 | static DEFINE_MUTEX(acpi_pm_notifier_lock); | 368 | static DEFINE_MUTEX(acpi_pm_notifier_lock); |
369 | 369 | ||
370 | static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used) | ||
371 | { | ||
372 | struct acpi_device *adev; | ||
373 | |||
374 | if (val != ACPI_NOTIFY_DEVICE_WAKE) | ||
375 | return; | ||
376 | |||
377 | adev = acpi_bus_get_acpi_device(handle); | ||
378 | if (!adev) | ||
379 | return; | ||
380 | |||
381 | mutex_lock(&acpi_pm_notifier_lock); | ||
382 | |||
383 | if (adev->wakeup.flags.notifier_present) { | ||
384 | __pm_wakeup_event(adev->wakeup.ws, 0); | ||
385 | if (adev->wakeup.context.work.func) | ||
386 | queue_pm_work(&adev->wakeup.context.work); | ||
387 | } | ||
388 | |||
389 | mutex_unlock(&acpi_pm_notifier_lock); | ||
390 | |||
391 | acpi_bus_put_acpi_device(adev); | ||
392 | } | ||
393 | |||
370 | /** | 394 | /** |
371 | * acpi_add_pm_notifier - Register PM notifier for given ACPI device. | 395 | * acpi_add_pm_notifier - Register PM notify handler for given ACPI device. |
372 | * @adev: ACPI device to add the notifier for. | 396 | * @adev: ACPI device to add the notify handler for. |
373 | * @context: Context information to pass to the notifier routine. | 397 | * @dev: Device to generate a wakeup event for while handling the notification. |
398 | * @work_func: Work function to execute when handling the notification. | ||
374 | * | 399 | * |
375 | * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of | 400 | * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of |
376 | * PM wakeup events. For example, wakeup events may be generated for bridges | 401 | * PM wakeup events. For example, wakeup events may be generated for bridges |
377 | * if one of the devices below the bridge is signaling wakeup, even if the | 402 | * if one of the devices below the bridge is signaling wakeup, even if the |
378 | * bridge itself doesn't have a wakeup GPE associated with it. | 403 | * bridge itself doesn't have a wakeup GPE associated with it. |
379 | */ | 404 | */ |
380 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, | 405 | acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev, |
381 | acpi_notify_handler handler, void *context) | 406 | void (*work_func)(struct work_struct *work)) |
382 | { | 407 | { |
383 | acpi_status status = AE_ALREADY_EXISTS; | 408 | acpi_status status = AE_ALREADY_EXISTS; |
384 | 409 | ||
410 | if (!dev && !work_func) | ||
411 | return AE_BAD_PARAMETER; | ||
412 | |||
385 | mutex_lock(&acpi_pm_notifier_lock); | 413 | mutex_lock(&acpi_pm_notifier_lock); |
386 | 414 | ||
387 | if (adev->wakeup.flags.notifier_present) | 415 | if (adev->wakeup.flags.notifier_present) |
388 | goto out; | 416 | goto out; |
389 | 417 | ||
390 | status = acpi_install_notify_handler(adev->handle, | 418 | adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev)); |
391 | ACPI_SYSTEM_NOTIFY, | 419 | adev->wakeup.context.dev = dev; |
392 | handler, context); | 420 | if (work_func) |
421 | INIT_WORK(&adev->wakeup.context.work, work_func); | ||
422 | |||
423 | status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY, | ||
424 | acpi_pm_notify_handler, NULL); | ||
393 | if (ACPI_FAILURE(status)) | 425 | if (ACPI_FAILURE(status)) |
394 | goto out; | 426 | goto out; |
395 | 427 | ||
@@ -404,8 +436,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, | |||
404 | * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. | 436 | * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. |
405 | * @adev: ACPI device to remove the notifier from. | 437 | * @adev: ACPI device to remove the notifier from. |
406 | */ | 438 | */ |
407 | acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, | 439 | acpi_status acpi_remove_pm_notifier(struct acpi_device *adev) |
408 | acpi_notify_handler handler) | ||
409 | { | 440 | { |
410 | acpi_status status = AE_BAD_PARAMETER; | 441 | acpi_status status = AE_BAD_PARAMETER; |
411 | 442 | ||
@@ -416,10 +447,17 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, | |||
416 | 447 | ||
417 | status = acpi_remove_notify_handler(adev->handle, | 448 | status = acpi_remove_notify_handler(adev->handle, |
418 | ACPI_SYSTEM_NOTIFY, | 449 | ACPI_SYSTEM_NOTIFY, |
419 | handler); | 450 | acpi_pm_notify_handler); |
420 | if (ACPI_FAILURE(status)) | 451 | if (ACPI_FAILURE(status)) |
421 | goto out; | 452 | goto out; |
422 | 453 | ||
454 | if (adev->wakeup.context.work.func) { | ||
455 | cancel_work_sync(&adev->wakeup.context.work); | ||
456 | adev->wakeup.context.work.func = NULL; | ||
457 | } | ||
458 | adev->wakeup.context.dev = NULL; | ||
459 | wakeup_source_unregister(adev->wakeup.ws); | ||
460 | |||
423 | adev->wakeup.flags.notifier_present = false; | 461 | adev->wakeup.flags.notifier_present = false; |
424 | 462 | ||
425 | out: | 463 | out: |
@@ -558,7 +596,6 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, | |||
558 | */ | 596 | */ |
559 | int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) | 597 | int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) |
560 | { | 598 | { |
561 | acpi_handle handle = ACPI_HANDLE(dev); | ||
562 | struct acpi_device *adev; | 599 | struct acpi_device *adev; |
563 | int ret, d_min, d_max; | 600 | int ret, d_min, d_max; |
564 | 601 | ||
@@ -573,8 +610,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) | |||
573 | d_max_in = ACPI_STATE_D3_HOT; | 610 | d_max_in = ACPI_STATE_D3_HOT; |
574 | } | 611 | } |
575 | 612 | ||
576 | if (!handle || acpi_bus_get_device(handle, &adev)) { | 613 | adev = ACPI_COMPANION(dev); |
577 | dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); | 614 | if (!adev) { |
615 | dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); | ||
578 | return -ENODEV; | 616 | return -ENODEV; |
579 | } | 617 | } |
580 | 618 | ||
@@ -600,26 +638,25 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in) | |||
600 | } | 638 | } |
601 | EXPORT_SYMBOL(acpi_pm_device_sleep_state); | 639 | EXPORT_SYMBOL(acpi_pm_device_sleep_state); |
602 | 640 | ||
603 | #ifdef CONFIG_PM_RUNTIME | ||
604 | /** | 641 | /** |
605 | * acpi_wakeup_device - Wakeup notification handler for ACPI devices. | 642 | * acpi_pm_notify_work_func - ACPI devices wakeup notification work function. |
606 | * @handle: ACPI handle of the device the notification is for. | 643 | * @work: Work item to handle. |
607 | * @event: Type of the signaled event. | ||
608 | * @context: Device corresponding to @handle. | ||
609 | */ | 644 | */ |
610 | static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) | 645 | static void acpi_pm_notify_work_func(struct work_struct *work) |
611 | { | 646 | { |
612 | struct device *dev = context; | 647 | struct device *dev; |
613 | 648 | ||
614 | if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) { | 649 | dev = container_of(work, struct acpi_device_wakeup_context, work)->dev; |
650 | if (dev) { | ||
615 | pm_wakeup_event(dev, 0); | 651 | pm_wakeup_event(dev, 0); |
616 | pm_runtime_resume(dev); | 652 | pm_runtime_resume(dev); |
617 | } | 653 | } |
618 | } | 654 | } |
619 | 655 | ||
620 | /** | 656 | /** |
621 | * __acpi_device_run_wake - Enable/disable runtime remote wakeup for device. | 657 | * acpi_device_wakeup - Enable/disable wakeup functionality for device. |
622 | * @adev: ACPI device to enable/disable the remote wakeup for. | 658 | * @adev: ACPI device to enable/disable wakeup functionality for. |
659 | * @target_state: State the system is transitioning into. | ||
623 | * @enable: Whether to enable or disable the wakeup functionality. | 660 | * @enable: Whether to enable or disable the wakeup functionality. |
624 | * | 661 | * |
625 | * Enable/disable the GPE associated with @adev so that it can generate | 662 | * Enable/disable the GPE associated with @adev so that it can generate |
@@ -629,7 +666,8 @@ static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) | |||
629 | * Callers must ensure that @adev is a valid ACPI device node before executing | 666 | * Callers must ensure that @adev is a valid ACPI device node before executing |
630 | * this function. | 667 | * this function. |
631 | */ | 668 | */ |
632 | int __acpi_device_run_wake(struct acpi_device *adev, bool enable) | 669 | static int acpi_device_wakeup(struct acpi_device *adev, u32 target_state, |
670 | bool enable) | ||
633 | { | 671 | { |
634 | struct acpi_device_wakeup *wakeup = &adev->wakeup; | 672 | struct acpi_device_wakeup *wakeup = &adev->wakeup; |
635 | 673 | ||
@@ -637,7 +675,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) | |||
637 | acpi_status res; | 675 | acpi_status res; |
638 | int error; | 676 | int error; |
639 | 677 | ||
640 | error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0); | 678 | error = acpi_enable_wakeup_device_power(adev, target_state); |
641 | if (error) | 679 | if (error) |
642 | return error; | 680 | return error; |
643 | 681 | ||
@@ -653,6 +691,7 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) | |||
653 | return 0; | 691 | return 0; |
654 | } | 692 | } |
655 | 693 | ||
694 | #ifdef CONFIG_PM_RUNTIME | ||
656 | /** | 695 | /** |
657 | * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. | 696 | * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. |
658 | * @dev: Device to enable/disable the platform to wake up. | 697 | * @dev: Device to enable/disable the platform to wake up. |
@@ -661,63 +700,42 @@ int __acpi_device_run_wake(struct acpi_device *adev, bool enable) | |||
661 | int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) | 700 | int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) |
662 | { | 701 | { |
663 | struct acpi_device *adev; | 702 | struct acpi_device *adev; |
664 | acpi_handle handle; | ||
665 | 703 | ||
666 | if (!device_run_wake(phys_dev)) | 704 | if (!device_run_wake(phys_dev)) |
667 | return -EINVAL; | 705 | return -EINVAL; |
668 | 706 | ||
669 | handle = ACPI_HANDLE(phys_dev); | 707 | adev = ACPI_COMPANION(phys_dev); |
670 | if (!handle || acpi_bus_get_device(handle, &adev)) { | 708 | if (!adev) { |
671 | dev_dbg(phys_dev, "ACPI handle without context in %s!\n", | 709 | dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__); |
672 | __func__); | ||
673 | return -ENODEV; | 710 | return -ENODEV; |
674 | } | 711 | } |
675 | 712 | ||
676 | return __acpi_device_run_wake(adev, enable); | 713 | return acpi_device_wakeup(adev, enable, ACPI_STATE_S0); |
677 | } | 714 | } |
678 | EXPORT_SYMBOL(acpi_pm_device_run_wake); | 715 | EXPORT_SYMBOL(acpi_pm_device_run_wake); |
679 | #else | ||
680 | static inline void acpi_wakeup_device(acpi_handle handle, u32 event, | ||
681 | void *context) {} | ||
682 | #endif /* CONFIG_PM_RUNTIME */ | 716 | #endif /* CONFIG_PM_RUNTIME */ |
683 | 717 | ||
684 | #ifdef CONFIG_PM_SLEEP | 718 | #ifdef CONFIG_PM_SLEEP |
685 | /** | 719 | /** |
686 | * __acpi_device_sleep_wake - Enable or disable device to wake up the system. | ||
687 | * @dev: Device to enable/desible to wake up the system. | ||
688 | * @target_state: System state the device is supposed to wake up from. | ||
689 | * @enable: Whether to enable or disable @dev to wake up the system. | ||
690 | */ | ||
691 | int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state, | ||
692 | bool enable) | ||
693 | { | ||
694 | return enable ? | ||
695 | acpi_enable_wakeup_device_power(adev, target_state) : | ||
696 | acpi_disable_wakeup_device_power(adev); | ||
697 | } | ||
698 | |||
699 | /** | ||
700 | * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system. | 720 | * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system. |
701 | * @dev: Device to enable/desible to wake up the system from sleep states. | 721 | * @dev: Device to enable/desible to wake up the system from sleep states. |
702 | * @enable: Whether to enable or disable @dev to wake up the system. | 722 | * @enable: Whether to enable or disable @dev to wake up the system. |
703 | */ | 723 | */ |
704 | int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | 724 | int acpi_pm_device_sleep_wake(struct device *dev, bool enable) |
705 | { | 725 | { |
706 | acpi_handle handle; | ||
707 | struct acpi_device *adev; | 726 | struct acpi_device *adev; |
708 | int error; | 727 | int error; |
709 | 728 | ||
710 | if (!device_can_wakeup(dev)) | 729 | if (!device_can_wakeup(dev)) |
711 | return -EINVAL; | 730 | return -EINVAL; |
712 | 731 | ||
713 | handle = ACPI_HANDLE(dev); | 732 | adev = ACPI_COMPANION(dev); |
714 | if (!handle || acpi_bus_get_device(handle, &adev)) { | 733 | if (!adev) { |
715 | dev_dbg(dev, "ACPI handle without context in %s!\n", __func__); | 734 | dev_dbg(dev, "ACPI companion missing in %s!\n", __func__); |
716 | return -ENODEV; | 735 | return -ENODEV; |
717 | } | 736 | } |
718 | 737 | ||
719 | error = __acpi_device_sleep_wake(adev, acpi_target_system_state(), | 738 | error = acpi_device_wakeup(adev, acpi_target_system_state(), enable); |
720 | enable); | ||
721 | if (!error) | 739 | if (!error) |
722 | dev_info(dev, "System wakeup %s by ACPI\n", | 740 | dev_info(dev, "System wakeup %s by ACPI\n", |
723 | enable ? "enabled" : "disabled"); | 741 | enable ? "enabled" : "disabled"); |
@@ -775,13 +793,13 @@ int acpi_dev_runtime_suspend(struct device *dev) | |||
775 | 793 | ||
776 | remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) > | 794 | remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) > |
777 | PM_QOS_FLAGS_NONE; | 795 | PM_QOS_FLAGS_NONE; |
778 | error = __acpi_device_run_wake(adev, remote_wakeup); | 796 | error = acpi_device_wakeup(adev, ACPI_STATE_S0, remote_wakeup); |
779 | if (remote_wakeup && error) | 797 | if (remote_wakeup && error) |
780 | return -EAGAIN; | 798 | return -EAGAIN; |
781 | 799 | ||
782 | error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); | 800 | error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); |
783 | if (error) | 801 | if (error) |
784 | __acpi_device_run_wake(adev, false); | 802 | acpi_device_wakeup(adev, ACPI_STATE_S0, false); |
785 | 803 | ||
786 | return error; | 804 | return error; |
787 | } | 805 | } |
@@ -804,7 +822,7 @@ int acpi_dev_runtime_resume(struct device *dev) | |||
804 | return 0; | 822 | return 0; |
805 | 823 | ||
806 | error = acpi_dev_pm_full_power(adev); | 824 | error = acpi_dev_pm_full_power(adev); |
807 | __acpi_device_run_wake(adev, false); | 825 | acpi_device_wakeup(adev, ACPI_STATE_S0, false); |
808 | return error; | 826 | return error; |
809 | } | 827 | } |
810 | EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume); | 828 | EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume); |
@@ -860,13 +878,13 @@ int acpi_dev_suspend_late(struct device *dev) | |||
860 | 878 | ||
861 | target_state = acpi_target_system_state(); | 879 | target_state = acpi_target_system_state(); |
862 | wakeup = device_may_wakeup(dev); | 880 | wakeup = device_may_wakeup(dev); |
863 | error = __acpi_device_sleep_wake(adev, target_state, wakeup); | 881 | error = acpi_device_wakeup(adev, target_state, wakeup); |
864 | if (wakeup && error) | 882 | if (wakeup && error) |
865 | return error; | 883 | return error; |
866 | 884 | ||
867 | error = acpi_dev_pm_low_power(dev, adev, target_state); | 885 | error = acpi_dev_pm_low_power(dev, adev, target_state); |
868 | if (error) | 886 | if (error) |
869 | __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); | 887 | acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false); |
870 | 888 | ||
871 | return error; | 889 | return error; |
872 | } | 890 | } |
@@ -889,7 +907,7 @@ int acpi_dev_resume_early(struct device *dev) | |||
889 | return 0; | 907 | return 0; |
890 | 908 | ||
891 | error = acpi_dev_pm_full_power(adev); | 909 | error = acpi_dev_pm_full_power(adev); |
892 | __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); | 910 | acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false); |
893 | return error; | 911 | return error; |
894 | } | 912 | } |
895 | EXPORT_SYMBOL_GPL(acpi_dev_resume_early); | 913 | EXPORT_SYMBOL_GPL(acpi_dev_resume_early); |
@@ -1048,11 +1066,11 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) | |||
1048 | if (dev->pm_domain) | 1066 | if (dev->pm_domain) |
1049 | return -EEXIST; | 1067 | return -EEXIST; |
1050 | 1068 | ||
1051 | acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); | 1069 | acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); |
1052 | dev->pm_domain = &acpi_general_pm_domain; | 1070 | dev->pm_domain = &acpi_general_pm_domain; |
1053 | if (power_on) { | 1071 | if (power_on) { |
1054 | acpi_dev_pm_full_power(adev); | 1072 | acpi_dev_pm_full_power(adev); |
1055 | __acpi_device_run_wake(adev, false); | 1073 | acpi_device_wakeup(adev, ACPI_STATE_S0, false); |
1056 | } | 1074 | } |
1057 | return 0; | 1075 | return 0; |
1058 | } | 1076 | } |
@@ -1076,7 +1094,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) | |||
1076 | 1094 | ||
1077 | if (adev && dev->pm_domain == &acpi_general_pm_domain) { | 1095 | if (adev && dev->pm_domain == &acpi_general_pm_domain) { |
1078 | dev->pm_domain = NULL; | 1096 | dev->pm_domain = NULL; |
1079 | acpi_remove_pm_notifier(adev, acpi_wakeup_device); | 1097 | acpi_remove_pm_notifier(adev); |
1080 | if (power_off) { | 1098 | if (power_off) { |
1081 | /* | 1099 | /* |
1082 | * If the device's PM QoS resume latency limit or flags | 1100 | * If the device's PM QoS resume latency limit or flags |
@@ -1086,7 +1104,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off) | |||
1086 | */ | 1104 | */ |
1087 | dev_pm_qos_hide_latency_limit(dev); | 1105 | dev_pm_qos_hide_latency_limit(dev); |
1088 | dev_pm_qos_hide_flags(dev); | 1106 | dev_pm_qos_hide_flags(dev); |
1089 | __acpi_device_run_wake(adev, false); | 1107 | acpi_device_wakeup(adev, ACPI_STATE_S0, false); |
1090 | acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); | 1108 | acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0); |
1091 | } | 1109 | } |
1092 | } | 1110 | } |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ad11ba4a412d..a66ab658abbc 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -1,11 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * ec.c - ACPI Embedded Controller Driver (v2.1) | 2 | * ec.c - ACPI Embedded Controller Driver (v2.2) |
3 | * | 3 | * |
4 | * Copyright (C) 2006-2008 Alexey Starikovskiy <astarikovskiy@suse.de> | 4 | * Copyright (C) 2001-2014 Intel Corporation |
5 | * Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com> | 5 | * Author: 2014 Lv Zheng <lv.zheng@intel.com> |
6 | * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> | 6 | * 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> |
7 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | 7 | * 2006 Denis Sadykov <denis.m.sadykov@intel.com> |
8 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 8 | * 2004 Luming Yu <luming.yu@intel.com> |
9 | * 2001, 2002 Andy Grover <andrew.grover@intel.com> | ||
10 | * 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | ||
11 | * Copyright (C) 2008 Alexey Starikovskiy <astarikovskiy@suse.de> | ||
9 | * | 12 | * |
10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 13 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
11 | * | 14 | * |
@@ -52,6 +55,7 @@ | |||
52 | /* EC status register */ | 55 | /* EC status register */ |
53 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ | 56 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ |
54 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ | 57 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ |
58 | #define ACPI_EC_FLAG_CMD 0x08 /* Input buffer contains a command */ | ||
55 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ | 59 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ |
56 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ | 60 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ |
57 | 61 | ||
@@ -78,6 +82,9 @@ enum { | |||
78 | EC_FLAGS_BLOCKED, /* Transactions are blocked */ | 82 | EC_FLAGS_BLOCKED, /* Transactions are blocked */ |
79 | }; | 83 | }; |
80 | 84 | ||
85 | #define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */ | ||
86 | #define ACPI_EC_COMMAND_COMPLETE 0x02 /* Completed last byte */ | ||
87 | |||
81 | /* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */ | 88 | /* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */ |
82 | static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; | 89 | static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; |
83 | module_param(ec_delay, uint, 0644); | 90 | module_param(ec_delay, uint, 0644); |
@@ -109,7 +116,7 @@ struct transaction { | |||
109 | u8 ri; | 116 | u8 ri; |
110 | u8 wlen; | 117 | u8 wlen; |
111 | u8 rlen; | 118 | u8 rlen; |
112 | bool done; | 119 | u8 flags; |
113 | }; | 120 | }; |
114 | 121 | ||
115 | struct acpi_ec *boot_ec, *first_ec; | 122 | struct acpi_ec *boot_ec, *first_ec; |
@@ -127,83 +134,104 @@ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ | |||
127 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) | 134 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) |
128 | { | 135 | { |
129 | u8 x = inb(ec->command_addr); | 136 | u8 x = inb(ec->command_addr); |
130 | pr_debug("---> status = 0x%2.2x\n", x); | 137 | pr_debug("EC_SC(R) = 0x%2.2x " |
138 | "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n", | ||
139 | x, | ||
140 | !!(x & ACPI_EC_FLAG_SCI), | ||
141 | !!(x & ACPI_EC_FLAG_BURST), | ||
142 | !!(x & ACPI_EC_FLAG_CMD), | ||
143 | !!(x & ACPI_EC_FLAG_IBF), | ||
144 | !!(x & ACPI_EC_FLAG_OBF)); | ||
131 | return x; | 145 | return x; |
132 | } | 146 | } |
133 | 147 | ||
134 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) | 148 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) |
135 | { | 149 | { |
136 | u8 x = inb(ec->data_addr); | 150 | u8 x = inb(ec->data_addr); |
137 | pr_debug("---> data = 0x%2.2x\n", x); | 151 | pr_debug("EC_DATA(R) = 0x%2.2x\n", x); |
138 | return x; | 152 | return x; |
139 | } | 153 | } |
140 | 154 | ||
141 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) | 155 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) |
142 | { | 156 | { |
143 | pr_debug("<--- command = 0x%2.2x\n", command); | 157 | pr_debug("EC_SC(W) = 0x%2.2x\n", command); |
144 | outb(command, ec->command_addr); | 158 | outb(command, ec->command_addr); |
145 | } | 159 | } |
146 | 160 | ||
147 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) | 161 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) |
148 | { | 162 | { |
149 | pr_debug("<--- data = 0x%2.2x\n", data); | 163 | pr_debug("EC_DATA(W) = 0x%2.2x\n", data); |
150 | outb(data, ec->data_addr); | 164 | outb(data, ec->data_addr); |
151 | } | 165 | } |
152 | 166 | ||
153 | static int ec_transaction_done(struct acpi_ec *ec) | 167 | static int ec_transaction_completed(struct acpi_ec *ec) |
154 | { | 168 | { |
155 | unsigned long flags; | 169 | unsigned long flags; |
156 | int ret = 0; | 170 | int ret = 0; |
157 | spin_lock_irqsave(&ec->lock, flags); | 171 | spin_lock_irqsave(&ec->lock, flags); |
158 | if (!ec->curr || ec->curr->done) | 172 | if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE)) |
159 | ret = 1; | 173 | ret = 1; |
160 | spin_unlock_irqrestore(&ec->lock, flags); | 174 | spin_unlock_irqrestore(&ec->lock, flags); |
161 | return ret; | 175 | return ret; |
162 | } | 176 | } |
163 | 177 | ||
164 | static void start_transaction(struct acpi_ec *ec) | 178 | static bool advance_transaction(struct acpi_ec *ec) |
165 | { | 179 | { |
166 | ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0; | ||
167 | ec->curr->done = false; | ||
168 | acpi_ec_write_cmd(ec, ec->curr->command); | ||
169 | } | ||
170 | |||
171 | static void advance_transaction(struct acpi_ec *ec, u8 status) | ||
172 | { | ||
173 | unsigned long flags; | ||
174 | struct transaction *t; | 180 | struct transaction *t; |
181 | u8 status; | ||
182 | bool wakeup = false; | ||
175 | 183 | ||
176 | spin_lock_irqsave(&ec->lock, flags); | 184 | pr_debug("===== %s =====\n", in_interrupt() ? "IRQ" : "TASK"); |
185 | status = acpi_ec_read_status(ec); | ||
177 | t = ec->curr; | 186 | t = ec->curr; |
178 | if (!t) | 187 | if (!t) |
179 | goto unlock; | 188 | goto err; |
180 | if (t->wlen > t->wi) { | 189 | if (t->flags & ACPI_EC_COMMAND_POLL) { |
181 | if ((status & ACPI_EC_FLAG_IBF) == 0) | 190 | if (t->wlen > t->wi) { |
182 | acpi_ec_write_data(ec, | 191 | if ((status & ACPI_EC_FLAG_IBF) == 0) |
183 | t->wdata[t->wi++]); | 192 | acpi_ec_write_data(ec, t->wdata[t->wi++]); |
184 | else | 193 | else |
185 | goto err; | 194 | goto err; |
186 | } else if (t->rlen > t->ri) { | 195 | } else if (t->rlen > t->ri) { |
187 | if ((status & ACPI_EC_FLAG_OBF) == 1) { | 196 | if ((status & ACPI_EC_FLAG_OBF) == 1) { |
188 | t->rdata[t->ri++] = acpi_ec_read_data(ec); | 197 | t->rdata[t->ri++] = acpi_ec_read_data(ec); |
189 | if (t->rlen == t->ri) | 198 | if (t->rlen == t->ri) { |
190 | t->done = true; | 199 | t->flags |= ACPI_EC_COMMAND_COMPLETE; |
200 | wakeup = true; | ||
201 | } | ||
202 | } else | ||
203 | goto err; | ||
204 | } else if (t->wlen == t->wi && | ||
205 | (status & ACPI_EC_FLAG_IBF) == 0) { | ||
206 | t->flags |= ACPI_EC_COMMAND_COMPLETE; | ||
207 | wakeup = true; | ||
208 | } | ||
209 | return wakeup; | ||
210 | } else { | ||
211 | if ((status & ACPI_EC_FLAG_IBF) == 0) { | ||
212 | acpi_ec_write_cmd(ec, t->command); | ||
213 | t->flags |= ACPI_EC_COMMAND_POLL; | ||
191 | } else | 214 | } else |
192 | goto err; | 215 | goto err; |
193 | } else if (t->wlen == t->wi && | 216 | return wakeup; |
194 | (status & ACPI_EC_FLAG_IBF) == 0) | 217 | } |
195 | t->done = true; | ||
196 | goto unlock; | ||
197 | err: | 218 | err: |
198 | /* | 219 | /* |
199 | * If SCI bit is set, then don't think it's a false IRQ | 220 | * If SCI bit is set, then don't think it's a false IRQ |
200 | * otherwise will take a not handled IRQ as a false one. | 221 | * otherwise will take a not handled IRQ as a false one. |
201 | */ | 222 | */ |
202 | if (in_interrupt() && !(status & ACPI_EC_FLAG_SCI)) | 223 | if (!(status & ACPI_EC_FLAG_SCI)) { |
203 | ++t->irq_count; | 224 | if (in_interrupt() && t) |
225 | ++t->irq_count; | ||
226 | } | ||
227 | return wakeup; | ||
228 | } | ||
204 | 229 | ||
205 | unlock: | 230 | static void start_transaction(struct acpi_ec *ec) |
206 | spin_unlock_irqrestore(&ec->lock, flags); | 231 | { |
232 | ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0; | ||
233 | ec->curr->flags = 0; | ||
234 | (void)advance_transaction(ec); | ||
207 | } | 235 | } |
208 | 236 | ||
209 | static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data); | 237 | static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data); |
@@ -228,15 +256,17 @@ static int ec_poll(struct acpi_ec *ec) | |||
228 | /* don't sleep with disabled interrupts */ | 256 | /* don't sleep with disabled interrupts */ |
229 | if (EC_FLAGS_MSI || irqs_disabled()) { | 257 | if (EC_FLAGS_MSI || irqs_disabled()) { |
230 | udelay(ACPI_EC_MSI_UDELAY); | 258 | udelay(ACPI_EC_MSI_UDELAY); |
231 | if (ec_transaction_done(ec)) | 259 | if (ec_transaction_completed(ec)) |
232 | return 0; | 260 | return 0; |
233 | } else { | 261 | } else { |
234 | if (wait_event_timeout(ec->wait, | 262 | if (wait_event_timeout(ec->wait, |
235 | ec_transaction_done(ec), | 263 | ec_transaction_completed(ec), |
236 | msecs_to_jiffies(1))) | 264 | msecs_to_jiffies(1))) |
237 | return 0; | 265 | return 0; |
238 | } | 266 | } |
239 | advance_transaction(ec, acpi_ec_read_status(ec)); | 267 | spin_lock_irqsave(&ec->lock, flags); |
268 | (void)advance_transaction(ec); | ||
269 | spin_unlock_irqrestore(&ec->lock, flags); | ||
240 | } while (time_before(jiffies, delay)); | 270 | } while (time_before(jiffies, delay)); |
241 | pr_debug("controller reset, restart transaction\n"); | 271 | pr_debug("controller reset, restart transaction\n"); |
242 | spin_lock_irqsave(&ec->lock, flags); | 272 | spin_lock_irqsave(&ec->lock, flags); |
@@ -268,23 +298,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
268 | return ret; | 298 | return ret; |
269 | } | 299 | } |
270 | 300 | ||
271 | static int ec_check_ibf0(struct acpi_ec *ec) | ||
272 | { | ||
273 | u8 status = acpi_ec_read_status(ec); | ||
274 | return (status & ACPI_EC_FLAG_IBF) == 0; | ||
275 | } | ||
276 | |||
277 | static int ec_wait_ibf0(struct acpi_ec *ec) | ||
278 | { | ||
279 | unsigned long delay = jiffies + msecs_to_jiffies(ec_delay); | ||
280 | /* interrupt wait manually if GPE mode is not active */ | ||
281 | while (time_before(jiffies, delay)) | ||
282 | if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), | ||
283 | msecs_to_jiffies(1))) | ||
284 | return 0; | ||
285 | return -ETIME; | ||
286 | } | ||
287 | |||
288 | static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | 301 | static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) |
289 | { | 302 | { |
290 | int status; | 303 | int status; |
@@ -305,12 +318,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | |||
305 | goto unlock; | 318 | goto unlock; |
306 | } | 319 | } |
307 | } | 320 | } |
308 | if (ec_wait_ibf0(ec)) { | ||
309 | pr_err("input buffer is not empty, " | ||
310 | "aborting transaction\n"); | ||
311 | status = -ETIME; | ||
312 | goto end; | ||
313 | } | ||
314 | pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n", | 321 | pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n", |
315 | t->command, t->wdata ? t->wdata[0] : 0); | 322 | t->command, t->wdata ? t->wdata[0] : 0); |
316 | /* disable GPE during transaction if storm is detected */ | 323 | /* disable GPE during transaction if storm is detected */ |
@@ -334,7 +341,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | |||
334 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); | 341 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); |
335 | } | 342 | } |
336 | pr_debug("transaction end\n"); | 343 | pr_debug("transaction end\n"); |
337 | end: | ||
338 | if (ec->global_lock) | 344 | if (ec->global_lock) |
339 | acpi_release_global_lock(glk); | 345 | acpi_release_global_lock(glk); |
340 | unlock: | 346 | unlock: |
@@ -634,17 +640,14 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) | |||
634 | static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, | 640 | static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, |
635 | u32 gpe_number, void *data) | 641 | u32 gpe_number, void *data) |
636 | { | 642 | { |
643 | unsigned long flags; | ||
637 | struct acpi_ec *ec = data; | 644 | struct acpi_ec *ec = data; |
638 | u8 status = acpi_ec_read_status(ec); | ||
639 | 645 | ||
640 | pr_debug("~~~> interrupt, status:0x%02x\n", status); | 646 | spin_lock_irqsave(&ec->lock, flags); |
641 | 647 | if (advance_transaction(ec)) | |
642 | advance_transaction(ec, status); | ||
643 | if (ec_transaction_done(ec) && | ||
644 | (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { | ||
645 | wake_up(&ec->wait); | 648 | wake_up(&ec->wait); |
646 | ec_check_sci(ec, acpi_ec_read_status(ec)); | 649 | spin_unlock_irqrestore(&ec->lock, flags); |
647 | } | 650 | ec_check_sci(ec, acpi_ec_read_status(ec)); |
648 | return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE; | 651 | return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE; |
649 | } | 652 | } |
650 | 653 | ||
@@ -1066,8 +1069,10 @@ int __init acpi_ec_ecdt_probe(void) | |||
1066 | /* fall through */ | 1069 | /* fall through */ |
1067 | } | 1070 | } |
1068 | 1071 | ||
1069 | if (EC_FLAGS_SKIP_DSDT_SCAN) | 1072 | if (EC_FLAGS_SKIP_DSDT_SCAN) { |
1073 | kfree(saved_ec); | ||
1070 | return -ENODEV; | 1074 | return -ENODEV; |
1075 | } | ||
1071 | 1076 | ||
1072 | /* This workaround is needed only on some broken machines, | 1077 | /* This workaround is needed only on some broken machines, |
1073 | * which require early EC, but fail to provide ECDT */ | 1078 | * which require early EC, but fail to provide ECDT */ |
@@ -1105,6 +1110,7 @@ install: | |||
1105 | } | 1110 | } |
1106 | error: | 1111 | error: |
1107 | kfree(boot_ec); | 1112 | kfree(boot_ec); |
1113 | kfree(saved_ec); | ||
1108 | boot_ec = NULL; | 1114 | boot_ec = NULL; |
1109 | return -ENODEV; | 1115 | return -ENODEV; |
1110 | } | 1116 | } |
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 7de5b603f272..4c5cf77e7576 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -84,8 +84,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
84 | int type, unsigned long long sta); | 84 | int type, unsigned long long sta); |
85 | void acpi_device_add_finalize(struct acpi_device *device); | 85 | void acpi_device_add_finalize(struct acpi_device *device); |
86 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); | 86 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp); |
87 | int acpi_bind_one(struct device *dev, struct acpi_device *adev); | ||
88 | int acpi_unbind_one(struct device *dev); | ||
89 | bool acpi_device_is_present(struct acpi_device *adev); | 87 | bool acpi_device_is_present(struct acpi_device *adev); |
90 | bool acpi_device_is_battery(struct acpi_device *adev); | 88 | bool acpi_device_is_battery(struct acpi_device *adev); |
91 | 89 | ||
@@ -108,7 +106,12 @@ int acpi_power_transition(struct acpi_device *device, int state); | |||
108 | int acpi_device_update_power(struct acpi_device *device, int *state_p); | 106 | int acpi_device_update_power(struct acpi_device *device, int *state_p); |
109 | 107 | ||
110 | int acpi_wakeup_device_init(void); | 108 | int acpi_wakeup_device_init(void); |
109 | |||
110 | #ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC | ||
111 | void acpi_early_processor_set_pdc(void); | 111 | void acpi_early_processor_set_pdc(void); |
112 | #else | ||
113 | static inline void acpi_early_processor_set_pdc(void) {} | ||
114 | #endif | ||
112 | 115 | ||
113 | /* -------------------------------------------------------------------------- | 116 | /* -------------------------------------------------------------------------- |
114 | Embedded Controller | 117 | Embedded Controller |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index bad25b070fe0..3abe9b223ba7 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -259,12 +259,14 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) | |||
259 | "System description tables not found\n"); | 259 | "System description tables not found\n"); |
260 | return 0; | 260 | return 0; |
261 | } | 261 | } |
262 | } else { | 262 | } else if (IS_ENABLED(CONFIG_ACPI_LEGACY_TABLES_LOOKUP)) { |
263 | acpi_physical_address pa = 0; | 263 | acpi_physical_address pa = 0; |
264 | 264 | ||
265 | acpi_find_root_pointer(&pa); | 265 | acpi_find_root_pointer(&pa); |
266 | return pa; | 266 | return pa; |
267 | } | 267 | } |
268 | |||
269 | return 0; | ||
268 | } | 270 | } |
269 | 271 | ||
270 | /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ | 272 | /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */ |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index d388f13d48b4..e6ae603ed1a1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -593,7 +593,7 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
593 | if (no_aspm) | 593 | if (no_aspm) |
594 | pcie_no_aspm(); | 594 | pcie_no_aspm(); |
595 | 595 | ||
596 | pci_acpi_add_bus_pm_notifier(device, root->bus); | 596 | pci_acpi_add_bus_pm_notifier(device); |
597 | if (device->wakeup.flags.run_wake) | 597 | if (device->wakeup.flags.run_wake) |
598 | device_set_run_wake(root->bus->bridge, true); | 598 | device_set_run_wake(root->bus->bridge, true); |
599 | 599 | ||
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 71e2065639a6..e32321ce9a5c 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -4,17 +4,11 @@ | |||
4 | * | 4 | * |
5 | * Alex Chiang <achiang@hp.com> | 5 | * Alex Chiang <achiang@hp.com> |
6 | * - Unified x86/ia64 implementations | 6 | * - Unified x86/ia64 implementations |
7 | * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> | ||
8 | * - Added _PDC for platforms with Intel CPUs | ||
9 | */ | 7 | */ |
10 | #include <linux/export.h> | 8 | #include <linux/export.h> |
11 | #include <linux/dmi.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/acpi.h> | 9 | #include <linux/acpi.h> |
14 | #include <acpi/processor.h> | 10 | #include <acpi/processor.h> |
15 | 11 | ||
16 | #include "internal.h" | ||
17 | |||
18 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 12 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
19 | ACPI_MODULE_NAME("processor_core"); | 13 | ACPI_MODULE_NAME("processor_core"); |
20 | 14 | ||
@@ -135,6 +129,8 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) | |||
135 | map_lapic_id(header, acpi_id, &apic_id); | 129 | map_lapic_id(header, acpi_id, &apic_id); |
136 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { | 130 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { |
137 | map_lsapic_id(header, type, acpi_id, &apic_id); | 131 | map_lsapic_id(header, type, acpi_id, &apic_id); |
132 | } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) { | ||
133 | map_x2apic_id(header, type, acpi_id, &apic_id); | ||
138 | } | 134 | } |
139 | 135 | ||
140 | exit: | 136 | exit: |
@@ -208,195 +204,3 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) | |||
208 | return acpi_map_cpuid(apic_id, acpi_id); | 204 | return acpi_map_cpuid(apic_id, acpi_id); |
209 | } | 205 | } |
210 | EXPORT_SYMBOL_GPL(acpi_get_cpuid); | 206 | EXPORT_SYMBOL_GPL(acpi_get_cpuid); |
211 | |||
212 | static bool __init processor_physically_present(acpi_handle handle) | ||
213 | { | ||
214 | int cpuid, type; | ||
215 | u32 acpi_id; | ||
216 | acpi_status status; | ||
217 | acpi_object_type acpi_type; | ||
218 | unsigned long long tmp; | ||
219 | union acpi_object object = { 0 }; | ||
220 | struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; | ||
221 | |||
222 | status = acpi_get_type(handle, &acpi_type); | ||
223 | if (ACPI_FAILURE(status)) | ||
224 | return false; | ||
225 | |||
226 | switch (acpi_type) { | ||
227 | case ACPI_TYPE_PROCESSOR: | ||
228 | status = acpi_evaluate_object(handle, NULL, NULL, &buffer); | ||
229 | if (ACPI_FAILURE(status)) | ||
230 | return false; | ||
231 | acpi_id = object.processor.proc_id; | ||
232 | break; | ||
233 | case ACPI_TYPE_DEVICE: | ||
234 | status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp); | ||
235 | if (ACPI_FAILURE(status)) | ||
236 | return false; | ||
237 | acpi_id = tmp; | ||
238 | break; | ||
239 | default: | ||
240 | return false; | ||
241 | } | ||
242 | |||
243 | type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; | ||
244 | cpuid = acpi_get_cpuid(handle, type, acpi_id); | ||
245 | |||
246 | if (cpuid == -1) | ||
247 | return false; | ||
248 | |||
249 | return true; | ||
250 | } | ||
251 | |||
252 | static void acpi_set_pdc_bits(u32 *buf) | ||
253 | { | ||
254 | buf[0] = ACPI_PDC_REVISION_ID; | ||
255 | buf[1] = 1; | ||
256 | |||
257 | /* Enable coordination with firmware's _TSD info */ | ||
258 | buf[2] = ACPI_PDC_SMP_T_SWCOORD; | ||
259 | |||
260 | /* Twiddle arch-specific bits needed for _PDC */ | ||
261 | arch_acpi_set_pdc_bits(buf); | ||
262 | } | ||
263 | |||
264 | static struct acpi_object_list *acpi_processor_alloc_pdc(void) | ||
265 | { | ||
266 | struct acpi_object_list *obj_list; | ||
267 | union acpi_object *obj; | ||
268 | u32 *buf; | ||
269 | |||
270 | /* allocate and initialize pdc. It will be used later. */ | ||
271 | obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); | ||
272 | if (!obj_list) { | ||
273 | printk(KERN_ERR "Memory allocation error\n"); | ||
274 | return NULL; | ||
275 | } | ||
276 | |||
277 | obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); | ||
278 | if (!obj) { | ||
279 | printk(KERN_ERR "Memory allocation error\n"); | ||
280 | kfree(obj_list); | ||
281 | return NULL; | ||
282 | } | ||
283 | |||
284 | buf = kmalloc(12, GFP_KERNEL); | ||
285 | if (!buf) { | ||
286 | printk(KERN_ERR "Memory allocation error\n"); | ||
287 | kfree(obj); | ||
288 | kfree(obj_list); | ||
289 | return NULL; | ||
290 | } | ||
291 | |||
292 | acpi_set_pdc_bits(buf); | ||
293 | |||
294 | obj->type = ACPI_TYPE_BUFFER; | ||
295 | obj->buffer.length = 12; | ||
296 | obj->buffer.pointer = (u8 *) buf; | ||
297 | obj_list->count = 1; | ||
298 | obj_list->pointer = obj; | ||
299 | |||
300 | return obj_list; | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * _PDC is required for a BIOS-OS handshake for most of the newer | ||
305 | * ACPI processor features. | ||
306 | */ | ||
307 | static acpi_status | ||
308 | acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) | ||
309 | { | ||
310 | acpi_status status = AE_OK; | ||
311 | |||
312 | if (boot_option_idle_override == IDLE_NOMWAIT) { | ||
313 | /* | ||
314 | * If mwait is disabled for CPU C-states, the C2C3_FFH access | ||
315 | * mode will be disabled in the parameter of _PDC object. | ||
316 | * Of course C1_FFH access mode will also be disabled. | ||
317 | */ | ||
318 | union acpi_object *obj; | ||
319 | u32 *buffer = NULL; | ||
320 | |||
321 | obj = pdc_in->pointer; | ||
322 | buffer = (u32 *)(obj->buffer.pointer); | ||
323 | buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); | ||
324 | |||
325 | } | ||
326 | status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); | ||
327 | |||
328 | if (ACPI_FAILURE(status)) | ||
329 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
330 | "Could not evaluate _PDC, using legacy perf. control.\n")); | ||
331 | |||
332 | return status; | ||
333 | } | ||
334 | |||
335 | void acpi_processor_set_pdc(acpi_handle handle) | ||
336 | { | ||
337 | struct acpi_object_list *obj_list; | ||
338 | |||
339 | if (arch_has_acpi_pdc() == false) | ||
340 | return; | ||
341 | |||
342 | obj_list = acpi_processor_alloc_pdc(); | ||
343 | if (!obj_list) | ||
344 | return; | ||
345 | |||
346 | acpi_processor_eval_pdc(handle, obj_list); | ||
347 | |||
348 | kfree(obj_list->pointer->buffer.pointer); | ||
349 | kfree(obj_list->pointer); | ||
350 | kfree(obj_list); | ||
351 | } | ||
352 | |||
353 | static acpi_status __init | ||
354 | early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
355 | { | ||
356 | if (processor_physically_present(handle) == false) | ||
357 | return AE_OK; | ||
358 | |||
359 | acpi_processor_set_pdc(handle); | ||
360 | return AE_OK; | ||
361 | } | ||
362 | |||
363 | #if defined(CONFIG_X86) || defined(CONFIG_IA64) | ||
364 | static int __init set_no_mwait(const struct dmi_system_id *id) | ||
365 | { | ||
366 | pr_notice(PREFIX "%s detected - disabling mwait for CPU C-states\n", | ||
367 | id->ident); | ||
368 | boot_option_idle_override = IDLE_NOMWAIT; | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | static struct dmi_system_id processor_idle_dmi_table[] __initdata = { | ||
373 | { | ||
374 | set_no_mwait, "Extensa 5220", { | ||
375 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), | ||
376 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
377 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), | ||
378 | DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, | ||
379 | {}, | ||
380 | }; | ||
381 | |||
382 | static void __init processor_dmi_check(void) | ||
383 | { | ||
384 | /* | ||
385 | * Check whether the system is DMI table. If yes, OSPM | ||
386 | * should not use mwait for CPU-states. | ||
387 | */ | ||
388 | dmi_check_system(processor_idle_dmi_table); | ||
389 | } | ||
390 | #else | ||
391 | static inline void processor_dmi_check(void) {} | ||
392 | #endif | ||
393 | |||
394 | void __init acpi_early_processor_set_pdc(void) | ||
395 | { | ||
396 | processor_dmi_check(); | ||
397 | |||
398 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, | ||
399 | ACPI_UINT32_MAX, | ||
400 | early_init_pdc, NULL, NULL, NULL); | ||
401 | acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL); | ||
402 | } | ||
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c new file mode 100644 index 000000000000..e5dd80800930 --- /dev/null +++ b/drivers/acpi/processor_pdc.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Intel Corporation | ||
3 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. | ||
4 | * | ||
5 | * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> | ||
6 | * - Added _PDC for platforms with Intel CPUs | ||
7 | */ | ||
8 | |||
9 | #define pr_fmt(fmt) "ACPI: " fmt | ||
10 | |||
11 | #include <linux/dmi.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/acpi.h> | ||
14 | #include <acpi/processor.h> | ||
15 | |||
16 | #include "internal.h" | ||
17 | |||
18 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | ||
19 | ACPI_MODULE_NAME("processor_pdc"); | ||
20 | |||
21 | static bool __init processor_physically_present(acpi_handle handle) | ||
22 | { | ||
23 | int cpuid, type; | ||
24 | u32 acpi_id; | ||
25 | acpi_status status; | ||
26 | acpi_object_type acpi_type; | ||
27 | unsigned long long tmp; | ||
28 | union acpi_object object = { 0 }; | ||
29 | struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; | ||
30 | |||
31 | status = acpi_get_type(handle, &acpi_type); | ||
32 | if (ACPI_FAILURE(status)) | ||
33 | return false; | ||
34 | |||
35 | switch (acpi_type) { | ||
36 | case ACPI_TYPE_PROCESSOR: | ||
37 | status = acpi_evaluate_object(handle, NULL, NULL, &buffer); | ||
38 | if (ACPI_FAILURE(status)) | ||
39 | return false; | ||
40 | acpi_id = object.processor.proc_id; | ||
41 | break; | ||
42 | case ACPI_TYPE_DEVICE: | ||
43 | status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp); | ||
44 | if (ACPI_FAILURE(status)) | ||
45 | return false; | ||
46 | acpi_id = tmp; | ||
47 | break; | ||
48 | default: | ||
49 | return false; | ||
50 | } | ||
51 | |||
52 | type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; | ||
53 | cpuid = acpi_get_cpuid(handle, type, acpi_id); | ||
54 | |||
55 | if (cpuid == -1) | ||
56 | return false; | ||
57 | |||
58 | return true; | ||
59 | } | ||
60 | |||
61 | static void acpi_set_pdc_bits(u32 *buf) | ||
62 | { | ||
63 | buf[0] = ACPI_PDC_REVISION_ID; | ||
64 | buf[1] = 1; | ||
65 | |||
66 | /* Enable coordination with firmware's _TSD info */ | ||
67 | buf[2] = ACPI_PDC_SMP_T_SWCOORD; | ||
68 | |||
69 | /* Twiddle arch-specific bits needed for _PDC */ | ||
70 | arch_acpi_set_pdc_bits(buf); | ||
71 | } | ||
72 | |||
73 | static struct acpi_object_list *acpi_processor_alloc_pdc(void) | ||
74 | { | ||
75 | struct acpi_object_list *obj_list; | ||
76 | union acpi_object *obj; | ||
77 | u32 *buf; | ||
78 | |||
79 | /* allocate and initialize pdc. It will be used later. */ | ||
80 | obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); | ||
81 | if (!obj_list) | ||
82 | goto out; | ||
83 | |||
84 | obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); | ||
85 | if (!obj) { | ||
86 | kfree(obj_list); | ||
87 | goto out; | ||
88 | } | ||
89 | |||
90 | buf = kmalloc(12, GFP_KERNEL); | ||
91 | if (!buf) { | ||
92 | kfree(obj); | ||
93 | kfree(obj_list); | ||
94 | goto out; | ||
95 | } | ||
96 | |||
97 | acpi_set_pdc_bits(buf); | ||
98 | |||
99 | obj->type = ACPI_TYPE_BUFFER; | ||
100 | obj->buffer.length = 12; | ||
101 | obj->buffer.pointer = (u8 *) buf; | ||
102 | obj_list->count = 1; | ||
103 | obj_list->pointer = obj; | ||
104 | |||
105 | return obj_list; | ||
106 | out: | ||
107 | pr_err("Memory allocation error\n"); | ||
108 | return NULL; | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * _PDC is required for a BIOS-OS handshake for most of the newer | ||
113 | * ACPI processor features. | ||
114 | */ | ||
115 | static acpi_status | ||
116 | acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) | ||
117 | { | ||
118 | acpi_status status = AE_OK; | ||
119 | |||
120 | if (boot_option_idle_override == IDLE_NOMWAIT) { | ||
121 | /* | ||
122 | * If mwait is disabled for CPU C-states, the C2C3_FFH access | ||
123 | * mode will be disabled in the parameter of _PDC object. | ||
124 | * Of course C1_FFH access mode will also be disabled. | ||
125 | */ | ||
126 | union acpi_object *obj; | ||
127 | u32 *buffer = NULL; | ||
128 | |||
129 | obj = pdc_in->pointer; | ||
130 | buffer = (u32 *)(obj->buffer.pointer); | ||
131 | buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); | ||
132 | |||
133 | } | ||
134 | status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); | ||
135 | |||
136 | if (ACPI_FAILURE(status)) | ||
137 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
138 | "Could not evaluate _PDC, using legacy perf. control.\n")); | ||
139 | |||
140 | return status; | ||
141 | } | ||
142 | |||
143 | void acpi_processor_set_pdc(acpi_handle handle) | ||
144 | { | ||
145 | struct acpi_object_list *obj_list; | ||
146 | |||
147 | if (arch_has_acpi_pdc() == false) | ||
148 | return; | ||
149 | |||
150 | obj_list = acpi_processor_alloc_pdc(); | ||
151 | if (!obj_list) | ||
152 | return; | ||
153 | |||
154 | acpi_processor_eval_pdc(handle, obj_list); | ||
155 | |||
156 | kfree(obj_list->pointer->buffer.pointer); | ||
157 | kfree(obj_list->pointer); | ||
158 | kfree(obj_list); | ||
159 | } | ||
160 | |||
161 | static acpi_status __init | ||
162 | early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
163 | { | ||
164 | if (processor_physically_present(handle) == false) | ||
165 | return AE_OK; | ||
166 | |||
167 | acpi_processor_set_pdc(handle); | ||
168 | return AE_OK; | ||
169 | } | ||
170 | |||
171 | static int __init set_no_mwait(const struct dmi_system_id *id) | ||
172 | { | ||
173 | pr_notice("%s detected - disabling mwait for CPU C-states\n", | ||
174 | id->ident); | ||
175 | boot_option_idle_override = IDLE_NOMWAIT; | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static struct dmi_system_id processor_idle_dmi_table[] __initdata = { | ||
180 | { | ||
181 | set_no_mwait, "Extensa 5220", { | ||
182 | DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), | ||
183 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
184 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), | ||
185 | DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, | ||
186 | {}, | ||
187 | }; | ||
188 | |||
189 | static void __init processor_dmi_check(void) | ||
190 | { | ||
191 | /* | ||
192 | * Check whether the system is DMI table. If yes, OSPM | ||
193 | * should not use mwait for CPU-states. | ||
194 | */ | ||
195 | dmi_check_system(processor_idle_dmi_table); | ||
196 | } | ||
197 | |||
198 | void __init acpi_early_processor_set_pdc(void) | ||
199 | { | ||
200 | processor_dmi_check(); | ||
201 | |||
202 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, | ||
203 | ACPI_UINT32_MAX, | ||
204 | early_init_pdc, NULL, NULL, NULL); | ||
205 | acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL); | ||
206 | } | ||
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 0bdacc5e26a3..2ba8f02ced36 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c | |||
@@ -77,7 +77,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) | |||
77 | switch (ares->type) { | 77 | switch (ares->type) { |
78 | case ACPI_RESOURCE_TYPE_MEMORY24: | 78 | case ACPI_RESOURCE_TYPE_MEMORY24: |
79 | memory24 = &ares->data.memory24; | 79 | memory24 = &ares->data.memory24; |
80 | if (!memory24->address_length) | 80 | if (!memory24->minimum && !memory24->address_length) |
81 | return false; | 81 | return false; |
82 | acpi_dev_get_memresource(res, memory24->minimum, | 82 | acpi_dev_get_memresource(res, memory24->minimum, |
83 | memory24->address_length, | 83 | memory24->address_length, |
@@ -85,7 +85,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) | |||
85 | break; | 85 | break; |
86 | case ACPI_RESOURCE_TYPE_MEMORY32: | 86 | case ACPI_RESOURCE_TYPE_MEMORY32: |
87 | memory32 = &ares->data.memory32; | 87 | memory32 = &ares->data.memory32; |
88 | if (!memory32->address_length) | 88 | if (!memory32->minimum && !memory32->address_length) |
89 | return false; | 89 | return false; |
90 | acpi_dev_get_memresource(res, memory32->minimum, | 90 | acpi_dev_get_memresource(res, memory32->minimum, |
91 | memory32->address_length, | 91 | memory32->address_length, |
@@ -93,7 +93,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) | |||
93 | break; | 93 | break; |
94 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | 94 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
95 | fixed_memory32 = &ares->data.fixed_memory32; | 95 | fixed_memory32 = &ares->data.fixed_memory32; |
96 | if (!fixed_memory32->address_length) | 96 | if (!fixed_memory32->address && !fixed_memory32->address_length) |
97 | return false; | 97 | return false; |
98 | acpi_dev_get_memresource(res, fixed_memory32->address, | 98 | acpi_dev_get_memresource(res, fixed_memory32->address, |
99 | fixed_memory32->address_length, | 99 | fixed_memory32->address_length, |
@@ -150,7 +150,7 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) | |||
150 | switch (ares->type) { | 150 | switch (ares->type) { |
151 | case ACPI_RESOURCE_TYPE_IO: | 151 | case ACPI_RESOURCE_TYPE_IO: |
152 | io = &ares->data.io; | 152 | io = &ares->data.io; |
153 | if (!io->address_length) | 153 | if (!io->minimum && !io->address_length) |
154 | return false; | 154 | return false; |
155 | acpi_dev_get_ioresource(res, io->minimum, | 155 | acpi_dev_get_ioresource(res, io->minimum, |
156 | io->address_length, | 156 | io->address_length, |
@@ -158,7 +158,7 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) | |||
158 | break; | 158 | break; |
159 | case ACPI_RESOURCE_TYPE_FIXED_IO: | 159 | case ACPI_RESOURCE_TYPE_FIXED_IO: |
160 | fixed_io = &ares->data.fixed_io; | 160 | fixed_io = &ares->data.fixed_io; |
161 | if (!fixed_io->address_length) | 161 | if (!fixed_io->address && !fixed_io->address_length) |
162 | return false; | 162 | return false; |
163 | acpi_dev_get_ioresource(res, fixed_io->address, | 163 | acpi_dev_get_ioresource(res, fixed_io->address, |
164 | fixed_io->address_length, | 164 | fixed_io->address_length, |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f775fa0d850f..5d592e17d760 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -77,7 +77,9 @@ void acpi_initialize_hp_context(struct acpi_device *adev, | |||
77 | void (*uevent)(struct acpi_device *, u32)) | 77 | void (*uevent)(struct acpi_device *, u32)) |
78 | { | 78 | { |
79 | acpi_lock_hp_context(); | 79 | acpi_lock_hp_context(); |
80 | acpi_set_hp_context(adev, hp, notify, uevent, NULL); | 80 | hp->notify = notify; |
81 | hp->uevent = uevent; | ||
82 | acpi_set_hp_context(adev, hp); | ||
81 | acpi_unlock_hp_context(); | 83 | acpi_unlock_hp_context(); |
82 | } | 84 | } |
83 | EXPORT_SYMBOL_GPL(acpi_initialize_hp_context); | 85 | EXPORT_SYMBOL_GPL(acpi_initialize_hp_context); |
@@ -1421,14 +1423,13 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, | |||
1421 | wakeup->sleep_state = sleep_state; | 1423 | wakeup->sleep_state = sleep_state; |
1422 | } | 1424 | } |
1423 | } | 1425 | } |
1424 | acpi_setup_gpe_for_wake(handle, wakeup->gpe_device, wakeup->gpe_number); | ||
1425 | 1426 | ||
1426 | out: | 1427 | out: |
1427 | kfree(buffer.pointer); | 1428 | kfree(buffer.pointer); |
1428 | return err; | 1429 | return err; |
1429 | } | 1430 | } |
1430 | 1431 | ||
1431 | static void acpi_bus_set_run_wake_flags(struct acpi_device *device) | 1432 | static void acpi_wakeup_gpe_init(struct acpi_device *device) |
1432 | { | 1433 | { |
1433 | struct acpi_device_id button_device_ids[] = { | 1434 | struct acpi_device_id button_device_ids[] = { |
1434 | {"PNP0C0C", 0}, | 1435 | {"PNP0C0C", 0}, |
@@ -1436,29 +1437,33 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) | |||
1436 | {"PNP0C0E", 0}, | 1437 | {"PNP0C0E", 0}, |
1437 | {"", 0}, | 1438 | {"", 0}, |
1438 | }; | 1439 | }; |
1440 | struct acpi_device_wakeup *wakeup = &device->wakeup; | ||
1439 | acpi_status status; | 1441 | acpi_status status; |
1440 | acpi_event_status event_status; | 1442 | acpi_event_status event_status; |
1441 | 1443 | ||
1442 | device->wakeup.flags.notifier_present = 0; | 1444 | wakeup->flags.notifier_present = 0; |
1443 | 1445 | ||
1444 | /* Power button, Lid switch always enable wakeup */ | 1446 | /* Power button, Lid switch always enable wakeup */ |
1445 | if (!acpi_match_device_ids(device, button_device_ids)) { | 1447 | if (!acpi_match_device_ids(device, button_device_ids)) { |
1446 | device->wakeup.flags.run_wake = 1; | 1448 | wakeup->flags.run_wake = 1; |
1447 | if (!acpi_match_device_ids(device, &button_device_ids[1])) { | 1449 | if (!acpi_match_device_ids(device, &button_device_ids[1])) { |
1448 | /* Do not use Lid/sleep button for S5 wakeup */ | 1450 | /* Do not use Lid/sleep button for S5 wakeup */ |
1449 | if (device->wakeup.sleep_state == ACPI_STATE_S5) | 1451 | if (wakeup->sleep_state == ACPI_STATE_S5) |
1450 | device->wakeup.sleep_state = ACPI_STATE_S4; | 1452 | wakeup->sleep_state = ACPI_STATE_S4; |
1451 | } | 1453 | } |
1454 | acpi_mark_gpe_for_wake(wakeup->gpe_device, wakeup->gpe_number); | ||
1452 | device_set_wakeup_capable(&device->dev, true); | 1455 | device_set_wakeup_capable(&device->dev, true); |
1453 | return; | 1456 | return; |
1454 | } | 1457 | } |
1455 | 1458 | ||
1456 | status = acpi_get_gpe_status(device->wakeup.gpe_device, | 1459 | acpi_setup_gpe_for_wake(device->handle, wakeup->gpe_device, |
1457 | device->wakeup.gpe_number, | 1460 | wakeup->gpe_number); |
1458 | &event_status); | 1461 | status = acpi_get_gpe_status(wakeup->gpe_device, wakeup->gpe_number, |
1459 | if (status == AE_OK) | 1462 | &event_status); |
1460 | device->wakeup.flags.run_wake = | 1463 | if (ACPI_FAILURE(status)) |
1461 | !!(event_status & ACPI_EVENT_FLAG_HANDLE); | 1464 | return; |
1465 | |||
1466 | wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HANDLE); | ||
1462 | } | 1467 | } |
1463 | 1468 | ||
1464 | static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | 1469 | static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) |
@@ -1478,7 +1483,7 @@ static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
1478 | 1483 | ||
1479 | device->wakeup.flags.valid = 1; | 1484 | device->wakeup.flags.valid = 1; |
1480 | device->wakeup.prepare_count = 0; | 1485 | device->wakeup.prepare_count = 0; |
1481 | acpi_bus_set_run_wake_flags(device); | 1486 | acpi_wakeup_gpe_init(device); |
1482 | /* Call _PSW/_DSW object to disable its ability to wake the sleeping | 1487 | /* Call _PSW/_DSW object to disable its ability to wake the sleeping |
1483 | * system for the ACPI device with the _PRW object. | 1488 | * system for the ACPI device with the _PRW object. |
1484 | * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. | 1489 | * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index b3e3cc73ba79..54da4a3fe65e 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -322,6 +322,11 @@ static struct dmi_system_id acpisleep_dmi_table[] __initdata = { | |||
322 | 322 | ||
323 | static void acpi_sleep_dmi_check(void) | 323 | static void acpi_sleep_dmi_check(void) |
324 | { | 324 | { |
325 | int year; | ||
326 | |||
327 | if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2012) | ||
328 | acpi_nvs_nosave_s3(); | ||
329 | |||
325 | dmi_check_system(acpisleep_dmi_table); | 330 | dmi_check_system(acpisleep_dmi_table); |
326 | } | 331 | } |
327 | 332 | ||
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index fb9ffe9adc64..826884392e6b 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -68,7 +68,7 @@ MODULE_AUTHOR("Bruno Ducrot"); | |||
68 | MODULE_DESCRIPTION("ACPI Video Driver"); | 68 | MODULE_DESCRIPTION("ACPI Video Driver"); |
69 | MODULE_LICENSE("GPL"); | 69 | MODULE_LICENSE("GPL"); |
70 | 70 | ||
71 | static bool brightness_switch_enabled; | 71 | static bool brightness_switch_enabled = 1; |
72 | module_param(brightness_switch_enabled, bool, 0644); | 72 | module_param(brightness_switch_enabled, bool, 0644); |
73 | 73 | ||
74 | /* | 74 | /* |
@@ -204,6 +204,8 @@ struct acpi_video_device { | |||
204 | struct acpi_video_device_flags flags; | 204 | struct acpi_video_device_flags flags; |
205 | struct acpi_video_device_cap cap; | 205 | struct acpi_video_device_cap cap; |
206 | struct list_head entry; | 206 | struct list_head entry; |
207 | struct delayed_work switch_brightness_work; | ||
208 | int switch_brightness_event; | ||
207 | struct acpi_video_bus *video; | 209 | struct acpi_video_bus *video; |
208 | struct acpi_device *dev; | 210 | struct acpi_device *dev; |
209 | struct acpi_video_device_brightness *brightness; | 211 | struct acpi_video_device_brightness *brightness; |
@@ -230,8 +232,7 @@ static int acpi_video_device_lcd_get_level_current( | |||
230 | unsigned long long *level, bool raw); | 232 | unsigned long long *level, bool raw); |
231 | static int acpi_video_get_next_level(struct acpi_video_device *device, | 233 | static int acpi_video_get_next_level(struct acpi_video_device *device, |
232 | u32 level_current, u32 event); | 234 | u32 level_current, u32 event); |
233 | static int acpi_video_switch_brightness(struct acpi_video_device *device, | 235 | static void acpi_video_switch_brightness(struct work_struct *work); |
234 | int event); | ||
235 | 236 | ||
236 | static bool acpi_video_use_native_backlight(void) | 237 | static bool acpi_video_use_native_backlight(void) |
237 | { | 238 | { |
@@ -241,13 +242,14 @@ static bool acpi_video_use_native_backlight(void) | |||
241 | return use_native_backlight_dmi; | 242 | return use_native_backlight_dmi; |
242 | } | 243 | } |
243 | 244 | ||
244 | static bool acpi_video_verify_backlight_support(void) | 245 | bool acpi_video_verify_backlight_support(void) |
245 | { | 246 | { |
246 | if (acpi_osi_is_win8() && acpi_video_use_native_backlight() && | 247 | if (acpi_osi_is_win8() && acpi_video_use_native_backlight() && |
247 | backlight_device_registered(BACKLIGHT_RAW)) | 248 | backlight_device_registered(BACKLIGHT_RAW)) |
248 | return false; | 249 | return false; |
249 | return acpi_video_backlight_support(); | 250 | return acpi_video_backlight_support(); |
250 | } | 251 | } |
252 | EXPORT_SYMBOL_GPL(acpi_video_verify_backlight_support); | ||
251 | 253 | ||
252 | /* backlight device sysfs support */ | 254 | /* backlight device sysfs support */ |
253 | static int acpi_video_get_brightness(struct backlight_device *bd) | 255 | static int acpi_video_get_brightness(struct backlight_device *bd) |
@@ -274,6 +276,7 @@ static int acpi_video_set_brightness(struct backlight_device *bd) | |||
274 | int request_level = bd->props.brightness + 2; | 276 | int request_level = bd->props.brightness + 2; |
275 | struct acpi_video_device *vd = bl_get_data(bd); | 277 | struct acpi_video_device *vd = bl_get_data(bd); |
276 | 278 | ||
279 | cancel_delayed_work(&vd->switch_brightness_work); | ||
277 | return acpi_video_device_lcd_set_level(vd, | 280 | return acpi_video_device_lcd_set_level(vd, |
278 | vd->brightness->levels[request_level]); | 281 | vd->brightness->levels[request_level]); |
279 | } | 282 | } |
@@ -460,6 +463,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
460 | }, | 463 | }, |
461 | { | 464 | { |
462 | .callback = video_set_use_native_backlight, | 465 | .callback = video_set_use_native_backlight, |
466 | .ident = "ThinkPad X230", | ||
467 | .matches = { | ||
468 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
469 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), | ||
470 | }, | ||
471 | }, | ||
472 | { | ||
473 | .callback = video_set_use_native_backlight, | ||
463 | .ident = "ThinkPad T430 and T430s", | 474 | .ident = "ThinkPad T430 and T430s", |
464 | .matches = { | 475 | .matches = { |
465 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 476 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
@@ -468,10 +479,42 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
468 | }, | 479 | }, |
469 | { | 480 | { |
470 | .callback = video_set_use_native_backlight, | 481 | .callback = video_set_use_native_backlight, |
471 | .ident = "ThinkPad X230", | 482 | .ident = "ThinkPad T430", |
472 | .matches = { | 483 | .matches = { |
473 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 484 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
474 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"), | 485 | DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"), |
486 | }, | ||
487 | }, | ||
488 | { | ||
489 | .callback = video_set_use_native_backlight, | ||
490 | .ident = "ThinkPad T431s", | ||
491 | .matches = { | ||
492 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
493 | DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"), | ||
494 | }, | ||
495 | }, | ||
496 | { | ||
497 | .callback = video_set_use_native_backlight, | ||
498 | .ident = "ThinkPad Edge E530", | ||
499 | .matches = { | ||
500 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
501 | DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"), | ||
502 | }, | ||
503 | }, | ||
504 | { | ||
505 | .callback = video_set_use_native_backlight, | ||
506 | .ident = "ThinkPad Edge E530", | ||
507 | .matches = { | ||
508 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
509 | DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"), | ||
510 | }, | ||
511 | }, | ||
512 | { | ||
513 | .callback = video_set_use_native_backlight, | ||
514 | .ident = "ThinkPad Edge E530", | ||
515 | .matches = { | ||
516 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
517 | DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"), | ||
475 | }, | 518 | }, |
476 | }, | 519 | }, |
477 | { | 520 | { |
@@ -563,6 +606,38 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
563 | }, | 606 | }, |
564 | }, | 607 | }, |
565 | { | 608 | { |
609 | .callback = video_set_use_native_backlight, | ||
610 | .ident = "Acer TravelMate B113", | ||
611 | .matches = { | ||
612 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
613 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate B113"), | ||
614 | }, | ||
615 | }, | ||
616 | { | ||
617 | .callback = video_set_use_native_backlight, | ||
618 | .ident = "Acer Aspire V5-572G", | ||
619 | .matches = { | ||
620 | DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), | ||
621 | DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"), | ||
622 | }, | ||
623 | }, | ||
624 | { | ||
625 | .callback = video_set_use_native_backlight, | ||
626 | .ident = "Acer Aspire V5-573G", | ||
627 | .matches = { | ||
628 | DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"), | ||
629 | DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"), | ||
630 | }, | ||
631 | }, | ||
632 | { | ||
633 | .callback = video_set_use_native_backlight, | ||
634 | .ident = "ASUS Zenbook Prime UX31A", | ||
635 | .matches = { | ||
636 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
637 | DMI_MATCH(DMI_PRODUCT_NAME, "UX31A"), | ||
638 | }, | ||
639 | }, | ||
640 | { | ||
566 | .callback = video_set_use_native_backlight, | 641 | .callback = video_set_use_native_backlight, |
567 | .ident = "HP ProBook 4340s", | 642 | .ident = "HP ProBook 4340s", |
568 | .matches = { | 643 | .matches = { |
@@ -572,6 +647,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
572 | }, | 647 | }, |
573 | { | 648 | { |
574 | .callback = video_set_use_native_backlight, | 649 | .callback = video_set_use_native_backlight, |
650 | .ident = "HP ProBook 4540s", | ||
651 | .matches = { | ||
652 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
653 | DMI_MATCH(DMI_PRODUCT_VERSION, "HP ProBook 4540s"), | ||
654 | }, | ||
655 | }, | ||
656 | { | ||
657 | .callback = video_set_use_native_backlight, | ||
575 | .ident = "HP ProBook 2013 models", | 658 | .ident = "HP ProBook 2013 models", |
576 | .matches = { | 659 | .matches = { |
577 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 660 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
@@ -590,6 +673,15 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
590 | }, | 673 | }, |
591 | { | 674 | { |
592 | .callback = video_set_use_native_backlight, | 675 | .callback = video_set_use_native_backlight, |
676 | .ident = "HP EliteBook 2014 models", | ||
677 | .matches = { | ||
678 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
679 | DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook "), | ||
680 | DMI_MATCH(DMI_PRODUCT_NAME, " G2"), | ||
681 | }, | ||
682 | }, | ||
683 | { | ||
684 | .callback = video_set_use_native_backlight, | ||
593 | .ident = "HP ZBook 14", | 685 | .ident = "HP ZBook 14", |
594 | .matches = { | 686 | .matches = { |
595 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 687 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
@@ -1171,6 +1263,8 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1171 | data->device_id = device_id; | 1263 | data->device_id = device_id; |
1172 | data->video = video; | 1264 | data->video = video; |
1173 | data->dev = device; | 1265 | data->dev = device; |
1266 | INIT_DELAYED_WORK(&data->switch_brightness_work, | ||
1267 | acpi_video_switch_brightness); | ||
1174 | 1268 | ||
1175 | attribute = acpi_video_get_device_attr(video, device_id); | 1269 | attribute = acpi_video_get_device_attr(video, device_id); |
1176 | 1270 | ||
@@ -1393,15 +1487,18 @@ acpi_video_get_next_level(struct acpi_video_device *device, | |||
1393 | } | 1487 | } |
1394 | } | 1488 | } |
1395 | 1489 | ||
1396 | static int | 1490 | static void |
1397 | acpi_video_switch_brightness(struct acpi_video_device *device, int event) | 1491 | acpi_video_switch_brightness(struct work_struct *work) |
1398 | { | 1492 | { |
1493 | struct acpi_video_device *device = container_of(to_delayed_work(work), | ||
1494 | struct acpi_video_device, switch_brightness_work); | ||
1399 | unsigned long long level_current, level_next; | 1495 | unsigned long long level_current, level_next; |
1496 | int event = device->switch_brightness_event; | ||
1400 | int result = -EINVAL; | 1497 | int result = -EINVAL; |
1401 | 1498 | ||
1402 | /* no warning message if acpi_backlight=vendor or a quirk is used */ | 1499 | /* no warning message if acpi_backlight=vendor or a quirk is used */ |
1403 | if (!acpi_video_verify_backlight_support()) | 1500 | if (!acpi_video_verify_backlight_support()) |
1404 | return 0; | 1501 | return; |
1405 | 1502 | ||
1406 | if (!device->brightness) | 1503 | if (!device->brightness) |
1407 | goto out; | 1504 | goto out; |
@@ -1423,8 +1520,6 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) | |||
1423 | out: | 1520 | out: |
1424 | if (result) | 1521 | if (result) |
1425 | printk(KERN_ERR PREFIX "Failed to switch the brightness\n"); | 1522 | printk(KERN_ERR PREFIX "Failed to switch the brightness\n"); |
1426 | |||
1427 | return result; | ||
1428 | } | 1523 | } |
1429 | 1524 | ||
1430 | int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, | 1525 | int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, |
@@ -1592,6 +1687,16 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) | |||
1592 | return; | 1687 | return; |
1593 | } | 1688 | } |
1594 | 1689 | ||
1690 | static void brightness_switch_event(struct acpi_video_device *video_device, | ||
1691 | u32 event) | ||
1692 | { | ||
1693 | if (!brightness_switch_enabled) | ||
1694 | return; | ||
1695 | |||
1696 | video_device->switch_brightness_event = event; | ||
1697 | schedule_delayed_work(&video_device->switch_brightness_work, HZ / 10); | ||
1698 | } | ||
1699 | |||
1595 | static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | 1700 | static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) |
1596 | { | 1701 | { |
1597 | struct acpi_video_device *video_device = data; | 1702 | struct acpi_video_device *video_device = data; |
@@ -1609,28 +1714,23 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) | |||
1609 | 1714 | ||
1610 | switch (event) { | 1715 | switch (event) { |
1611 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ | 1716 | case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ |
1612 | if (brightness_switch_enabled) | 1717 | brightness_switch_event(video_device, event); |
1613 | acpi_video_switch_brightness(video_device, event); | ||
1614 | keycode = KEY_BRIGHTNESS_CYCLE; | 1718 | keycode = KEY_BRIGHTNESS_CYCLE; |
1615 | break; | 1719 | break; |
1616 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ | 1720 | case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ |
1617 | if (brightness_switch_enabled) | 1721 | brightness_switch_event(video_device, event); |
1618 | acpi_video_switch_brightness(video_device, event); | ||
1619 | keycode = KEY_BRIGHTNESSUP; | 1722 | keycode = KEY_BRIGHTNESSUP; |
1620 | break; | 1723 | break; |
1621 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ | 1724 | case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ |
1622 | if (brightness_switch_enabled) | 1725 | brightness_switch_event(video_device, event); |
1623 | acpi_video_switch_brightness(video_device, event); | ||
1624 | keycode = KEY_BRIGHTNESSDOWN; | 1726 | keycode = KEY_BRIGHTNESSDOWN; |
1625 | break; | 1727 | break; |
1626 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */ | 1728 | case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */ |
1627 | if (brightness_switch_enabled) | 1729 | brightness_switch_event(video_device, event); |
1628 | acpi_video_switch_brightness(video_device, event); | ||
1629 | keycode = KEY_BRIGHTNESS_ZERO; | 1730 | keycode = KEY_BRIGHTNESS_ZERO; |
1630 | break; | 1731 | break; |
1631 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ | 1732 | case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ |
1632 | if (brightness_switch_enabled) | 1733 | brightness_switch_event(video_device, event); |
1633 | acpi_video_switch_brightness(video_device, event); | ||
1634 | keycode = KEY_DISPLAY_OFF; | 1734 | keycode = KEY_DISPLAY_OFF; |
1635 | break; | 1735 | break; |
1636 | default: | 1736 | default: |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 33e3db548a29..c42feb2bacd0 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
@@ -166,6 +166,14 @@ static struct dmi_system_id video_detect_dmi_table[] = { | |||
166 | DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), | 166 | DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), |
167 | }, | 167 | }, |
168 | }, | 168 | }, |
169 | { | ||
170 | .callback = video_detect_force_vendor, | ||
171 | .ident = "Dell Inspiron 5737", | ||
172 | .matches = { | ||
173 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
174 | DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"), | ||
175 | }, | ||
176 | }, | ||
169 | { }, | 177 | { }, |
170 | }; | 178 | }; |
171 | 179 | ||