diff options
Diffstat (limited to 'drivers/acpi')
36 files changed, 2191 insertions, 378 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b7e2e776397d..acad70a0bb0d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -213,6 +213,10 @@ config ACPI_CPU_FREQ_PSS | |||
213 | bool | 213 | bool |
214 | select THERMAL | 214 | select THERMAL |
215 | 215 | ||
216 | config ACPI_PROCESSOR_CSTATE | ||
217 | def_bool y | ||
218 | depends on IA64 || X86 | ||
219 | |||
216 | config ACPI_PROCESSOR_IDLE | 220 | config ACPI_PROCESSOR_IDLE |
217 | bool | 221 | bool |
218 | select CPU_IDLE | 222 | select CPU_IDLE |
@@ -234,7 +238,7 @@ config ACPI_CPPC_LIB | |||
234 | config ACPI_PROCESSOR | 238 | config ACPI_PROCESSOR |
235 | tristate "Processor" | 239 | tristate "Processor" |
236 | depends on X86 || IA64 || ARM64 | 240 | depends on X86 || IA64 || ARM64 |
237 | select ACPI_PROCESSOR_IDLE if X86 || IA64 | 241 | select ACPI_PROCESSOR_IDLE |
238 | select ACPI_CPU_FREQ_PSS if X86 || IA64 | 242 | select ACPI_CPU_FREQ_PSS if X86 || IA64 |
239 | default y | 243 | default y |
240 | help | 244 | help |
@@ -291,8 +295,8 @@ config ACPI_THERMAL | |||
291 | config ACPI_NUMA | 295 | config ACPI_NUMA |
292 | bool "NUMA support" | 296 | bool "NUMA support" |
293 | depends on NUMA | 297 | depends on NUMA |
294 | depends on (X86 || IA64) | 298 | depends on (X86 || IA64 || ARM64) |
295 | default y if IA64_GENERIC || IA64_SGI_SN2 | 299 | default y if IA64_GENERIC || IA64_SGI_SN2 || ARM64 |
296 | 300 | ||
297 | config ACPI_CUSTOM_DSDT_FILE | 301 | config ACPI_CUSTOM_DSDT_FILE |
298 | string "Custom DSDT Table file to include" | 302 | string "Custom DSDT Table file to include" |
@@ -311,9 +315,12 @@ config ACPI_CUSTOM_DSDT | |||
311 | bool | 315 | bool |
312 | default ACPI_CUSTOM_DSDT_FILE != "" | 316 | default ACPI_CUSTOM_DSDT_FILE != "" |
313 | 317 | ||
318 | config ARCH_HAS_ACPI_TABLE_UPGRADE | ||
319 | def_bool n | ||
320 | |||
314 | config ACPI_TABLE_UPGRADE | 321 | config ACPI_TABLE_UPGRADE |
315 | bool "Allow upgrading ACPI tables via initrd" | 322 | bool "Allow upgrading ACPI tables via initrd" |
316 | depends on BLK_DEV_INITRD && X86 | 323 | depends on BLK_DEV_INITRD && ARCH_HAS_ACPI_TABLE_UPGRADE |
317 | default y | 324 | default y |
318 | help | 325 | help |
319 | This option provides functionality to upgrade arbitrary ACPI tables | 326 | This option provides functionality to upgrade arbitrary ACPI tables |
@@ -475,6 +482,7 @@ config ACPI_NFIT_DEBUG | |||
475 | issue. | 482 | issue. |
476 | 483 | ||
477 | source "drivers/acpi/apei/Kconfig" | 484 | source "drivers/acpi/apei/Kconfig" |
485 | source "drivers/acpi/dptf/Kconfig" | ||
478 | 486 | ||
479 | config ACPI_EXTLOG | 487 | config ACPI_EXTLOG |
480 | tristate "Extended Error Log support" | 488 | tristate "Extended Error Log support" |
@@ -519,6 +527,20 @@ config XPOWER_PMIC_OPREGION | |||
519 | help | 527 | help |
520 | This config adds ACPI operation region support for XPower AXP288 PMIC. | 528 | This config adds ACPI operation region support for XPower AXP288 PMIC. |
521 | 529 | ||
530 | config BXT_WC_PMIC_OPREGION | ||
531 | bool "ACPI operation region support for BXT WhiskeyCove PMIC" | ||
532 | depends on INTEL_SOC_PMIC | ||
533 | help | ||
534 | This config adds ACPI operation region support for BXT WhiskeyCove PMIC. | ||
535 | |||
522 | endif | 536 | endif |
523 | 537 | ||
538 | config ACPI_CONFIGFS | ||
539 | tristate "ACPI configfs support" | ||
540 | select CONFIGFS_FS | ||
541 | help | ||
542 | Select this option to enable support for ACPI configuration from | ||
543 | userspace. The configurable ACPI groups will be visible under | ||
544 | /config/acpi, assuming configfs is mounted under /config. | ||
545 | |||
524 | endif # ACPI | 546 | endif # ACPI |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 251ce85a66fb..88f54f03e3d2 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -44,7 +44,6 @@ acpi-y += acpi_lpss.o acpi_apd.o | |||
44 | acpi-y += acpi_platform.o | 44 | acpi-y += acpi_platform.o |
45 | acpi-y += acpi_pnp.o | 45 | acpi-y += acpi_pnp.o |
46 | acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o | 46 | acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o |
47 | acpi-y += int340x_thermal.o | ||
48 | acpi-y += power.o | 47 | acpi-y += power.o |
49 | acpi-y += event.o | 48 | acpi-y += event.o |
50 | acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o | 49 | acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o |
@@ -99,5 +98,9 @@ obj-$(CONFIG_ACPI_EXTLOG) += acpi_extlog.o | |||
99 | obj-$(CONFIG_PMIC_OPREGION) += pmic/intel_pmic.o | 98 | obj-$(CONFIG_PMIC_OPREGION) += pmic/intel_pmic.o |
100 | obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o | 99 | obj-$(CONFIG_CRC_PMIC_OPREGION) += pmic/intel_pmic_crc.o |
101 | obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o | 100 | obj-$(CONFIG_XPOWER_PMIC_OPREGION) += pmic/intel_pmic_xpower.o |
101 | obj-$(CONFIG_BXT_WC_PMIC_OPREGION) += pmic/intel_pmic_bxtwc.o | ||
102 | |||
103 | obj-$(CONFIG_ACPI_CONFIGFS) += acpi_configfs.o | ||
102 | 104 | ||
103 | video-objs += acpi_video.o video_detect.o | 105 | video-objs += acpi_video.o video_detect.o |
106 | obj-y += dptf/ | ||
diff --git a/drivers/acpi/acpi_configfs.c b/drivers/acpi/acpi_configfs.c new file mode 100644 index 000000000000..146a77fb762d --- /dev/null +++ b/drivers/acpi/acpi_configfs.c | |||
@@ -0,0 +1,267 @@ | |||
1 | /* | ||
2 | * ACPI configfs support | ||
3 | * | ||
4 | * Copyright (c) 2016 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #define pr_fmt(fmt) "ACPI configfs: " fmt | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/configfs.h> | ||
16 | #include <linux/acpi.h> | ||
17 | |||
18 | static struct config_group *acpi_table_group; | ||
19 | |||
20 | struct acpi_table { | ||
21 | struct config_item cfg; | ||
22 | struct acpi_table_header *header; | ||
23 | }; | ||
24 | |||
25 | static ssize_t acpi_table_aml_write(struct config_item *cfg, | ||
26 | const void *data, size_t size) | ||
27 | { | ||
28 | const struct acpi_table_header *header = data; | ||
29 | struct acpi_table *table; | ||
30 | int ret; | ||
31 | |||
32 | table = container_of(cfg, struct acpi_table, cfg); | ||
33 | |||
34 | if (table->header) { | ||
35 | pr_err("table already loaded\n"); | ||
36 | return -EBUSY; | ||
37 | } | ||
38 | |||
39 | if (header->length != size) { | ||
40 | pr_err("invalid table length\n"); | ||
41 | return -EINVAL; | ||
42 | } | ||
43 | |||
44 | if (memcmp(header->signature, ACPI_SIG_SSDT, 4)) { | ||
45 | pr_err("invalid table signature\n"); | ||
46 | return -EINVAL; | ||
47 | } | ||
48 | |||
49 | table = container_of(cfg, struct acpi_table, cfg); | ||
50 | |||
51 | table->header = kmemdup(header, header->length, GFP_KERNEL); | ||
52 | if (!table->header) | ||
53 | return -ENOMEM; | ||
54 | |||
55 | ret = acpi_load_table(table->header); | ||
56 | if (ret) { | ||
57 | kfree(table->header); | ||
58 | table->header = NULL; | ||
59 | } | ||
60 | |||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | static inline struct acpi_table_header *get_header(struct config_item *cfg) | ||
65 | { | ||
66 | struct acpi_table *table = container_of(cfg, struct acpi_table, cfg); | ||
67 | |||
68 | if (!table->header) | ||
69 | pr_err("table not loaded\n"); | ||
70 | |||
71 | return table->header; | ||
72 | } | ||
73 | |||
74 | static ssize_t acpi_table_aml_read(struct config_item *cfg, | ||
75 | void *data, size_t size) | ||
76 | { | ||
77 | struct acpi_table_header *h = get_header(cfg); | ||
78 | |||
79 | if (!h) | ||
80 | return -EINVAL; | ||
81 | |||
82 | if (data) | ||
83 | memcpy(data, h, h->length); | ||
84 | |||
85 | return h->length; | ||
86 | } | ||
87 | |||
88 | #define MAX_ACPI_TABLE_SIZE (128 * 1024) | ||
89 | |||
90 | CONFIGFS_BIN_ATTR(acpi_table_, aml, NULL, MAX_ACPI_TABLE_SIZE); | ||
91 | |||
92 | struct configfs_bin_attribute *acpi_table_bin_attrs[] = { | ||
93 | &acpi_table_attr_aml, | ||
94 | NULL, | ||
95 | }; | ||
96 | |||
97 | ssize_t acpi_table_signature_show(struct config_item *cfg, char *str) | ||
98 | { | ||
99 | struct acpi_table_header *h = get_header(cfg); | ||
100 | |||
101 | if (!h) | ||
102 | return -EINVAL; | ||
103 | |||
104 | return sprintf(str, "%.*s\n", ACPI_NAME_SIZE, h->signature); | ||
105 | } | ||
106 | |||
107 | ssize_t acpi_table_length_show(struct config_item *cfg, char *str) | ||
108 | { | ||
109 | struct acpi_table_header *h = get_header(cfg); | ||
110 | |||
111 | if (!h) | ||
112 | return -EINVAL; | ||
113 | |||
114 | return sprintf(str, "%d\n", h->length); | ||
115 | } | ||
116 | |||
117 | ssize_t acpi_table_revision_show(struct config_item *cfg, char *str) | ||
118 | { | ||
119 | struct acpi_table_header *h = get_header(cfg); | ||
120 | |||
121 | if (!h) | ||
122 | return -EINVAL; | ||
123 | |||
124 | return sprintf(str, "%d\n", h->revision); | ||
125 | } | ||
126 | |||
127 | ssize_t acpi_table_oem_id_show(struct config_item *cfg, char *str) | ||
128 | { | ||
129 | struct acpi_table_header *h = get_header(cfg); | ||
130 | |||
131 | if (!h) | ||
132 | return -EINVAL; | ||
133 | |||
134 | return sprintf(str, "%.*s\n", ACPI_OEM_ID_SIZE, h->oem_id); | ||
135 | } | ||
136 | |||
137 | ssize_t acpi_table_oem_table_id_show(struct config_item *cfg, char *str) | ||
138 | { | ||
139 | struct acpi_table_header *h = get_header(cfg); | ||
140 | |||
141 | if (!h) | ||
142 | return -EINVAL; | ||
143 | |||
144 | return sprintf(str, "%.*s\n", ACPI_OEM_TABLE_ID_SIZE, h->oem_table_id); | ||
145 | } | ||
146 | |||
147 | ssize_t acpi_table_oem_revision_show(struct config_item *cfg, char *str) | ||
148 | { | ||
149 | struct acpi_table_header *h = get_header(cfg); | ||
150 | |||
151 | if (!h) | ||
152 | return -EINVAL; | ||
153 | |||
154 | return sprintf(str, "%d\n", h->oem_revision); | ||
155 | } | ||
156 | |||
157 | ssize_t acpi_table_asl_compiler_id_show(struct config_item *cfg, char *str) | ||
158 | { | ||
159 | struct acpi_table_header *h = get_header(cfg); | ||
160 | |||
161 | if (!h) | ||
162 | return -EINVAL; | ||
163 | |||
164 | return sprintf(str, "%.*s\n", ACPI_NAME_SIZE, h->asl_compiler_id); | ||
165 | } | ||
166 | |||
167 | ssize_t acpi_table_asl_compiler_revision_show(struct config_item *cfg, | ||
168 | char *str) | ||
169 | { | ||
170 | struct acpi_table_header *h = get_header(cfg); | ||
171 | |||
172 | if (!h) | ||
173 | return -EINVAL; | ||
174 | |||
175 | return sprintf(str, "%d\n", h->asl_compiler_revision); | ||
176 | } | ||
177 | |||
178 | CONFIGFS_ATTR_RO(acpi_table_, signature); | ||
179 | CONFIGFS_ATTR_RO(acpi_table_, length); | ||
180 | CONFIGFS_ATTR_RO(acpi_table_, revision); | ||
181 | CONFIGFS_ATTR_RO(acpi_table_, oem_id); | ||
182 | CONFIGFS_ATTR_RO(acpi_table_, oem_table_id); | ||
183 | CONFIGFS_ATTR_RO(acpi_table_, oem_revision); | ||
184 | CONFIGFS_ATTR_RO(acpi_table_, asl_compiler_id); | ||
185 | CONFIGFS_ATTR_RO(acpi_table_, asl_compiler_revision); | ||
186 | |||
187 | struct configfs_attribute *acpi_table_attrs[] = { | ||
188 | &acpi_table_attr_signature, | ||
189 | &acpi_table_attr_length, | ||
190 | &acpi_table_attr_revision, | ||
191 | &acpi_table_attr_oem_id, | ||
192 | &acpi_table_attr_oem_table_id, | ||
193 | &acpi_table_attr_oem_revision, | ||
194 | &acpi_table_attr_asl_compiler_id, | ||
195 | &acpi_table_attr_asl_compiler_revision, | ||
196 | NULL, | ||
197 | }; | ||
198 | |||
199 | static struct config_item_type acpi_table_type = { | ||
200 | .ct_owner = THIS_MODULE, | ||
201 | .ct_bin_attrs = acpi_table_bin_attrs, | ||
202 | .ct_attrs = acpi_table_attrs, | ||
203 | }; | ||
204 | |||
205 | static struct config_item *acpi_table_make_item(struct config_group *group, | ||
206 | const char *name) | ||
207 | { | ||
208 | struct acpi_table *table; | ||
209 | |||
210 | table = kzalloc(sizeof(*table), GFP_KERNEL); | ||
211 | if (!table) | ||
212 | return ERR_PTR(-ENOMEM); | ||
213 | |||
214 | config_item_init_type_name(&table->cfg, name, &acpi_table_type); | ||
215 | return &table->cfg; | ||
216 | } | ||
217 | |||
218 | struct configfs_group_operations acpi_table_group_ops = { | ||
219 | .make_item = acpi_table_make_item, | ||
220 | }; | ||
221 | |||
222 | static struct config_item_type acpi_tables_type = { | ||
223 | .ct_owner = THIS_MODULE, | ||
224 | .ct_group_ops = &acpi_table_group_ops, | ||
225 | }; | ||
226 | |||
227 | static struct config_item_type acpi_root_group_type = { | ||
228 | .ct_owner = THIS_MODULE, | ||
229 | }; | ||
230 | |||
231 | static struct configfs_subsystem acpi_configfs = { | ||
232 | .su_group = { | ||
233 | .cg_item = { | ||
234 | .ci_namebuf = "acpi", | ||
235 | .ci_type = &acpi_root_group_type, | ||
236 | }, | ||
237 | }, | ||
238 | .su_mutex = __MUTEX_INITIALIZER(acpi_configfs.su_mutex), | ||
239 | }; | ||
240 | |||
241 | static int __init acpi_configfs_init(void) | ||
242 | { | ||
243 | int ret; | ||
244 | struct config_group *root = &acpi_configfs.su_group; | ||
245 | |||
246 | config_group_init(root); | ||
247 | |||
248 | ret = configfs_register_subsystem(&acpi_configfs); | ||
249 | if (ret) | ||
250 | return ret; | ||
251 | |||
252 | acpi_table_group = configfs_register_default_group(root, "table", | ||
253 | &acpi_tables_type); | ||
254 | return PTR_ERR_OR_ZERO(acpi_table_group); | ||
255 | } | ||
256 | module_init(acpi_configfs_init); | ||
257 | |||
258 | static void __exit acpi_configfs_exit(void) | ||
259 | { | ||
260 | configfs_unregister_default_group(acpi_table_group); | ||
261 | configfs_unregister_subsystem(&acpi_configfs); | ||
262 | } | ||
263 | module_exit(acpi_configfs_exit); | ||
264 | |||
265 | MODULE_AUTHOR("Octavian Purdila <octavian.purdila@intel.com>"); | ||
266 | MODULE_DESCRIPTION("ACPI configfs support"); | ||
267 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/acpi/acpi_lpat.c b/drivers/acpi/acpi_lpat.c index feb61c1630eb..c1c4877ca96c 100644 --- a/drivers/acpi/acpi_lpat.c +++ b/drivers/acpi/acpi_lpat.c | |||
@@ -13,7 +13,7 @@ | |||
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/export.h> |
17 | #include <linux/acpi.h> | 17 | #include <linux/acpi.h> |
18 | #include <acpi/acpi_lpat.h> | 18 | #include <acpi/acpi_lpat.h> |
19 | 19 | ||
@@ -157,5 +157,3 @@ void acpi_lpat_free_conversion_table(struct acpi_lpat_conversion_table | |||
157 | } | 157 | } |
158 | } | 158 | } |
159 | EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table); | 159 | EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table); |
160 | |||
161 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 0872d5fecb82..357a0b8f860b 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
@@ -29,6 +29,7 @@ ACPI_MODULE_NAME("acpi_lpss"); | |||
29 | #ifdef CONFIG_X86_INTEL_LPSS | 29 | #ifdef CONFIG_X86_INTEL_LPSS |
30 | 30 | ||
31 | #include <asm/cpu_device_id.h> | 31 | #include <asm/cpu_device_id.h> |
32 | #include <asm/intel-family.h> | ||
32 | #include <asm/iosf_mbi.h> | 33 | #include <asm/iosf_mbi.h> |
33 | #include <asm/pmc_atom.h> | 34 | #include <asm/pmc_atom.h> |
34 | 35 | ||
@@ -229,8 +230,8 @@ static const struct lpss_device_desc bsw_spi_dev_desc = { | |||
229 | #define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } | 230 | #define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } |
230 | 231 | ||
231 | static const struct x86_cpu_id lpss_cpu_ids[] = { | 232 | static const struct x86_cpu_id lpss_cpu_ids[] = { |
232 | ICPU(0x37), /* Valleyview, Bay Trail */ | 233 | ICPU(INTEL_FAM6_ATOM_SILVERMONT1), /* Valleyview, Bay Trail */ |
233 | ICPU(0x4c), /* Braswell, Cherry Trail */ | 234 | ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */ |
234 | {} | 235 | {} |
235 | }; | 236 | }; |
236 | 237 | ||
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index c1d138e128cb..c5557d070954 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c | |||
@@ -1246,6 +1246,9 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1246 | union acpi_object *dod = NULL; | 1246 | union acpi_object *dod = NULL; |
1247 | union acpi_object *obj; | 1247 | union acpi_object *obj; |
1248 | 1248 | ||
1249 | if (!video->cap._DOD) | ||
1250 | return AE_NOT_EXIST; | ||
1251 | |||
1249 | status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer); | 1252 | status = acpi_evaluate_object(video->device->handle, "_DOD", NULL, &buffer); |
1250 | if (!ACPI_SUCCESS(status)) { | 1253 | if (!ACPI_SUCCESS(status)) { |
1251 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD")); | 1254 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _DOD")); |
diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile index 5d575a955940..e50573de25f1 100644 --- a/drivers/acpi/apei/Makefile +++ b/drivers/acpi/apei/Makefile | |||
@@ -3,4 +3,4 @@ obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o | |||
3 | obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o | 3 | obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o |
4 | obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o | 4 | obj-$(CONFIG_ACPI_APEI_ERST_DEBUG) += erst-dbg.o |
5 | 5 | ||
6 | apei-y := apei-base.o hest.o erst.o | 6 | apei-y := apei-base.o hest.o erst.o bert.o |
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index 16129c78b489..6e9f14c0a71b 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * apei-internal.h - ACPI Platform Error Interface internal | 2 | * apei-internal.h - ACPI Platform Error Interface internal |
3 | * definations. | 3 | * definitions. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef APEI_INTERNAL_H | 6 | #ifndef APEI_INTERNAL_H |
diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c new file mode 100644 index 000000000000..a05b5c0cf181 --- /dev/null +++ b/drivers/acpi/apei/bert.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * APEI Boot Error Record Table (BERT) support | ||
3 | * | ||
4 | * Copyright 2011 Intel Corp. | ||
5 | * Author: Huang Ying <ying.huang@intel.com> | ||
6 | * | ||
7 | * Under normal circumstances, when a hardware error occurs, the error | ||
8 | * handler receives control and processes the error. This gives OSPM a | ||
9 | * chance to process the error condition, report it, and optionally attempt | ||
10 | * recovery. In some cases, the system is unable to process an error. | ||
11 | * For example, system firmware or a management controller may choose to | ||
12 | * reset the system or the system might experience an uncontrolled crash | ||
13 | * or reset.The boot error source is used to report unhandled errors that | ||
14 | * occurred in a previous boot. This mechanism is described in the BERT | ||
15 | * table. | ||
16 | * | ||
17 | * For more information about BERT, please refer to ACPI Specification | ||
18 | * version 4.0, section 17.3.1 | ||
19 | * | ||
20 | * This file is licensed under GPLv2. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/acpi.h> | ||
28 | #include <linux/io.h> | ||
29 | |||
30 | #include "apei-internal.h" | ||
31 | |||
32 | #undef pr_fmt | ||
33 | #define pr_fmt(fmt) "BERT: " fmt | ||
34 | |||
35 | static int bert_disable; | ||
36 | |||
37 | static void __init bert_print_all(struct acpi_bert_region *region, | ||
38 | unsigned int region_len) | ||
39 | { | ||
40 | struct acpi_hest_generic_status *estatus = | ||
41 | (struct acpi_hest_generic_status *)region; | ||
42 | int remain = region_len; | ||
43 | u32 estatus_len; | ||
44 | |||
45 | if (!estatus->block_status) | ||
46 | return; | ||
47 | |||
48 | while (remain > sizeof(struct acpi_bert_region)) { | ||
49 | if (cper_estatus_check(estatus)) { | ||
50 | pr_err(FW_BUG "Invalid error record.\n"); | ||
51 | return; | ||
52 | } | ||
53 | |||
54 | estatus_len = cper_estatus_len(estatus); | ||
55 | if (remain < estatus_len) { | ||
56 | pr_err(FW_BUG "Truncated status block (length: %u).\n", | ||
57 | estatus_len); | ||
58 | return; | ||
59 | } | ||
60 | |||
61 | pr_info_once("Error records from previous boot:\n"); | ||
62 | |||
63 | cper_estatus_print(KERN_INFO HW_ERR, estatus); | ||
64 | |||
65 | /* | ||
66 | * Because the boot error source is "one-time polled" type, | ||
67 | * clear Block Status of current Generic Error Status Block, | ||
68 | * once it's printed. | ||
69 | */ | ||
70 | estatus->block_status = 0; | ||
71 | |||
72 | estatus = (void *)estatus + estatus_len; | ||
73 | /* No more error records. */ | ||
74 | if (!estatus->block_status) | ||
75 | return; | ||
76 | |||
77 | remain -= estatus_len; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static int __init setup_bert_disable(char *str) | ||
82 | { | ||
83 | bert_disable = 1; | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | __setup("bert_disable", setup_bert_disable); | ||
88 | |||
89 | static int __init bert_check_table(struct acpi_table_bert *bert_tab) | ||
90 | { | ||
91 | if (bert_tab->header.length < sizeof(struct acpi_table_bert) || | ||
92 | bert_tab->region_length < sizeof(struct acpi_bert_region)) | ||
93 | return -EINVAL; | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int __init bert_init(void) | ||
99 | { | ||
100 | struct acpi_bert_region *boot_error_region; | ||
101 | struct acpi_table_bert *bert_tab; | ||
102 | unsigned int region_len; | ||
103 | acpi_status status; | ||
104 | int rc = 0; | ||
105 | |||
106 | if (acpi_disabled) | ||
107 | return 0; | ||
108 | |||
109 | if (bert_disable) { | ||
110 | pr_info("Boot Error Record Table support is disabled.\n"); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | status = acpi_get_table(ACPI_SIG_BERT, 0, (struct acpi_table_header **)&bert_tab); | ||
115 | if (status == AE_NOT_FOUND) | ||
116 | return 0; | ||
117 | |||
118 | if (ACPI_FAILURE(status)) { | ||
119 | pr_err("get table failed, %s.\n", acpi_format_exception(status)); | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | |||
123 | rc = bert_check_table(bert_tab); | ||
124 | if (rc) { | ||
125 | pr_err(FW_BUG "table invalid.\n"); | ||
126 | return rc; | ||
127 | } | ||
128 | |||
129 | region_len = bert_tab->region_length; | ||
130 | if (!request_mem_region(bert_tab->address, region_len, "APEI BERT")) { | ||
131 | pr_err("Can't request iomem region <%016llx-%016llx>.\n", | ||
132 | (unsigned long long)bert_tab->address, | ||
133 | (unsigned long long)bert_tab->address + region_len - 1); | ||
134 | return -EIO; | ||
135 | } | ||
136 | |||
137 | boot_error_region = ioremap_cache(bert_tab->address, region_len); | ||
138 | if (boot_error_region) { | ||
139 | bert_print_all(boot_error_region, region_len); | ||
140 | iounmap(boot_error_region); | ||
141 | } else { | ||
142 | rc = -ENOMEM; | ||
143 | } | ||
144 | |||
145 | release_mem_region(bert_tab->address, region_len); | ||
146 | |||
147 | return rc; | ||
148 | } | ||
149 | |||
150 | late_initcall(bert_init); | ||
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 559c1173de1c..eebb7e39c49c 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -33,7 +33,8 @@ | |||
33 | 33 | ||
34 | #include "apei-internal.h" | 34 | #include "apei-internal.h" |
35 | 35 | ||
36 | #define EINJ_PFX "EINJ: " | 36 | #undef pr_fmt |
37 | #define pr_fmt(fmt) "EINJ: " fmt | ||
37 | 38 | ||
38 | #define SPIN_UNIT 100 /* 100ns */ | 39 | #define SPIN_UNIT 100 /* 100ns */ |
39 | /* Firmware should respond within 1 milliseconds */ | 40 | /* Firmware should respond within 1 milliseconds */ |
@@ -179,8 +180,7 @@ static int einj_get_available_error_type(u32 *type) | |||
179 | static int einj_timedout(u64 *t) | 180 | static int einj_timedout(u64 *t) |
180 | { | 181 | { |
181 | if ((s64)*t < SPIN_UNIT) { | 182 | if ((s64)*t < SPIN_UNIT) { |
182 | pr_warning(FW_WARN EINJ_PFX | 183 | pr_warning(FW_WARN "Firmware does not respond in time\n"); |
183 | "Firmware does not respond in time\n"); | ||
184 | return 1; | 184 | return 1; |
185 | } | 185 | } |
186 | *t -= SPIN_UNIT; | 186 | *t -= SPIN_UNIT; |
@@ -307,8 +307,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, | |||
307 | r = request_mem_region(trigger_paddr, sizeof(*trigger_tab), | 307 | r = request_mem_region(trigger_paddr, sizeof(*trigger_tab), |
308 | "APEI EINJ Trigger Table"); | 308 | "APEI EINJ Trigger Table"); |
309 | if (!r) { | 309 | if (!r) { |
310 | pr_err(EINJ_PFX | 310 | pr_err("Can not request [mem %#010llx-%#010llx] for Trigger table\n", |
311 | "Can not request [mem %#010llx-%#010llx] for Trigger table\n", | ||
312 | (unsigned long long)trigger_paddr, | 311 | (unsigned long long)trigger_paddr, |
313 | (unsigned long long)trigger_paddr + | 312 | (unsigned long long)trigger_paddr + |
314 | sizeof(*trigger_tab) - 1); | 313 | sizeof(*trigger_tab) - 1); |
@@ -316,13 +315,12 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, | |||
316 | } | 315 | } |
317 | trigger_tab = ioremap_cache(trigger_paddr, sizeof(*trigger_tab)); | 316 | trigger_tab = ioremap_cache(trigger_paddr, sizeof(*trigger_tab)); |
318 | if (!trigger_tab) { | 317 | if (!trigger_tab) { |
319 | pr_err(EINJ_PFX "Failed to map trigger table!\n"); | 318 | pr_err("Failed to map trigger table!\n"); |
320 | goto out_rel_header; | 319 | goto out_rel_header; |
321 | } | 320 | } |
322 | rc = einj_check_trigger_header(trigger_tab); | 321 | rc = einj_check_trigger_header(trigger_tab); |
323 | if (rc) { | 322 | if (rc) { |
324 | pr_warning(FW_BUG EINJ_PFX | 323 | pr_warning(FW_BUG "Invalid trigger error action table.\n"); |
325 | "The trigger error action table is invalid\n"); | ||
326 | goto out_rel_header; | 324 | goto out_rel_header; |
327 | } | 325 | } |
328 | 326 | ||
@@ -336,8 +334,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, | |||
336 | table_size - sizeof(*trigger_tab), | 334 | table_size - sizeof(*trigger_tab), |
337 | "APEI EINJ Trigger Table"); | 335 | "APEI EINJ Trigger Table"); |
338 | if (!r) { | 336 | if (!r) { |
339 | pr_err(EINJ_PFX | 337 | pr_err("Can not request [mem %#010llx-%#010llx] for Trigger Table Entry\n", |
340 | "Can not request [mem %#010llx-%#010llx] for Trigger Table Entry\n", | ||
341 | (unsigned long long)trigger_paddr + sizeof(*trigger_tab), | 338 | (unsigned long long)trigger_paddr + sizeof(*trigger_tab), |
342 | (unsigned long long)trigger_paddr + table_size - 1); | 339 | (unsigned long long)trigger_paddr + table_size - 1); |
343 | goto out_rel_header; | 340 | goto out_rel_header; |
@@ -345,7 +342,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type, | |||
345 | iounmap(trigger_tab); | 342 | iounmap(trigger_tab); |
346 | trigger_tab = ioremap_cache(trigger_paddr, table_size); | 343 | trigger_tab = ioremap_cache(trigger_paddr, table_size); |
347 | if (!trigger_tab) { | 344 | if (!trigger_tab) { |
348 | pr_err(EINJ_PFX "Failed to map trigger table!\n"); | 345 | pr_err("Failed to map trigger table!\n"); |
349 | goto out_rel_entry; | 346 | goto out_rel_entry; |
350 | } | 347 | } |
351 | trigger_entry = (struct acpi_whea_header *) | 348 | trigger_entry = (struct acpi_whea_header *) |
@@ -695,34 +692,42 @@ static int __init einj_init(void) | |||
695 | struct dentry *fentry; | 692 | struct dentry *fentry; |
696 | struct apei_exec_context ctx; | 693 | struct apei_exec_context ctx; |
697 | 694 | ||
698 | if (acpi_disabled) | 695 | if (acpi_disabled) { |
696 | pr_warn("ACPI disabled.\n"); | ||
699 | return -ENODEV; | 697 | return -ENODEV; |
698 | } | ||
700 | 699 | ||
701 | status = acpi_get_table(ACPI_SIG_EINJ, 0, | 700 | status = acpi_get_table(ACPI_SIG_EINJ, 0, |
702 | (struct acpi_table_header **)&einj_tab); | 701 | (struct acpi_table_header **)&einj_tab); |
703 | if (status == AE_NOT_FOUND) | 702 | if (status == AE_NOT_FOUND) { |
703 | pr_warn("EINJ table not found.\n"); | ||
704 | return -ENODEV; | 704 | return -ENODEV; |
705 | } | ||
705 | else if (ACPI_FAILURE(status)) { | 706 | else if (ACPI_FAILURE(status)) { |
706 | const char *msg = acpi_format_exception(status); | 707 | pr_err("Failed to get EINJ table: %s\n", |
707 | pr_err(EINJ_PFX "Failed to get table, %s\n", msg); | 708 | acpi_format_exception(status)); |
708 | return -EINVAL; | 709 | return -EINVAL; |
709 | } | 710 | } |
710 | 711 | ||
711 | rc = einj_check_table(einj_tab); | 712 | rc = einj_check_table(einj_tab); |
712 | if (rc) { | 713 | if (rc) { |
713 | pr_warning(FW_BUG EINJ_PFX "EINJ table is invalid\n"); | 714 | pr_warn(FW_BUG "Invalid EINJ table.n"); |
714 | return -EINVAL; | 715 | return -EINVAL; |
715 | } | 716 | } |
716 | 717 | ||
717 | rc = -ENOMEM; | 718 | rc = -ENOMEM; |
718 | einj_debug_dir = debugfs_create_dir("einj", apei_get_debugfs_dir()); | 719 | einj_debug_dir = debugfs_create_dir("einj", apei_get_debugfs_dir()); |
719 | if (!einj_debug_dir) | 720 | if (!einj_debug_dir) { |
721 | pr_err("Error creating debugfs node.\n"); | ||
720 | goto err_cleanup; | 722 | goto err_cleanup; |
723 | } | ||
724 | |||
721 | fentry = debugfs_create_file("available_error_type", S_IRUSR, | 725 | fentry = debugfs_create_file("available_error_type", S_IRUSR, |
722 | einj_debug_dir, NULL, | 726 | einj_debug_dir, NULL, |
723 | &available_error_type_fops); | 727 | &available_error_type_fops); |
724 | if (!fentry) | 728 | if (!fentry) |
725 | goto err_cleanup; | 729 | goto err_cleanup; |
730 | |||
726 | fentry = debugfs_create_file("error_type", S_IRUSR | S_IWUSR, | 731 | fentry = debugfs_create_file("error_type", S_IRUSR | S_IWUSR, |
727 | einj_debug_dir, NULL, &error_type_fops); | 732 | einj_debug_dir, NULL, &error_type_fops); |
728 | if (!fentry) | 733 | if (!fentry) |
@@ -735,14 +740,22 @@ static int __init einj_init(void) | |||
735 | apei_resources_init(&einj_resources); | 740 | apei_resources_init(&einj_resources); |
736 | einj_exec_ctx_init(&ctx); | 741 | einj_exec_ctx_init(&ctx); |
737 | rc = apei_exec_collect_resources(&ctx, &einj_resources); | 742 | rc = apei_exec_collect_resources(&ctx, &einj_resources); |
738 | if (rc) | 743 | if (rc) { |
744 | pr_err("Error collecting EINJ resources.\n"); | ||
739 | goto err_fini; | 745 | goto err_fini; |
746 | } | ||
747 | |||
740 | rc = apei_resources_request(&einj_resources, "APEI EINJ"); | 748 | rc = apei_resources_request(&einj_resources, "APEI EINJ"); |
741 | if (rc) | 749 | if (rc) { |
750 | pr_err("Error requesting memory/port resources.\n"); | ||
742 | goto err_fini; | 751 | goto err_fini; |
752 | } | ||
753 | |||
743 | rc = apei_exec_pre_map_gars(&ctx); | 754 | rc = apei_exec_pre_map_gars(&ctx); |
744 | if (rc) | 755 | if (rc) { |
756 | pr_err("Error pre-mapping GARs.\n"); | ||
745 | goto err_release; | 757 | goto err_release; |
758 | } | ||
746 | 759 | ||
747 | rc = -ENOMEM; | 760 | rc = -ENOMEM; |
748 | einj_param = einj_get_parameter_address(); | 761 | einj_param = einj_get_parameter_address(); |
@@ -787,7 +800,7 @@ static int __init einj_init(void) | |||
787 | goto err_unmap; | 800 | goto err_unmap; |
788 | } | 801 | } |
789 | 802 | ||
790 | pr_info(EINJ_PFX "Error INJection is initialized.\n"); | 803 | pr_info("Error INJection is initialized.\n"); |
791 | 804 | ||
792 | return 0; | 805 | return 0; |
793 | 806 | ||
@@ -798,6 +811,7 @@ err_unmap: | |||
798 | sizeof(struct einj_parameter); | 811 | sizeof(struct einj_parameter); |
799 | 812 | ||
800 | acpi_os_unmap_iomem(einj_param, size); | 813 | acpi_os_unmap_iomem(einj_param, size); |
814 | pr_err("Error creating param extension debugfs nodes.\n"); | ||
801 | } | 815 | } |
802 | apei_exec_post_unmap_gars(&ctx); | 816 | apei_exec_post_unmap_gars(&ctx); |
803 | err_release: | 817 | err_release: |
@@ -805,6 +819,7 @@ err_release: | |||
805 | err_fini: | 819 | err_fini: |
806 | apei_resources_fini(&einj_resources); | 820 | apei_resources_fini(&einj_resources); |
807 | err_cleanup: | 821 | err_cleanup: |
822 | pr_err("Error creating primary debugfs nodes.\n"); | ||
808 | debugfs_remove_recursive(einj_debug_dir); | 823 | debugfs_remove_recursive(einj_debug_dir); |
809 | 824 | ||
810 | return rc; | 825 | return rc; |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 262ca31b86d9..85b7d07fe5c8 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -30,6 +30,9 @@ | |||
30 | #include <linux/acpi.h> | 30 | #include <linux/acpi.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/regulator/machine.h> | 32 | #include <linux/regulator/machine.h> |
33 | #include <linux/workqueue.h> | ||
34 | #include <linux/reboot.h> | ||
35 | #include <linux/delay.h> | ||
33 | #ifdef CONFIG_X86 | 36 | #ifdef CONFIG_X86 |
34 | #include <asm/mpspec.h> | 37 | #include <asm/mpspec.h> |
35 | #endif | 38 | #endif |
@@ -174,22 +177,17 @@ void acpi_bus_detach_private_data(acpi_handle handle) | |||
174 | EXPORT_SYMBOL_GPL(acpi_bus_detach_private_data); | 177 | EXPORT_SYMBOL_GPL(acpi_bus_detach_private_data); |
175 | 178 | ||
176 | static void acpi_print_osc_error(acpi_handle handle, | 179 | static void acpi_print_osc_error(acpi_handle handle, |
177 | struct acpi_osc_context *context, char *error) | 180 | struct acpi_osc_context *context, char *error) |
178 | { | 181 | { |
179 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER}; | ||
180 | int i; | 182 | int i; |
181 | 183 | ||
182 | if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) | 184 | acpi_handle_debug(handle, "(%s): %s\n", context->uuid_str, error); |
183 | printk(KERN_DEBUG "%s: %s\n", context->uuid_str, error); | 185 | |
184 | else { | 186 | pr_debug("_OSC request data:"); |
185 | printk(KERN_DEBUG "%s (%s): %s\n", | ||
186 | (char *)buffer.pointer, context->uuid_str, error); | ||
187 | kfree(buffer.pointer); | ||
188 | } | ||
189 | printk(KERN_DEBUG "_OSC request data:"); | ||
190 | for (i = 0; i < context->cap.length; i += sizeof(u32)) | 187 | for (i = 0; i < context->cap.length; i += sizeof(u32)) |
191 | printk(" %x", *((u32 *)(context->cap.pointer + i))); | 188 | pr_debug(" %x", *((u32 *)(context->cap.pointer + i))); |
192 | printk("\n"); | 189 | |
190 | pr_debug("\n"); | ||
193 | } | 191 | } |
194 | 192 | ||
195 | acpi_status acpi_str_to_uuid(char *str, u8 *uuid) | 193 | acpi_status acpi_str_to_uuid(char *str, u8 *uuid) |
@@ -302,6 +300,14 @@ out_kfree: | |||
302 | EXPORT_SYMBOL(acpi_run_osc); | 300 | EXPORT_SYMBOL(acpi_run_osc); |
303 | 301 | ||
304 | bool osc_sb_apei_support_acked; | 302 | bool osc_sb_apei_support_acked; |
303 | |||
304 | /* | ||
305 | * ACPI 6.0 Section 8.4.4.2 Idle State Coordination | ||
306 | * OSPM supports platform coordinated low power idle(LPI) states | ||
307 | */ | ||
308 | bool osc_pc_lpi_support_confirmed; | ||
309 | EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed); | ||
310 | |||
305 | static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; | 311 | static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; |
306 | static void acpi_bus_osc_support(void) | 312 | static void acpi_bus_osc_support(void) |
307 | { | 313 | { |
@@ -322,6 +328,7 @@ static void acpi_bus_osc_support(void) | |||
322 | capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; | 328 | capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT; |
323 | 329 | ||
324 | capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; | 330 | capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT; |
331 | capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT; | ||
325 | 332 | ||
326 | if (!ghes_disable) | 333 | if (!ghes_disable) |
327 | capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; | 334 | capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT; |
@@ -329,9 +336,12 @@ static void acpi_bus_osc_support(void) | |||
329 | return; | 336 | return; |
330 | if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) { | 337 | if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) { |
331 | u32 *capbuf_ret = context.ret.pointer; | 338 | u32 *capbuf_ret = context.ret.pointer; |
332 | if (context.ret.length > OSC_SUPPORT_DWORD) | 339 | if (context.ret.length > OSC_SUPPORT_DWORD) { |
333 | osc_sb_apei_support_acked = | 340 | osc_sb_apei_support_acked = |
334 | capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; | 341 | capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT; |
342 | osc_pc_lpi_support_confirmed = | ||
343 | capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT; | ||
344 | } | ||
335 | kfree(context.ret.pointer); | 345 | kfree(context.ret.pointer); |
336 | } | 346 | } |
337 | /* do we need to check other returned cap? Sounds no */ | 347 | /* do we need to check other returned cap? Sounds no */ |
@@ -475,6 +485,56 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) | |||
475 | acpi_device_notify); | 485 | acpi_device_notify); |
476 | } | 486 | } |
477 | 487 | ||
488 | /* Handle events targeting \_SB device (at present only graceful shutdown) */ | ||
489 | |||
490 | #define ACPI_SB_NOTIFY_SHUTDOWN_REQUEST 0x81 | ||
491 | #define ACPI_SB_INDICATE_INTERVAL 10000 | ||
492 | |||
493 | static void sb_notify_work(struct work_struct *dummy) | ||
494 | { | ||
495 | acpi_handle sb_handle; | ||
496 | |||
497 | orderly_poweroff(true); | ||
498 | |||
499 | /* | ||
500 | * After initiating graceful shutdown, the ACPI spec requires OSPM | ||
501 | * to evaluate _OST method once every 10seconds to indicate that | ||
502 | * the shutdown is in progress | ||
503 | */ | ||
504 | acpi_get_handle(NULL, "\\_SB", &sb_handle); | ||
505 | while (1) { | ||
506 | pr_info("Graceful shutdown in progress.\n"); | ||
507 | acpi_evaluate_ost(sb_handle, ACPI_OST_EC_OSPM_SHUTDOWN, | ||
508 | ACPI_OST_SC_OS_SHUTDOWN_IN_PROGRESS, NULL); | ||
509 | msleep(ACPI_SB_INDICATE_INTERVAL); | ||
510 | } | ||
511 | } | ||
512 | |||
513 | static void acpi_sb_notify(acpi_handle handle, u32 event, void *data) | ||
514 | { | ||
515 | static DECLARE_WORK(acpi_sb_work, sb_notify_work); | ||
516 | |||
517 | if (event == ACPI_SB_NOTIFY_SHUTDOWN_REQUEST) { | ||
518 | if (!work_busy(&acpi_sb_work)) | ||
519 | schedule_work(&acpi_sb_work); | ||
520 | } else | ||
521 | pr_warn("event %x is not supported by \\_SB device\n", event); | ||
522 | } | ||
523 | |||
524 | static int __init acpi_setup_sb_notify_handler(void) | ||
525 | { | ||
526 | acpi_handle sb_handle; | ||
527 | |||
528 | if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &sb_handle))) | ||
529 | return -ENXIO; | ||
530 | |||
531 | if (ACPI_FAILURE(acpi_install_notify_handler(sb_handle, ACPI_DEVICE_NOTIFY, | ||
532 | acpi_sb_notify, NULL))) | ||
533 | return -EINVAL; | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
478 | /* -------------------------------------------------------------------------- | 538 | /* -------------------------------------------------------------------------- |
479 | Device Matching | 539 | Device Matching |
480 | -------------------------------------------------------------------------- */ | 540 | -------------------------------------------------------------------------- */ |
@@ -961,8 +1021,7 @@ void __init acpi_early_init(void) | |||
961 | /** | 1021 | /** |
962 | * acpi_subsystem_init - Finalize the early initialization of ACPI. | 1022 | * acpi_subsystem_init - Finalize the early initialization of ACPI. |
963 | * | 1023 | * |
964 | * Switch over the platform to the ACPI mode (if possible), initialize the | 1024 | * Switch over the platform to the ACPI mode (if possible). |
965 | * handling of ACPI events, install the interrupt and global lock handlers. | ||
966 | * | 1025 | * |
967 | * Doing this too early is generally unsafe, but at the same time it needs to be | 1026 | * Doing this too early is generally unsafe, but at the same time it needs to be |
968 | * done before all things that really depend on ACPI. The right spot appears to | 1027 | * done before all things that really depend on ACPI. The right spot appears to |
@@ -990,6 +1049,13 @@ void __init acpi_subsystem_init(void) | |||
990 | } | 1049 | } |
991 | } | 1050 | } |
992 | 1051 | ||
1052 | static acpi_status acpi_bus_table_handler(u32 event, void *table, void *context) | ||
1053 | { | ||
1054 | acpi_scan_table_handler(event, table, context); | ||
1055 | |||
1056 | return acpi_sysfs_table_handler(event, table, context); | ||
1057 | } | ||
1058 | |||
993 | static int __init acpi_bus_init(void) | 1059 | static int __init acpi_bus_init(void) |
994 | { | 1060 | { |
995 | int result; | 1061 | int result; |
@@ -1043,6 +1109,8 @@ static int __init acpi_bus_init(void) | |||
1043 | * _PDC control method may load dynamic SSDT tables, | 1109 | * _PDC control method may load dynamic SSDT tables, |
1044 | * and we need to install the table handler before that. | 1110 | * and we need to install the table handler before that. |
1045 | */ | 1111 | */ |
1112 | status = acpi_install_table_handler(acpi_bus_table_handler, NULL); | ||
1113 | |||
1046 | acpi_sysfs_init(); | 1114 | acpi_sysfs_init(); |
1047 | 1115 | ||
1048 | acpi_early_processor_set_pdc(); | 1116 | acpi_early_processor_set_pdc(); |
@@ -1124,6 +1192,7 @@ static int __init acpi_init(void) | |||
1124 | acpi_sleep_proc_init(); | 1192 | acpi_sleep_proc_init(); |
1125 | acpi_wakeup_device_init(); | 1193 | acpi_wakeup_device_init(); |
1126 | acpi_debugger_init(); | 1194 | acpi_debugger_init(); |
1195 | acpi_setup_sb_notify_handler(); | ||
1127 | return 0; | 1196 | return 0; |
1128 | } | 1197 | } |
1129 | 1198 | ||
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 5c3b0918d5fd..148f4e5ca104 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -53,6 +53,10 @@ | |||
53 | #define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch" | 53 | #define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch" |
54 | #define ACPI_BUTTON_TYPE_LID 0x05 | 54 | #define ACPI_BUTTON_TYPE_LID 0x05 |
55 | 55 | ||
56 | #define ACPI_BUTTON_LID_INIT_IGNORE 0x00 | ||
57 | #define ACPI_BUTTON_LID_INIT_OPEN 0x01 | ||
58 | #define ACPI_BUTTON_LID_INIT_METHOD 0x02 | ||
59 | |||
56 | #define _COMPONENT ACPI_BUTTON_COMPONENT | 60 | #define _COMPONENT ACPI_BUTTON_COMPONENT |
57 | ACPI_MODULE_NAME("button"); | 61 | ACPI_MODULE_NAME("button"); |
58 | 62 | ||
@@ -105,6 +109,7 @@ struct acpi_button { | |||
105 | 109 | ||
106 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); | 110 | static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); |
107 | static struct acpi_device *lid_device; | 111 | static struct acpi_device *lid_device; |
112 | static u8 lid_init_state = ACPI_BUTTON_LID_INIT_METHOD; | ||
108 | 113 | ||
109 | /* -------------------------------------------------------------------------- | 114 | /* -------------------------------------------------------------------------- |
110 | FS Interface (/proc) | 115 | FS Interface (/proc) |
@@ -113,16 +118,52 @@ static struct acpi_device *lid_device; | |||
113 | static struct proc_dir_entry *acpi_button_dir; | 118 | static struct proc_dir_entry *acpi_button_dir; |
114 | static struct proc_dir_entry *acpi_lid_dir; | 119 | static struct proc_dir_entry *acpi_lid_dir; |
115 | 120 | ||
121 | static int acpi_lid_evaluate_state(struct acpi_device *device) | ||
122 | { | ||
123 | unsigned long long lid_state; | ||
124 | acpi_status status; | ||
125 | |||
126 | status = acpi_evaluate_integer(device->handle, "_LID", NULL, &lid_state); | ||
127 | if (ACPI_FAILURE(status)) | ||
128 | return -ENODEV; | ||
129 | |||
130 | return lid_state ? 1 : 0; | ||
131 | } | ||
132 | |||
133 | static int acpi_lid_notify_state(struct acpi_device *device, int state) | ||
134 | { | ||
135 | struct acpi_button *button = acpi_driver_data(device); | ||
136 | int ret; | ||
137 | |||
138 | /* input layer checks if event is redundant */ | ||
139 | input_report_switch(button->input, SW_LID, !state); | ||
140 | input_sync(button->input); | ||
141 | |||
142 | if (state) | ||
143 | pm_wakeup_event(&device->dev, 0); | ||
144 | |||
145 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); | ||
146 | if (ret == NOTIFY_DONE) | ||
147 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, | ||
148 | device); | ||
149 | if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { | ||
150 | /* | ||
151 | * It is also regarded as success if the notifier_chain | ||
152 | * returns NOTIFY_OK or NOTIFY_DONE. | ||
153 | */ | ||
154 | ret = 0; | ||
155 | } | ||
156 | return ret; | ||
157 | } | ||
158 | |||
116 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) | 159 | static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) |
117 | { | 160 | { |
118 | struct acpi_device *device = seq->private; | 161 | struct acpi_device *device = seq->private; |
119 | acpi_status status; | 162 | int state; |
120 | unsigned long long state; | ||
121 | 163 | ||
122 | status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); | 164 | state = acpi_lid_evaluate_state(device); |
123 | seq_printf(seq, "state: %s\n", | 165 | seq_printf(seq, "state: %s\n", |
124 | ACPI_FAILURE(status) ? "unsupported" : | 166 | state < 0 ? "unsupported" : (state ? "open" : "closed")); |
125 | (state ? "open" : "closed")); | ||
126 | return 0; | 167 | return 0; |
127 | } | 168 | } |
128 | 169 | ||
@@ -231,51 +272,37 @@ EXPORT_SYMBOL(acpi_lid_notifier_unregister); | |||
231 | 272 | ||
232 | int acpi_lid_open(void) | 273 | int acpi_lid_open(void) |
233 | { | 274 | { |
234 | acpi_status status; | ||
235 | unsigned long long state; | ||
236 | |||
237 | if (!lid_device) | 275 | if (!lid_device) |
238 | return -ENODEV; | 276 | return -ENODEV; |
239 | 277 | ||
240 | status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL, | 278 | return acpi_lid_evaluate_state(lid_device); |
241 | &state); | ||
242 | if (ACPI_FAILURE(status)) | ||
243 | return -ENODEV; | ||
244 | |||
245 | return !!state; | ||
246 | } | 279 | } |
247 | EXPORT_SYMBOL(acpi_lid_open); | 280 | EXPORT_SYMBOL(acpi_lid_open); |
248 | 281 | ||
249 | static int acpi_lid_send_state(struct acpi_device *device) | 282 | static int acpi_lid_update_state(struct acpi_device *device) |
250 | { | 283 | { |
251 | struct acpi_button *button = acpi_driver_data(device); | 284 | int state; |
252 | unsigned long long state; | ||
253 | acpi_status status; | ||
254 | int ret; | ||
255 | |||
256 | status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); | ||
257 | if (ACPI_FAILURE(status)) | ||
258 | return -ENODEV; | ||
259 | 285 | ||
260 | /* input layer checks if event is redundant */ | 286 | state = acpi_lid_evaluate_state(device); |
261 | input_report_switch(button->input, SW_LID, !state); | 287 | if (state < 0) |
262 | input_sync(button->input); | 288 | return state; |
263 | 289 | ||
264 | if (state) | 290 | return acpi_lid_notify_state(device, state); |
265 | pm_wakeup_event(&device->dev, 0); | 291 | } |
266 | 292 | ||
267 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); | 293 | static void acpi_lid_initialize_state(struct acpi_device *device) |
268 | if (ret == NOTIFY_DONE) | 294 | { |
269 | ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, | 295 | switch (lid_init_state) { |
270 | device); | 296 | case ACPI_BUTTON_LID_INIT_OPEN: |
271 | if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { | 297 | (void)acpi_lid_notify_state(device, 1); |
272 | /* | 298 | break; |
273 | * It is also regarded as success if the notifier_chain | 299 | case ACPI_BUTTON_LID_INIT_METHOD: |
274 | * returns NOTIFY_OK or NOTIFY_DONE. | 300 | (void)acpi_lid_update_state(device); |
275 | */ | 301 | break; |
276 | ret = 0; | 302 | case ACPI_BUTTON_LID_INIT_IGNORE: |
303 | default: | ||
304 | break; | ||
277 | } | 305 | } |
278 | return ret; | ||
279 | } | 306 | } |
280 | 307 | ||
281 | static void acpi_button_notify(struct acpi_device *device, u32 event) | 308 | static void acpi_button_notify(struct acpi_device *device, u32 event) |
@@ -290,7 +317,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) | |||
290 | case ACPI_BUTTON_NOTIFY_STATUS: | 317 | case ACPI_BUTTON_NOTIFY_STATUS: |
291 | input = button->input; | 318 | input = button->input; |
292 | if (button->type == ACPI_BUTTON_TYPE_LID) { | 319 | if (button->type == ACPI_BUTTON_TYPE_LID) { |
293 | acpi_lid_send_state(device); | 320 | acpi_lid_update_state(device); |
294 | } else { | 321 | } else { |
295 | int keycode; | 322 | int keycode; |
296 | 323 | ||
@@ -335,7 +362,7 @@ static int acpi_button_resume(struct device *dev) | |||
335 | 362 | ||
336 | button->suspended = false; | 363 | button->suspended = false; |
337 | if (button->type == ACPI_BUTTON_TYPE_LID) | 364 | if (button->type == ACPI_BUTTON_TYPE_LID) |
338 | return acpi_lid_send_state(device); | 365 | acpi_lid_initialize_state(device); |
339 | return 0; | 366 | return 0; |
340 | } | 367 | } |
341 | #endif | 368 | #endif |
@@ -416,7 +443,7 @@ static int acpi_button_add(struct acpi_device *device) | |||
416 | if (error) | 443 | if (error) |
417 | goto err_remove_fs; | 444 | goto err_remove_fs; |
418 | if (button->type == ACPI_BUTTON_TYPE_LID) { | 445 | if (button->type == ACPI_BUTTON_TYPE_LID) { |
419 | acpi_lid_send_state(device); | 446 | acpi_lid_initialize_state(device); |
420 | /* | 447 | /* |
421 | * This assumes there's only one lid device, or if there are | 448 | * This assumes there's only one lid device, or if there are |
422 | * more we only care about the last one... | 449 | * more we only care about the last one... |
@@ -446,4 +473,42 @@ static int acpi_button_remove(struct acpi_device *device) | |||
446 | return 0; | 473 | return 0; |
447 | } | 474 | } |
448 | 475 | ||
476 | static int param_set_lid_init_state(const char *val, struct kernel_param *kp) | ||
477 | { | ||
478 | int result = 0; | ||
479 | |||
480 | if (!strncmp(val, "open", sizeof("open") - 1)) { | ||
481 | lid_init_state = ACPI_BUTTON_LID_INIT_OPEN; | ||
482 | pr_info("Notify initial lid state as open\n"); | ||
483 | } else if (!strncmp(val, "method", sizeof("method") - 1)) { | ||
484 | lid_init_state = ACPI_BUTTON_LID_INIT_METHOD; | ||
485 | pr_info("Notify initial lid state with _LID return value\n"); | ||
486 | } else if (!strncmp(val, "ignore", sizeof("ignore") - 1)) { | ||
487 | lid_init_state = ACPI_BUTTON_LID_INIT_IGNORE; | ||
488 | pr_info("Do not notify initial lid state\n"); | ||
489 | } else | ||
490 | result = -EINVAL; | ||
491 | return result; | ||
492 | } | ||
493 | |||
494 | static int param_get_lid_init_state(char *buffer, struct kernel_param *kp) | ||
495 | { | ||
496 | switch (lid_init_state) { | ||
497 | case ACPI_BUTTON_LID_INIT_OPEN: | ||
498 | return sprintf(buffer, "open"); | ||
499 | case ACPI_BUTTON_LID_INIT_METHOD: | ||
500 | return sprintf(buffer, "method"); | ||
501 | case ACPI_BUTTON_LID_INIT_IGNORE: | ||
502 | return sprintf(buffer, "ignore"); | ||
503 | default: | ||
504 | return sprintf(buffer, "invalid"); | ||
505 | } | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | module_param_call(lid_init_state, | ||
510 | param_set_lid_init_state, param_get_lid_init_state, | ||
511 | NULL, 0644); | ||
512 | MODULE_PARM_DESC(lid_init_state, "Behavior for reporting LID initial state"); | ||
513 | |||
449 | module_acpi_driver(acpi_button_driver); | 514 | module_acpi_driver(acpi_button_driver); |
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 8adac69dba3d..2e981732805b 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c | |||
@@ -299,8 +299,10 @@ int acpi_get_psd_map(struct cpudata **all_cpu_data) | |||
299 | continue; | 299 | continue; |
300 | 300 | ||
301 | cpc_ptr = per_cpu(cpc_desc_ptr, i); | 301 | cpc_ptr = per_cpu(cpc_desc_ptr, i); |
302 | if (!cpc_ptr) | 302 | if (!cpc_ptr) { |
303 | continue; | 303 | retval = -EFAULT; |
304 | goto err_ret; | ||
305 | } | ||
304 | 306 | ||
305 | pdomain = &(cpc_ptr->domain_info); | 307 | pdomain = &(cpc_ptr->domain_info); |
306 | cpumask_set_cpu(i, pr->shared_cpu_map); | 308 | cpumask_set_cpu(i, pr->shared_cpu_map); |
@@ -322,8 +324,10 @@ int acpi_get_psd_map(struct cpudata **all_cpu_data) | |||
322 | continue; | 324 | continue; |
323 | 325 | ||
324 | match_cpc_ptr = per_cpu(cpc_desc_ptr, j); | 326 | match_cpc_ptr = per_cpu(cpc_desc_ptr, j); |
325 | if (!match_cpc_ptr) | 327 | if (!match_cpc_ptr) { |
326 | continue; | 328 | retval = -EFAULT; |
329 | goto err_ret; | ||
330 | } | ||
327 | 331 | ||
328 | match_pdomain = &(match_cpc_ptr->domain_info); | 332 | match_pdomain = &(match_cpc_ptr->domain_info); |
329 | if (match_pdomain->domain != pdomain->domain) | 333 | if (match_pdomain->domain != pdomain->domain) |
@@ -353,8 +357,10 @@ int acpi_get_psd_map(struct cpudata **all_cpu_data) | |||
353 | continue; | 357 | continue; |
354 | 358 | ||
355 | match_cpc_ptr = per_cpu(cpc_desc_ptr, j); | 359 | match_cpc_ptr = per_cpu(cpc_desc_ptr, j); |
356 | if (!match_cpc_ptr) | 360 | if (!match_cpc_ptr) { |
357 | continue; | 361 | retval = -EFAULT; |
362 | goto err_ret; | ||
363 | } | ||
358 | 364 | ||
359 | match_pdomain = &(match_cpc_ptr->domain_info); | 365 | match_pdomain = &(match_cpc_ptr->domain_info); |
360 | if (match_pdomain->domain != pdomain->domain) | 366 | if (match_pdomain->domain != pdomain->domain) |
@@ -595,9 +601,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) | |||
595 | /* Store CPU Logical ID */ | 601 | /* Store CPU Logical ID */ |
596 | cpc_ptr->cpu_id = pr->id; | 602 | cpc_ptr->cpu_id = pr->id; |
597 | 603 | ||
598 | /* Plug it into this CPUs CPC descriptor. */ | ||
599 | per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr; | ||
600 | |||
601 | /* Parse PSD data for this CPU */ | 604 | /* Parse PSD data for this CPU */ |
602 | ret = acpi_get_psd(cpc_ptr, handle); | 605 | ret = acpi_get_psd(cpc_ptr, handle); |
603 | if (ret) | 606 | if (ret) |
@@ -610,6 +613,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) | |||
610 | goto out_free; | 613 | goto out_free; |
611 | } | 614 | } |
612 | 615 | ||
616 | /* Plug PSD data into this CPUs CPC descriptor. */ | ||
617 | per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr; | ||
618 | |||
613 | /* Everything looks okay */ | 619 | /* Everything looks okay */ |
614 | pr_debug("Parsed CPC struct for CPU: %d\n", pr->id); | 620 | pr_debug("Parsed CPC struct for CPU: %d\n", pr->id); |
615 | 621 | ||
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index e8e128dede29..0c00208b423e 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -21,7 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/module.h> | 24 | #include <linux/moduleparam.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
@@ -33,12 +33,7 @@ | |||
33 | 33 | ||
34 | #include "internal.h" | 34 | #include "internal.h" |
35 | 35 | ||
36 | #define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver" | ||
37 | |||
38 | ACPI_MODULE_NAME("dock"); | 36 | ACPI_MODULE_NAME("dock"); |
39 | MODULE_AUTHOR("Kristen Carlson Accardi"); | ||
40 | MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | 37 | ||
43 | static bool immediate_undock = 1; | 38 | static bool immediate_undock = 1; |
44 | module_param(immediate_undock, bool, 0644); | 39 | module_param(immediate_undock, bool, 0644); |
diff --git a/drivers/acpi/dptf/Kconfig b/drivers/acpi/dptf/Kconfig new file mode 100644 index 000000000000..ac0a6ed0cf46 --- /dev/null +++ b/drivers/acpi/dptf/Kconfig | |||
@@ -0,0 +1,15 @@ | |||
1 | config DPTF_POWER | ||
2 | tristate "DPTF Platform Power Participant" | ||
3 | depends on X86 | ||
4 | help | ||
5 | This driver adds support for Dynamic Platform and Thermal Framework | ||
6 | (DPTF) Platform Power Participant device (INT3407) support. | ||
7 | This participant is responsible for exposing platform telemetry: | ||
8 | max_platform_power | ||
9 | platform_power_source | ||
10 | adapter_rating | ||
11 | battery_steady_power | ||
12 | charger_type | ||
13 | |||
14 | To compile this driver as a module, choose M here: | ||
15 | the module will be called dptf_power. | ||
diff --git a/drivers/acpi/dptf/Makefile b/drivers/acpi/dptf/Makefile new file mode 100644 index 000000000000..06ea8809583d --- /dev/null +++ b/drivers/acpi/dptf/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | obj-$(CONFIG_ACPI) += int340x_thermal.o | ||
2 | obj-$(CONFIG_DPTF_POWER) += dptf_power.o | ||
3 | |||
4 | ccflags-y += -Idrivers/acpi | ||
diff --git a/drivers/acpi/dptf/dptf_power.c b/drivers/acpi/dptf/dptf_power.c new file mode 100644 index 000000000000..734642dc5008 --- /dev/null +++ b/drivers/acpi/dptf/dptf_power.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * dptf_power: DPTF platform power driver | ||
3 | * Copyright (c) 2016, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/acpi.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | |||
21 | /* | ||
22 | * Presentation of attributes which are defined for INT3407. They are: | ||
23 | * PMAX : Maximum platform powe | ||
24 | * PSRC : Platform power source | ||
25 | * ARTG : Adapter rating | ||
26 | * CTYP : Charger type | ||
27 | * PBSS : Battery steady power | ||
28 | */ | ||
29 | #define DPTF_POWER_SHOW(name, object) \ | ||
30 | static ssize_t name##_show(struct device *dev,\ | ||
31 | struct device_attribute *attr,\ | ||
32 | char *buf)\ | ||
33 | {\ | ||
34 | struct platform_device *pdev = to_platform_device(dev);\ | ||
35 | struct acpi_device *acpi_dev = platform_get_drvdata(pdev);\ | ||
36 | unsigned long long val;\ | ||
37 | acpi_status status;\ | ||
38 | \ | ||
39 | status = acpi_evaluate_integer(acpi_dev->handle, #object,\ | ||
40 | NULL, &val);\ | ||
41 | if (ACPI_SUCCESS(status))\ | ||
42 | return sprintf(buf, "%d\n", (int)val);\ | ||
43 | else \ | ||
44 | return -EINVAL;\ | ||
45 | } | ||
46 | |||
47 | DPTF_POWER_SHOW(max_platform_power_mw, PMAX) | ||
48 | DPTF_POWER_SHOW(platform_power_source, PSRC) | ||
49 | DPTF_POWER_SHOW(adapter_rating_mw, ARTG) | ||
50 | DPTF_POWER_SHOW(battery_steady_power_mw, PBSS) | ||
51 | DPTF_POWER_SHOW(charger_type, CTYP) | ||
52 | |||
53 | static DEVICE_ATTR_RO(max_platform_power_mw); | ||
54 | static DEVICE_ATTR_RO(platform_power_source); | ||
55 | static DEVICE_ATTR_RO(adapter_rating_mw); | ||
56 | static DEVICE_ATTR_RO(battery_steady_power_mw); | ||
57 | static DEVICE_ATTR_RO(charger_type); | ||
58 | |||
59 | static struct attribute *dptf_power_attrs[] = { | ||
60 | &dev_attr_max_platform_power_mw.attr, | ||
61 | &dev_attr_platform_power_source.attr, | ||
62 | &dev_attr_adapter_rating_mw.attr, | ||
63 | &dev_attr_battery_steady_power_mw.attr, | ||
64 | &dev_attr_charger_type.attr, | ||
65 | NULL | ||
66 | }; | ||
67 | |||
68 | static struct attribute_group dptf_power_attribute_group = { | ||
69 | .attrs = dptf_power_attrs, | ||
70 | .name = "dptf_power" | ||
71 | }; | ||
72 | |||
73 | static int dptf_power_add(struct platform_device *pdev) | ||
74 | { | ||
75 | struct acpi_device *acpi_dev; | ||
76 | acpi_status status; | ||
77 | unsigned long long ptype; | ||
78 | int result; | ||
79 | |||
80 | acpi_dev = ACPI_COMPANION(&(pdev->dev)); | ||
81 | if (!acpi_dev) | ||
82 | return -ENODEV; | ||
83 | |||
84 | status = acpi_evaluate_integer(acpi_dev->handle, "PTYP", NULL, &ptype); | ||
85 | if (ACPI_FAILURE(status)) | ||
86 | return -ENODEV; | ||
87 | |||
88 | if (ptype != 0x11) | ||
89 | return -ENODEV; | ||
90 | |||
91 | result = sysfs_create_group(&pdev->dev.kobj, | ||
92 | &dptf_power_attribute_group); | ||
93 | if (result) | ||
94 | return result; | ||
95 | |||
96 | platform_set_drvdata(pdev, acpi_dev); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int dptf_power_remove(struct platform_device *pdev) | ||
102 | { | ||
103 | |||
104 | sysfs_remove_group(&pdev->dev.kobj, &dptf_power_attribute_group); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static const struct acpi_device_id int3407_device_ids[] = { | ||
110 | {"INT3407", 0}, | ||
111 | {"", 0}, | ||
112 | }; | ||
113 | MODULE_DEVICE_TABLE(acpi, int3407_device_ids); | ||
114 | |||
115 | static struct platform_driver dptf_power_driver = { | ||
116 | .probe = dptf_power_add, | ||
117 | .remove = dptf_power_remove, | ||
118 | .driver = { | ||
119 | .name = "DPTF Platform Power", | ||
120 | .acpi_match_table = int3407_device_ids, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | module_platform_driver(dptf_power_driver); | ||
125 | |||
126 | MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); | ||
127 | MODULE_LICENSE("GPL v2"); | ||
128 | MODULE_DESCRIPTION("ACPI DPTF platform power driver"); | ||
diff --git a/drivers/acpi/int340x_thermal.c b/drivers/acpi/dptf/int340x_thermal.c index 33505c651f62..33505c651f62 100644 --- a/drivers/acpi/int340x_thermal.c +++ b/drivers/acpi/dptf/int340x_thermal.c | |||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 290d6f5be44b..999a10914678 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -1359,13 +1359,9 @@ static void ec_remove_handlers(struct acpi_ec *ec) | |||
1359 | } | 1359 | } |
1360 | } | 1360 | } |
1361 | 1361 | ||
1362 | static int acpi_ec_add(struct acpi_device *device) | 1362 | static struct acpi_ec *acpi_ec_alloc(void) |
1363 | { | 1363 | { |
1364 | struct acpi_ec *ec = NULL; | 1364 | struct acpi_ec *ec; |
1365 | int ret; | ||
1366 | |||
1367 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); | ||
1368 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); | ||
1369 | 1365 | ||
1370 | /* Check for boot EC */ | 1366 | /* Check for boot EC */ |
1371 | if (boot_ec) { | 1367 | if (boot_ec) { |
@@ -1376,9 +1372,21 @@ static int acpi_ec_add(struct acpi_device *device) | |||
1376 | first_ec = NULL; | 1372 | first_ec = NULL; |
1377 | } else { | 1373 | } else { |
1378 | ec = make_acpi_ec(); | 1374 | ec = make_acpi_ec(); |
1379 | if (!ec) | ||
1380 | return -ENOMEM; | ||
1381 | } | 1375 | } |
1376 | return ec; | ||
1377 | } | ||
1378 | |||
1379 | static int acpi_ec_add(struct acpi_device *device) | ||
1380 | { | ||
1381 | struct acpi_ec *ec = NULL; | ||
1382 | int ret; | ||
1383 | |||
1384 | strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); | ||
1385 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); | ||
1386 | |||
1387 | ec = acpi_ec_alloc(); | ||
1388 | if (!ec) | ||
1389 | return -ENOMEM; | ||
1382 | if (ec_parse_device(device->handle, 0, ec, NULL) != | 1390 | if (ec_parse_device(device->handle, 0, ec, NULL) != |
1383 | AE_CTRL_TERMINATE) { | 1391 | AE_CTRL_TERMINATE) { |
1384 | kfree(ec); | 1392 | kfree(ec); |
@@ -1465,27 +1473,31 @@ static const struct acpi_device_id ec_device_ids[] = { | |||
1465 | int __init acpi_ec_dsdt_probe(void) | 1473 | int __init acpi_ec_dsdt_probe(void) |
1466 | { | 1474 | { |
1467 | acpi_status status; | 1475 | acpi_status status; |
1476 | struct acpi_ec *ec; | ||
1477 | int ret; | ||
1468 | 1478 | ||
1469 | if (boot_ec) | 1479 | ec = acpi_ec_alloc(); |
1470 | return 0; | 1480 | if (!ec) |
1471 | 1481 | return -ENOMEM; | |
1472 | /* | 1482 | /* |
1473 | * Finding EC from DSDT if there is no ECDT EC available. When this | 1483 | * Finding EC from DSDT if there is no ECDT EC available. When this |
1474 | * function is invoked, ACPI tables have been fully loaded, we can | 1484 | * function is invoked, ACPI tables have been fully loaded, we can |
1475 | * walk namespace now. | 1485 | * walk namespace now. |
1476 | */ | 1486 | */ |
1477 | boot_ec = make_acpi_ec(); | ||
1478 | if (!boot_ec) | ||
1479 | return -ENOMEM; | ||
1480 | status = acpi_get_devices(ec_device_ids[0].id, | 1487 | status = acpi_get_devices(ec_device_ids[0].id, |
1481 | ec_parse_device, boot_ec, NULL); | 1488 | ec_parse_device, ec, NULL); |
1482 | if (ACPI_FAILURE(status) || !boot_ec->handle) | 1489 | if (ACPI_FAILURE(status) || !ec->handle) { |
1483 | return -ENODEV; | 1490 | ret = -ENODEV; |
1484 | if (!ec_install_handlers(boot_ec)) { | 1491 | goto error; |
1485 | first_ec = boot_ec; | ||
1486 | return 0; | ||
1487 | } | 1492 | } |
1488 | return -EFAULT; | 1493 | ret = ec_install_handlers(ec); |
1494 | |||
1495 | error: | ||
1496 | if (ret) | ||
1497 | kfree(ec); | ||
1498 | else | ||
1499 | first_ec = boot_ec = ec; | ||
1500 | return ret; | ||
1489 | } | 1501 | } |
1490 | 1502 | ||
1491 | #if 0 | 1503 | #if 0 |
@@ -1529,6 +1541,11 @@ static int ec_clear_on_resume(const struct dmi_system_id *id) | |||
1529 | return 0; | 1541 | return 0; |
1530 | } | 1542 | } |
1531 | 1543 | ||
1544 | /* | ||
1545 | * Some ECDTs contain wrong register addresses. | ||
1546 | * MSI MS-171F | ||
1547 | * https://bugzilla.kernel.org/show_bug.cgi?id=12461 | ||
1548 | */ | ||
1532 | static int ec_correct_ecdt(const struct dmi_system_id *id) | 1549 | static int ec_correct_ecdt(const struct dmi_system_id *id) |
1533 | { | 1550 | { |
1534 | pr_debug("Detected system needing ECDT address correction.\n"); | 1551 | pr_debug("Detected system needing ECDT address correction.\n"); |
@@ -1538,16 +1555,6 @@ static int ec_correct_ecdt(const struct dmi_system_id *id) | |||
1538 | 1555 | ||
1539 | static struct dmi_system_id ec_dmi_table[] __initdata = { | 1556 | static struct dmi_system_id ec_dmi_table[] __initdata = { |
1540 | { | 1557 | { |
1541 | ec_correct_ecdt, "Asus L4R", { | ||
1542 | DMI_MATCH(DMI_BIOS_VERSION, "1008.006"), | ||
1543 | DMI_MATCH(DMI_PRODUCT_NAME, "L4R"), | ||
1544 | DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL}, | ||
1545 | { | ||
1546 | ec_correct_ecdt, "Asus M6R", { | ||
1547 | DMI_MATCH(DMI_BIOS_VERSION, "0207"), | ||
1548 | DMI_MATCH(DMI_PRODUCT_NAME, "M6R"), | ||
1549 | DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL}, | ||
1550 | { | ||
1551 | ec_correct_ecdt, "MSI MS-171F", { | 1558 | ec_correct_ecdt, "MSI MS-171F", { |
1552 | DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"), | 1559 | DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"), |
1553 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-171F"),}, NULL}, | 1560 | DMI_MATCH(DMI_PRODUCT_NAME, "MS-171F"),}, NULL}, |
@@ -1559,12 +1566,13 @@ static struct dmi_system_id ec_dmi_table[] __initdata = { | |||
1559 | 1566 | ||
1560 | int __init acpi_ec_ecdt_probe(void) | 1567 | int __init acpi_ec_ecdt_probe(void) |
1561 | { | 1568 | { |
1562 | int ret = 0; | 1569 | int ret; |
1563 | acpi_status status; | 1570 | acpi_status status; |
1564 | struct acpi_table_ecdt *ecdt_ptr; | 1571 | struct acpi_table_ecdt *ecdt_ptr; |
1572 | struct acpi_ec *ec; | ||
1565 | 1573 | ||
1566 | boot_ec = make_acpi_ec(); | 1574 | ec = acpi_ec_alloc(); |
1567 | if (!boot_ec) | 1575 | if (!ec) |
1568 | return -ENOMEM; | 1576 | return -ENOMEM; |
1569 | /* | 1577 | /* |
1570 | * Generate a boot ec context | 1578 | * Generate a boot ec context |
@@ -1588,28 +1596,20 @@ int __init acpi_ec_ecdt_probe(void) | |||
1588 | 1596 | ||
1589 | pr_info("EC description table is found, configuring boot EC\n"); | 1597 | pr_info("EC description table is found, configuring boot EC\n"); |
1590 | if (EC_FLAGS_CORRECT_ECDT) { | 1598 | if (EC_FLAGS_CORRECT_ECDT) { |
1591 | /* | 1599 | ec->command_addr = ecdt_ptr->data.address; |
1592 | * Asus L4R, Asus M6R | 1600 | ec->data_addr = ecdt_ptr->control.address; |
1593 | * https://bugzilla.kernel.org/show_bug.cgi?id=9399 | ||
1594 | * MSI MS-171F | ||
1595 | * https://bugzilla.kernel.org/show_bug.cgi?id=12461 | ||
1596 | */ | ||
1597 | boot_ec->command_addr = ecdt_ptr->data.address; | ||
1598 | boot_ec->data_addr = ecdt_ptr->control.address; | ||
1599 | } else { | 1601 | } else { |
1600 | boot_ec->command_addr = ecdt_ptr->control.address; | 1602 | ec->command_addr = ecdt_ptr->control.address; |
1601 | boot_ec->data_addr = ecdt_ptr->data.address; | 1603 | ec->data_addr = ecdt_ptr->data.address; |
1602 | } | 1604 | } |
1603 | boot_ec->gpe = ecdt_ptr->gpe; | 1605 | ec->gpe = ecdt_ptr->gpe; |
1604 | boot_ec->handle = ACPI_ROOT_OBJECT; | 1606 | ec->handle = ACPI_ROOT_OBJECT; |
1605 | ret = ec_install_handlers(boot_ec); | 1607 | ret = ec_install_handlers(ec); |
1606 | if (!ret) | ||
1607 | first_ec = boot_ec; | ||
1608 | error: | 1608 | error: |
1609 | if (ret) { | 1609 | if (ret) |
1610 | kfree(boot_ec); | 1610 | kfree(ec); |
1611 | boot_ec = NULL; | 1611 | else |
1612 | } | 1612 | first_ec = boot_ec = ec; |
1613 | return ret; | 1613 | return ret; |
1614 | } | 1614 | } |
1615 | 1615 | ||
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 27cc7feabfe4..940218ff0193 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h | |||
@@ -87,6 +87,9 @@ bool acpi_queue_hotplug_work(struct work_struct *work); | |||
87 | void acpi_device_hotplug(struct acpi_device *adev, u32 src); | 87 | void acpi_device_hotplug(struct acpi_device *adev, u32 src); |
88 | bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent); | 88 | bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent); |
89 | 89 | ||
90 | acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context); | ||
91 | void acpi_scan_table_handler(u32 event, void *table, void *context); | ||
92 | |||
90 | /* -------------------------------------------------------------------------- | 93 | /* -------------------------------------------------------------------------- |
91 | Device Node Initialization / Removal | 94 | Device Node Initialization / Removal |
92 | -------------------------------------------------------------------------- */ | 95 | -------------------------------------------------------------------------- */ |
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index d176e0ece470..ce3a7a16f03f 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c | |||
@@ -18,22 +18,21 @@ | |||
18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 18 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | |||
22 | #define pr_fmt(fmt) "ACPI: " fmt | ||
23 | |||
21 | #include <linux/module.h> | 24 | #include <linux/module.h> |
22 | #include <linux/init.h> | 25 | #include <linux/init.h> |
23 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
24 | #include <linux/types.h> | 27 | #include <linux/types.h> |
25 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
26 | #include <linux/acpi.h> | 29 | #include <linux/acpi.h> |
30 | #include <linux/bootmem.h> | ||
31 | #include <linux/memblock.h> | ||
27 | #include <linux/numa.h> | 32 | #include <linux/numa.h> |
28 | #include <linux/nodemask.h> | 33 | #include <linux/nodemask.h> |
29 | #include <linux/topology.h> | 34 | #include <linux/topology.h> |
30 | 35 | ||
31 | #define PREFIX "ACPI: " | ||
32 | |||
33 | #define ACPI_NUMA 0x80000000 | ||
34 | #define _COMPONENT ACPI_NUMA | ||
35 | ACPI_MODULE_NAME("numa"); | ||
36 | |||
37 | static nodemask_t nodes_found_map = NODE_MASK_NONE; | 36 | static nodemask_t nodes_found_map = NODE_MASK_NONE; |
38 | 37 | ||
39 | /* maps to convert between proximity domain and logical node ID */ | 38 | /* maps to convert between proximity domain and logical node ID */ |
@@ -43,6 +42,7 @@ static int node_to_pxm_map[MAX_NUMNODES] | |||
43 | = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; | 42 | = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; |
44 | 43 | ||
45 | unsigned char acpi_srat_revision __initdata; | 44 | unsigned char acpi_srat_revision __initdata; |
45 | int acpi_numa __initdata; | ||
46 | 46 | ||
47 | int pxm_to_node(int pxm) | 47 | int pxm_to_node(int pxm) |
48 | { | 48 | { |
@@ -128,68 +128,63 @@ EXPORT_SYMBOL(acpi_map_pxm_to_online_node); | |||
128 | static void __init | 128 | static void __init |
129 | acpi_table_print_srat_entry(struct acpi_subtable_header *header) | 129 | acpi_table_print_srat_entry(struct acpi_subtable_header *header) |
130 | { | 130 | { |
131 | |||
132 | ACPI_FUNCTION_NAME("acpi_table_print_srat_entry"); | ||
133 | |||
134 | if (!header) | ||
135 | return; | ||
136 | |||
137 | switch (header->type) { | 131 | switch (header->type) { |
138 | |||
139 | case ACPI_SRAT_TYPE_CPU_AFFINITY: | 132 | case ACPI_SRAT_TYPE_CPU_AFFINITY: |
140 | #ifdef ACPI_DEBUG_OUTPUT | ||
141 | { | 133 | { |
142 | struct acpi_srat_cpu_affinity *p = | 134 | struct acpi_srat_cpu_affinity *p = |
143 | (struct acpi_srat_cpu_affinity *)header; | 135 | (struct acpi_srat_cpu_affinity *)header; |
144 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 136 | pr_debug("SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n", |
145 | "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n", | 137 | p->apic_id, p->local_sapic_eid, |
146 | p->apic_id, p->local_sapic_eid, | 138 | p->proximity_domain_lo, |
147 | p->proximity_domain_lo, | 139 | (p->flags & ACPI_SRAT_CPU_ENABLED) ? |
148 | (p->flags & ACPI_SRAT_CPU_ENABLED)? | 140 | "enabled" : "disabled"); |
149 | "enabled" : "disabled")); | ||
150 | } | 141 | } |
151 | #endif /* ACPI_DEBUG_OUTPUT */ | ||
152 | break; | 142 | break; |
153 | 143 | ||
154 | case ACPI_SRAT_TYPE_MEMORY_AFFINITY: | 144 | case ACPI_SRAT_TYPE_MEMORY_AFFINITY: |
155 | #ifdef ACPI_DEBUG_OUTPUT | ||
156 | { | 145 | { |
157 | struct acpi_srat_mem_affinity *p = | 146 | struct acpi_srat_mem_affinity *p = |
158 | (struct acpi_srat_mem_affinity *)header; | 147 | (struct acpi_srat_mem_affinity *)header; |
159 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 148 | pr_debug("SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n", |
160 | "SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n", | 149 | (unsigned long)p->base_address, |
161 | (unsigned long)p->base_address, | 150 | (unsigned long)p->length, |
162 | (unsigned long)p->length, | 151 | p->proximity_domain, |
163 | p->proximity_domain, | 152 | (p->flags & ACPI_SRAT_MEM_ENABLED) ? |
164 | (p->flags & ACPI_SRAT_MEM_ENABLED)? | 153 | "enabled" : "disabled", |
165 | "enabled" : "disabled", | 154 | (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) ? |
166 | (p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)? | 155 | " hot-pluggable" : "", |
167 | " hot-pluggable" : "", | 156 | (p->flags & ACPI_SRAT_MEM_NON_VOLATILE) ? |
168 | (p->flags & ACPI_SRAT_MEM_NON_VOLATILE)? | 157 | " non-volatile" : ""); |
169 | " non-volatile" : "")); | ||
170 | } | 158 | } |
171 | #endif /* ACPI_DEBUG_OUTPUT */ | ||
172 | break; | 159 | break; |
173 | 160 | ||
174 | case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: | 161 | case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: |
175 | #ifdef ACPI_DEBUG_OUTPUT | ||
176 | { | 162 | { |
177 | struct acpi_srat_x2apic_cpu_affinity *p = | 163 | struct acpi_srat_x2apic_cpu_affinity *p = |
178 | (struct acpi_srat_x2apic_cpu_affinity *)header; | 164 | (struct acpi_srat_x2apic_cpu_affinity *)header; |
179 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 165 | pr_debug("SRAT Processor (x2apicid[0x%08x]) in proximity domain %d %s\n", |
180 | "SRAT Processor (x2apicid[0x%08x]) in" | 166 | p->apic_id, |
181 | " proximity domain %d %s\n", | 167 | p->proximity_domain, |
182 | p->apic_id, | 168 | (p->flags & ACPI_SRAT_CPU_ENABLED) ? |
183 | p->proximity_domain, | 169 | "enabled" : "disabled"); |
184 | (p->flags & ACPI_SRAT_CPU_ENABLED) ? | ||
185 | "enabled" : "disabled")); | ||
186 | } | 170 | } |
187 | #endif /* ACPI_DEBUG_OUTPUT */ | ||
188 | break; | 171 | break; |
172 | |||
173 | case ACPI_SRAT_TYPE_GICC_AFFINITY: | ||
174 | { | ||
175 | struct acpi_srat_gicc_affinity *p = | ||
176 | (struct acpi_srat_gicc_affinity *)header; | ||
177 | pr_debug("SRAT Processor (acpi id[0x%04x]) in proximity domain %d %s\n", | ||
178 | p->acpi_processor_uid, | ||
179 | p->proximity_domain, | ||
180 | (p->flags & ACPI_SRAT_GICC_ENABLED) ? | ||
181 | "enabled" : "disabled"); | ||
182 | } | ||
183 | break; | ||
184 | |||
189 | default: | 185 | default: |
190 | printk(KERN_WARNING PREFIX | 186 | pr_warn("Found unsupported SRAT entry (type = 0x%x)\n", |
191 | "Found unsupported SRAT entry (type = 0x%x)\n", | 187 | header->type); |
192 | header->type); | ||
193 | break; | 188 | break; |
194 | } | 189 | } |
195 | } | 190 | } |
@@ -217,12 +212,117 @@ static int __init slit_valid(struct acpi_table_slit *slit) | |||
217 | return 1; | 212 | return 1; |
218 | } | 213 | } |
219 | 214 | ||
215 | void __init bad_srat(void) | ||
216 | { | ||
217 | pr_err("SRAT: SRAT not used.\n"); | ||
218 | acpi_numa = -1; | ||
219 | } | ||
220 | |||
221 | int __init srat_disabled(void) | ||
222 | { | ||
223 | return acpi_numa < 0; | ||
224 | } | ||
225 | |||
226 | #if defined(CONFIG_X86) || defined(CONFIG_ARM64) | ||
227 | /* | ||
228 | * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for | ||
229 | * I/O localities since SRAT does not list them. I/O localities are | ||
230 | * not supported at this point. | ||
231 | */ | ||
232 | void __init acpi_numa_slit_init(struct acpi_table_slit *slit) | ||
233 | { | ||
234 | int i, j; | ||
235 | |||
236 | for (i = 0; i < slit->locality_count; i++) { | ||
237 | const int from_node = pxm_to_node(i); | ||
238 | |||
239 | if (from_node == NUMA_NO_NODE) | ||
240 | continue; | ||
241 | |||
242 | for (j = 0; j < slit->locality_count; j++) { | ||
243 | const int to_node = pxm_to_node(j); | ||
244 | |||
245 | if (to_node == NUMA_NO_NODE) | ||
246 | continue; | ||
247 | |||
248 | numa_set_distance(from_node, to_node, | ||
249 | slit->entry[slit->locality_count * i + j]); | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * Default callback for parsing of the Proximity Domain <-> Memory | ||
256 | * Area mappings | ||
257 | */ | ||
258 | int __init | ||
259 | acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) | ||
260 | { | ||
261 | u64 start, end; | ||
262 | u32 hotpluggable; | ||
263 | int node, pxm; | ||
264 | |||
265 | if (srat_disabled()) | ||
266 | goto out_err; | ||
267 | if (ma->header.length < sizeof(struct acpi_srat_mem_affinity)) { | ||
268 | pr_err("SRAT: Unexpected header length: %d\n", | ||
269 | ma->header.length); | ||
270 | goto out_err_bad_srat; | ||
271 | } | ||
272 | if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) | ||
273 | goto out_err; | ||
274 | hotpluggable = ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE; | ||
275 | if (hotpluggable && !IS_ENABLED(CONFIG_MEMORY_HOTPLUG)) | ||
276 | goto out_err; | ||
277 | |||
278 | start = ma->base_address; | ||
279 | end = start + ma->length; | ||
280 | pxm = ma->proximity_domain; | ||
281 | if (acpi_srat_revision <= 1) | ||
282 | pxm &= 0xff; | ||
283 | |||
284 | node = acpi_map_pxm_to_node(pxm); | ||
285 | if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) { | ||
286 | pr_err("SRAT: Too many proximity domains.\n"); | ||
287 | goto out_err_bad_srat; | ||
288 | } | ||
289 | |||
290 | if (numa_add_memblk(node, start, end) < 0) { | ||
291 | pr_err("SRAT: Failed to add memblk to node %u [mem %#010Lx-%#010Lx]\n", | ||
292 | node, (unsigned long long) start, | ||
293 | (unsigned long long) end - 1); | ||
294 | goto out_err_bad_srat; | ||
295 | } | ||
296 | |||
297 | node_set(node, numa_nodes_parsed); | ||
298 | |||
299 | pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n", | ||
300 | node, pxm, | ||
301 | (unsigned long long) start, (unsigned long long) end - 1, | ||
302 | hotpluggable ? " hotplug" : "", | ||
303 | ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : ""); | ||
304 | |||
305 | /* Mark hotplug range in memblock. */ | ||
306 | if (hotpluggable && memblock_mark_hotplug(start, ma->length)) | ||
307 | pr_warn("SRAT: Failed to mark hotplug range [mem %#010Lx-%#010Lx] in memblock\n", | ||
308 | (unsigned long long)start, (unsigned long long)end - 1); | ||
309 | |||
310 | max_possible_pfn = max(max_possible_pfn, PFN_UP(end - 1)); | ||
311 | |||
312 | return 0; | ||
313 | out_err_bad_srat: | ||
314 | bad_srat(); | ||
315 | out_err: | ||
316 | return -EINVAL; | ||
317 | } | ||
318 | #endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */ | ||
319 | |||
220 | static int __init acpi_parse_slit(struct acpi_table_header *table) | 320 | static int __init acpi_parse_slit(struct acpi_table_header *table) |
221 | { | 321 | { |
222 | struct acpi_table_slit *slit = (struct acpi_table_slit *)table; | 322 | struct acpi_table_slit *slit = (struct acpi_table_slit *)table; |
223 | 323 | ||
224 | if (!slit_valid(slit)) { | 324 | if (!slit_valid(slit)) { |
225 | printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); | 325 | pr_info("SLIT table looks invalid. Not used.\n"); |
226 | return -EINVAL; | 326 | return -EINVAL; |
227 | } | 327 | } |
228 | acpi_numa_slit_init(slit); | 328 | acpi_numa_slit_init(slit); |
@@ -233,12 +333,9 @@ static int __init acpi_parse_slit(struct acpi_table_header *table) | |||
233 | void __init __weak | 333 | void __init __weak |
234 | acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) | 334 | acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) |
235 | { | 335 | { |
236 | printk(KERN_WARNING PREFIX | 336 | pr_warn("Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id); |
237 | "Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id); | ||
238 | return; | ||
239 | } | 337 | } |
240 | 338 | ||
241 | |||
242 | static int __init | 339 | static int __init |
243 | acpi_parse_x2apic_affinity(struct acpi_subtable_header *header, | 340 | acpi_parse_x2apic_affinity(struct acpi_subtable_header *header, |
244 | const unsigned long end) | 341 | const unsigned long end) |
@@ -275,6 +372,24 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header, | |||
275 | return 0; | 372 | return 0; |
276 | } | 373 | } |
277 | 374 | ||
375 | static int __init | ||
376 | acpi_parse_gicc_affinity(struct acpi_subtable_header *header, | ||
377 | const unsigned long end) | ||
378 | { | ||
379 | struct acpi_srat_gicc_affinity *processor_affinity; | ||
380 | |||
381 | processor_affinity = (struct acpi_srat_gicc_affinity *)header; | ||
382 | if (!processor_affinity) | ||
383 | return -EINVAL; | ||
384 | |||
385 | acpi_table_print_srat_entry(header); | ||
386 | |||
387 | /* let architecture-dependent part to do it */ | ||
388 | acpi_numa_gicc_affinity_init(processor_affinity); | ||
389 | |||
390 | return 0; | ||
391 | } | ||
392 | |||
278 | static int __initdata parsed_numa_memblks; | 393 | static int __initdata parsed_numa_memblks; |
279 | 394 | ||
280 | static int __init | 395 | static int __init |
@@ -319,6 +434,9 @@ int __init acpi_numa_init(void) | |||
319 | { | 434 | { |
320 | int cnt = 0; | 435 | int cnt = 0; |
321 | 436 | ||
437 | if (acpi_disabled) | ||
438 | return -EINVAL; | ||
439 | |||
322 | /* | 440 | /* |
323 | * Should not limit number with cpu num that is from NR_CPUS or nr_cpus= | 441 | * Should not limit number with cpu num that is from NR_CPUS or nr_cpus= |
324 | * SRAT cpu entries could have different order with that in MADT. | 442 | * SRAT cpu entries could have different order with that in MADT. |
@@ -327,13 +445,15 @@ int __init acpi_numa_init(void) | |||
327 | 445 | ||
328 | /* SRAT: Static Resource Affinity Table */ | 446 | /* SRAT: Static Resource Affinity Table */ |
329 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { | 447 | if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { |
330 | struct acpi_subtable_proc srat_proc[2]; | 448 | struct acpi_subtable_proc srat_proc[3]; |
331 | 449 | ||
332 | memset(srat_proc, 0, sizeof(srat_proc)); | 450 | memset(srat_proc, 0, sizeof(srat_proc)); |
333 | srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY; | 451 | srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY; |
334 | srat_proc[0].handler = acpi_parse_processor_affinity; | 452 | srat_proc[0].handler = acpi_parse_processor_affinity; |
335 | srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY; | 453 | srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY; |
336 | srat_proc[1].handler = acpi_parse_x2apic_affinity; | 454 | srat_proc[1].handler = acpi_parse_x2apic_affinity; |
455 | srat_proc[2].id = ACPI_SRAT_TYPE_GICC_AFFINITY; | ||
456 | srat_proc[2].handler = acpi_parse_gicc_affinity; | ||
337 | 457 | ||
338 | acpi_table_parse_entries_array(ACPI_SIG_SRAT, | 458 | acpi_table_parse_entries_array(ACPI_SIG_SRAT, |
339 | sizeof(struct acpi_table_srat), | 459 | sizeof(struct acpi_table_srat), |
@@ -347,8 +467,6 @@ int __init acpi_numa_init(void) | |||
347 | /* SLIT: System Locality Information Table */ | 467 | /* SLIT: System Locality Information Table */ |
348 | acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); | 468 | acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit); |
349 | 469 | ||
350 | acpi_numa_arch_fixup(); | ||
351 | |||
352 | if (cnt < 0) | 470 | if (cnt < 0) |
353 | return cnt; | 471 | return cnt; |
354 | else if (!parsed_numa_memblks) | 472 | else if (!parsed_numa_memblks) |
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index 7188e53b6b7c..f62c68e24317 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c | |||
@@ -22,8 +22,9 @@ | |||
22 | * General Public License for more details. | 22 | * General Public License for more details. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
26 | |||
25 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | 28 | #include <linux/init.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | #include <linux/types.h> | 30 | #include <linux/types.h> |
@@ -33,30 +34,11 @@ | |||
33 | #include <linux/dmi.h> | 34 | #include <linux/dmi.h> |
34 | #include <linux/pci-acpi.h> | 35 | #include <linux/pci-acpi.h> |
35 | 36 | ||
36 | static bool debug; | ||
37 | static int check_sta_before_sun; | 37 | static int check_sta_before_sun; |
38 | 38 | ||
39 | #define DRIVER_VERSION "0.1" | ||
40 | #define DRIVER_AUTHOR "Alex Chiang <achiang@hp.com>" | ||
41 | #define DRIVER_DESC "ACPI PCI Slot Detection Driver" | ||
42 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
43 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
44 | MODULE_LICENSE("GPL"); | ||
45 | MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); | ||
46 | module_param(debug, bool, 0644); | ||
47 | |||
48 | #define _COMPONENT ACPI_PCI_COMPONENT | 39 | #define _COMPONENT ACPI_PCI_COMPONENT |
49 | ACPI_MODULE_NAME("pci_slot"); | 40 | ACPI_MODULE_NAME("pci_slot"); |
50 | 41 | ||
51 | #define MY_NAME "pci_slot" | ||
52 | #define err(format, arg...) pr_err("%s: " format , MY_NAME , ## arg) | ||
53 | #define info(format, arg...) pr_info("%s: " format , MY_NAME , ## arg) | ||
54 | #define dbg(format, arg...) \ | ||
55 | do { \ | ||
56 | if (debug) \ | ||
57 | pr_debug("%s: " format, MY_NAME , ## arg); \ | ||
58 | } while (0) | ||
59 | |||
60 | #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ | 42 | #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ |
61 | 43 | ||
62 | struct acpi_pci_slot { | 44 | struct acpi_pci_slot { |
@@ -76,7 +58,7 @@ check_slot(acpi_handle handle, unsigned long long *sun) | |||
76 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 58 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
77 | 59 | ||
78 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 60 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
79 | dbg("Checking slot on path: %s\n", (char *)buffer.pointer); | 61 | pr_debug("Checking slot on path: %s\n", (char *)buffer.pointer); |
80 | 62 | ||
81 | if (check_sta_before_sun) { | 63 | if (check_sta_before_sun) { |
82 | /* If SxFy doesn't have _STA, we just assume it's there */ | 64 | /* If SxFy doesn't have _STA, we just assume it's there */ |
@@ -87,14 +69,16 @@ check_slot(acpi_handle handle, unsigned long long *sun) | |||
87 | 69 | ||
88 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | 70 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); |
89 | if (ACPI_FAILURE(status)) { | 71 | if (ACPI_FAILURE(status)) { |
90 | dbg("_ADR returned %d on %s\n", status, (char *)buffer.pointer); | 72 | pr_debug("_ADR returned %d on %s\n", |
73 | status, (char *)buffer.pointer); | ||
91 | goto out; | 74 | goto out; |
92 | } | 75 | } |
93 | 76 | ||
94 | /* No _SUN == not a slot == bail */ | 77 | /* No _SUN == not a slot == bail */ |
95 | status = acpi_evaluate_integer(handle, "_SUN", NULL, sun); | 78 | status = acpi_evaluate_integer(handle, "_SUN", NULL, sun); |
96 | if (ACPI_FAILURE(status)) { | 79 | if (ACPI_FAILURE(status)) { |
97 | dbg("_SUN returned %d on %s\n", status, (char *)buffer.pointer); | 80 | pr_debug("_SUN returned %d on %s\n", |
81 | status, (char *)buffer.pointer); | ||
98 | goto out; | 82 | goto out; |
99 | } | 83 | } |
100 | 84 | ||
@@ -132,15 +116,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
132 | } | 116 | } |
133 | 117 | ||
134 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); | 118 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); |
135 | if (!slot) { | 119 | if (!slot) |
136 | err("%s: cannot allocate memory\n", __func__); | ||
137 | return AE_OK; | 120 | return AE_OK; |
138 | } | ||
139 | 121 | ||
140 | snprintf(name, sizeof(name), "%llu", sun); | 122 | snprintf(name, sizeof(name), "%llu", sun); |
141 | pci_slot = pci_create_slot(pci_bus, device, name, NULL); | 123 | pci_slot = pci_create_slot(pci_bus, device, name, NULL); |
142 | if (IS_ERR(pci_slot)) { | 124 | if (IS_ERR(pci_slot)) { |
143 | err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot)); | 125 | pr_err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot)); |
144 | kfree(slot); | 126 | kfree(slot); |
145 | return AE_OK; | 127 | return AE_OK; |
146 | } | 128 | } |
@@ -150,8 +132,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
150 | 132 | ||
151 | get_device(&pci_bus->dev); | 133 | get_device(&pci_bus->dev); |
152 | 134 | ||
153 | dbg("pci_slot: %p, pci_bus: %x, device: %d, name: %s\n", | 135 | pr_debug("%p, pci_bus: %x, device: %d, name: %s\n", |
154 | pci_slot, pci_bus->number, device, name); | 136 | pci_slot, pci_bus->number, device, name); |
155 | 137 | ||
156 | return AE_OK; | 138 | return AE_OK; |
157 | } | 139 | } |
@@ -186,7 +168,8 @@ void acpi_pci_slot_remove(struct pci_bus *bus) | |||
186 | 168 | ||
187 | static int do_sta_before_sun(const struct dmi_system_id *d) | 169 | static int do_sta_before_sun(const struct dmi_system_id *d) |
188 | { | 170 | { |
189 | info("%s detected: will evaluate _STA before calling _SUN\n", d->ident); | 171 | pr_info("%s detected: will evaluate _STA before calling _SUN\n", |
172 | d->ident); | ||
190 | check_sta_before_sun = 1; | 173 | check_sta_before_sun = 1; |
191 | return 0; | 174 | return 0; |
192 | } | 175 | } |
diff --git a/drivers/acpi/pmic/intel_pmic.c b/drivers/acpi/pmic/intel_pmic.c index bd772cd56494..ca18e0d23df9 100644 --- a/drivers/acpi/pmic/intel_pmic.c +++ b/drivers/acpi/pmic/intel_pmic.c | |||
@@ -13,7 +13,7 @@ | |||
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/export.h> |
17 | #include <linux/acpi.h> | 17 | #include <linux/acpi.h> |
18 | #include <linux/regmap.h> | 18 | #include <linux/regmap.h> |
19 | #include <acpi/acpi_lpat.h> | 19 | #include <acpi/acpi_lpat.h> |
@@ -21,12 +21,19 @@ | |||
21 | 21 | ||
22 | #define PMIC_POWER_OPREGION_ID 0x8d | 22 | #define PMIC_POWER_OPREGION_ID 0x8d |
23 | #define PMIC_THERMAL_OPREGION_ID 0x8c | 23 | #define PMIC_THERMAL_OPREGION_ID 0x8c |
24 | #define PMIC_REGS_OPREGION_ID 0x8f | ||
25 | |||
26 | struct intel_pmic_regs_handler_ctx { | ||
27 | unsigned int val; | ||
28 | u16 addr; | ||
29 | }; | ||
24 | 30 | ||
25 | struct intel_pmic_opregion { | 31 | struct intel_pmic_opregion { |
26 | struct mutex lock; | 32 | struct mutex lock; |
27 | struct acpi_lpat_conversion_table *lpat_table; | 33 | struct acpi_lpat_conversion_table *lpat_table; |
28 | struct regmap *regmap; | 34 | struct regmap *regmap; |
29 | struct intel_pmic_opregion_data *data; | 35 | struct intel_pmic_opregion_data *data; |
36 | struct intel_pmic_regs_handler_ctx ctx; | ||
30 | }; | 37 | }; |
31 | 38 | ||
32 | static int pmic_get_reg_bit(int address, struct pmic_table *table, | 39 | static int pmic_get_reg_bit(int address, struct pmic_table *table, |
@@ -131,7 +138,7 @@ static int pmic_thermal_aux(struct intel_pmic_opregion *opregion, int reg, | |||
131 | } | 138 | } |
132 | 139 | ||
133 | static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg, | 140 | static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg, |
134 | u32 function, u64 *value) | 141 | int bit, u32 function, u64 *value) |
135 | { | 142 | { |
136 | struct intel_pmic_opregion_data *d = opregion->data; | 143 | struct intel_pmic_opregion_data *d = opregion->data; |
137 | struct regmap *regmap = opregion->regmap; | 144 | struct regmap *regmap = opregion->regmap; |
@@ -140,12 +147,12 @@ static int pmic_thermal_pen(struct intel_pmic_opregion *opregion, int reg, | |||
140 | return -ENXIO; | 147 | return -ENXIO; |
141 | 148 | ||
142 | if (function == ACPI_READ) | 149 | if (function == ACPI_READ) |
143 | return d->get_policy(regmap, reg, value); | 150 | return d->get_policy(regmap, reg, bit, value); |
144 | 151 | ||
145 | if (*value != 0 && *value != 1) | 152 | if (*value != 0 && *value != 1) |
146 | return -EINVAL; | 153 | return -EINVAL; |
147 | 154 | ||
148 | return d->update_policy(regmap, reg, *value); | 155 | return d->update_policy(regmap, reg, bit, *value); |
149 | } | 156 | } |
150 | 157 | ||
151 | static bool pmic_thermal_is_temp(int address) | 158 | static bool pmic_thermal_is_temp(int address) |
@@ -170,13 +177,13 @@ static acpi_status intel_pmic_thermal_handler(u32 function, | |||
170 | { | 177 | { |
171 | struct intel_pmic_opregion *opregion = region_context; | 178 | struct intel_pmic_opregion *opregion = region_context; |
172 | struct intel_pmic_opregion_data *d = opregion->data; | 179 | struct intel_pmic_opregion_data *d = opregion->data; |
173 | int reg, result; | 180 | int reg, bit, result; |
174 | 181 | ||
175 | if (bits != 32 || !value64) | 182 | if (bits != 32 || !value64) |
176 | return AE_BAD_PARAMETER; | 183 | return AE_BAD_PARAMETER; |
177 | 184 | ||
178 | result = pmic_get_reg_bit(address, d->thermal_table, | 185 | result = pmic_get_reg_bit(address, d->thermal_table, |
179 | d->thermal_table_count, ®, NULL); | 186 | d->thermal_table_count, ®, &bit); |
180 | if (result == -ENOENT) | 187 | if (result == -ENOENT) |
181 | return AE_BAD_PARAMETER; | 188 | return AE_BAD_PARAMETER; |
182 | 189 | ||
@@ -187,7 +194,8 @@ static acpi_status intel_pmic_thermal_handler(u32 function, | |||
187 | else if (pmic_thermal_is_aux(address)) | 194 | else if (pmic_thermal_is_aux(address)) |
188 | result = pmic_thermal_aux(opregion, reg, function, value64); | 195 | result = pmic_thermal_aux(opregion, reg, function, value64); |
189 | else if (pmic_thermal_is_pen(address)) | 196 | else if (pmic_thermal_is_pen(address)) |
190 | result = pmic_thermal_pen(opregion, reg, function, value64); | 197 | result = pmic_thermal_pen(opregion, reg, bit, |
198 | function, value64); | ||
191 | else | 199 | else |
192 | result = -EINVAL; | 200 | result = -EINVAL; |
193 | 201 | ||
@@ -203,6 +211,48 @@ static acpi_status intel_pmic_thermal_handler(u32 function, | |||
203 | return AE_OK; | 211 | return AE_OK; |
204 | } | 212 | } |
205 | 213 | ||
214 | static acpi_status intel_pmic_regs_handler(u32 function, | ||
215 | acpi_physical_address address, u32 bits, u64 *value64, | ||
216 | void *handler_context, void *region_context) | ||
217 | { | ||
218 | struct intel_pmic_opregion *opregion = region_context; | ||
219 | int result = 0; | ||
220 | |||
221 | switch (address) { | ||
222 | case 0: | ||
223 | return AE_OK; | ||
224 | case 1: | ||
225 | opregion->ctx.addr |= (*value64 & 0xff) << 8; | ||
226 | return AE_OK; | ||
227 | case 2: | ||
228 | opregion->ctx.addr |= *value64 & 0xff; | ||
229 | return AE_OK; | ||
230 | case 3: | ||
231 | opregion->ctx.val = *value64 & 0xff; | ||
232 | return AE_OK; | ||
233 | case 4: | ||
234 | if (*value64) { | ||
235 | result = regmap_write(opregion->regmap, opregion->ctx.addr, | ||
236 | opregion->ctx.val); | ||
237 | } else { | ||
238 | result = regmap_read(opregion->regmap, opregion->ctx.addr, | ||
239 | &opregion->ctx.val); | ||
240 | if (result == 0) | ||
241 | *value64 = opregion->ctx.val; | ||
242 | } | ||
243 | memset(&opregion->ctx, 0x00, sizeof(opregion->ctx)); | ||
244 | } | ||
245 | |||
246 | if (result < 0) { | ||
247 | if (result == -EINVAL) | ||
248 | return AE_BAD_PARAMETER; | ||
249 | else | ||
250 | return AE_ERROR; | ||
251 | } | ||
252 | |||
253 | return AE_OK; | ||
254 | } | ||
255 | |||
206 | int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, | 256 | int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, |
207 | struct regmap *regmap, | 257 | struct regmap *regmap, |
208 | struct intel_pmic_opregion_data *d) | 258 | struct intel_pmic_opregion_data *d) |
@@ -242,16 +292,30 @@ int intel_pmic_install_opregion_handler(struct device *dev, acpi_handle handle, | |||
242 | acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID, | 292 | acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID, |
243 | intel_pmic_power_handler); | 293 | intel_pmic_power_handler); |
244 | ret = -ENODEV; | 294 | ret = -ENODEV; |
245 | goto out_error; | 295 | goto out_remove_power_handler; |
296 | } | ||
297 | |||
298 | status = acpi_install_address_space_handler(handle, | ||
299 | PMIC_REGS_OPREGION_ID, intel_pmic_regs_handler, NULL, | ||
300 | opregion); | ||
301 | if (ACPI_FAILURE(status)) { | ||
302 | ret = -ENODEV; | ||
303 | goto out_remove_thermal_handler; | ||
246 | } | 304 | } |
247 | 305 | ||
248 | opregion->data = d; | 306 | opregion->data = d; |
249 | return 0; | 307 | return 0; |
250 | 308 | ||
309 | out_remove_thermal_handler: | ||
310 | acpi_remove_address_space_handler(handle, PMIC_THERMAL_OPREGION_ID, | ||
311 | intel_pmic_thermal_handler); | ||
312 | |||
313 | out_remove_power_handler: | ||
314 | acpi_remove_address_space_handler(handle, PMIC_POWER_OPREGION_ID, | ||
315 | intel_pmic_power_handler); | ||
316 | |||
251 | out_error: | 317 | out_error: |
252 | acpi_lpat_free_conversion_table(opregion->lpat_table); | 318 | acpi_lpat_free_conversion_table(opregion->lpat_table); |
253 | return ret; | 319 | return ret; |
254 | } | 320 | } |
255 | EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler); | 321 | EXPORT_SYMBOL_GPL(intel_pmic_install_opregion_handler); |
256 | |||
257 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/acpi/pmic/intel_pmic.h b/drivers/acpi/pmic/intel_pmic.h index d4e90af8f0dd..e8bfa7b865a5 100644 --- a/drivers/acpi/pmic/intel_pmic.h +++ b/drivers/acpi/pmic/intel_pmic.h | |||
@@ -12,8 +12,8 @@ struct intel_pmic_opregion_data { | |||
12 | int (*update_power)(struct regmap *r, int reg, int bit, bool on); | 12 | int (*update_power)(struct regmap *r, int reg, int bit, bool on); |
13 | int (*get_raw_temp)(struct regmap *r, int reg); | 13 | int (*get_raw_temp)(struct regmap *r, int reg); |
14 | int (*update_aux)(struct regmap *r, int reg, int raw_temp); | 14 | int (*update_aux)(struct regmap *r, int reg, int raw_temp); |
15 | int (*get_policy)(struct regmap *r, int reg, u64 *value); | 15 | int (*get_policy)(struct regmap *r, int reg, int bit, u64 *value); |
16 | int (*update_policy)(struct regmap *r, int reg, int enable); | 16 | int (*update_policy)(struct regmap *r, int reg, int bit, int enable); |
17 | struct pmic_table *power_table; | 17 | struct pmic_table *power_table; |
18 | int power_table_count; | 18 | int power_table_count; |
19 | struct pmic_table *thermal_table; | 19 | struct pmic_table *thermal_table; |
diff --git a/drivers/acpi/pmic/intel_pmic_bxtwc.c b/drivers/acpi/pmic/intel_pmic_bxtwc.c new file mode 100644 index 000000000000..90011aad4d20 --- /dev/null +++ b/drivers/acpi/pmic/intel_pmic_bxtwc.c | |||
@@ -0,0 +1,420 @@ | |||
1 | /* | ||
2 | * intel_pmic_bxtwc.c - Intel BXT WhiskeyCove PMIC operation region driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | #include <linux/acpi.h> | ||
18 | #include <linux/mfd/intel_soc_pmic.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include "intel_pmic.h" | ||
22 | |||
23 | #define WHISKEY_COVE_ALRT_HIGH_BIT_MASK 0x0F | ||
24 | #define WHISKEY_COVE_ADC_HIGH_BIT(x) (((x & 0x0F) << 8)) | ||
25 | #define WHISKEY_COVE_ADC_CURSRC(x) (((x & 0xF0) >> 4)) | ||
26 | #define VR_MODE_DISABLED 0 | ||
27 | #define VR_MODE_AUTO BIT(0) | ||
28 | #define VR_MODE_NORMAL BIT(1) | ||
29 | #define VR_MODE_SWITCH BIT(2) | ||
30 | #define VR_MODE_ECO (BIT(0)|BIT(1)) | ||
31 | #define VSWITCH2_OUTPUT BIT(5) | ||
32 | #define VSWITCH1_OUTPUT BIT(4) | ||
33 | #define VUSBPHY_CHARGE BIT(1) | ||
34 | |||
35 | static struct pmic_table power_table[] = { | ||
36 | { | ||
37 | .address = 0x0, | ||
38 | .reg = 0x63, | ||
39 | .bit = VR_MODE_AUTO, | ||
40 | }, /* VDD1 -> VDD1CNT */ | ||
41 | { | ||
42 | .address = 0x04, | ||
43 | .reg = 0x65, | ||
44 | .bit = VR_MODE_AUTO, | ||
45 | }, /* VDD2 -> VDD2CNT */ | ||
46 | { | ||
47 | .address = 0x08, | ||
48 | .reg = 0x67, | ||
49 | .bit = VR_MODE_AUTO, | ||
50 | }, /* VDD3 -> VDD3CNT */ | ||
51 | { | ||
52 | .address = 0x0c, | ||
53 | .reg = 0x6d, | ||
54 | .bit = VR_MODE_AUTO, | ||
55 | }, /* VLFX -> VFLEXCNT */ | ||
56 | { | ||
57 | .address = 0x10, | ||
58 | .reg = 0x6f, | ||
59 | .bit = VR_MODE_NORMAL, | ||
60 | }, /* VP1A -> VPROG1ACNT */ | ||
61 | { | ||
62 | .address = 0x14, | ||
63 | .reg = 0x70, | ||
64 | .bit = VR_MODE_NORMAL, | ||
65 | }, /* VP1B -> VPROG1BCNT */ | ||
66 | { | ||
67 | .address = 0x18, | ||
68 | .reg = 0x71, | ||
69 | .bit = VR_MODE_NORMAL, | ||
70 | }, /* VP1C -> VPROG1CCNT */ | ||
71 | { | ||
72 | .address = 0x1c, | ||
73 | .reg = 0x72, | ||
74 | .bit = VR_MODE_NORMAL, | ||
75 | }, /* VP1D -> VPROG1DCNT */ | ||
76 | { | ||
77 | .address = 0x20, | ||
78 | .reg = 0x73, | ||
79 | .bit = VR_MODE_NORMAL, | ||
80 | }, /* VP2A -> VPROG2ACNT */ | ||
81 | { | ||
82 | .address = 0x24, | ||
83 | .reg = 0x74, | ||
84 | .bit = VR_MODE_NORMAL, | ||
85 | }, /* VP2B -> VPROG2BCNT */ | ||
86 | { | ||
87 | .address = 0x28, | ||
88 | .reg = 0x75, | ||
89 | .bit = VR_MODE_NORMAL, | ||
90 | }, /* VP2C -> VPROG2CCNT */ | ||
91 | { | ||
92 | .address = 0x2c, | ||
93 | .reg = 0x76, | ||
94 | .bit = VR_MODE_NORMAL, | ||
95 | }, /* VP3A -> VPROG3ACNT */ | ||
96 | { | ||
97 | .address = 0x30, | ||
98 | .reg = 0x77, | ||
99 | .bit = VR_MODE_NORMAL, | ||
100 | }, /* VP3B -> VPROG3BCNT */ | ||
101 | { | ||
102 | .address = 0x34, | ||
103 | .reg = 0x78, | ||
104 | .bit = VSWITCH2_OUTPUT, | ||
105 | }, /* VSW2 -> VLD0CNT Bit 5*/ | ||
106 | { | ||
107 | .address = 0x38, | ||
108 | .reg = 0x78, | ||
109 | .bit = VSWITCH1_OUTPUT, | ||
110 | }, /* VSW1 -> VLD0CNT Bit 4 */ | ||
111 | { | ||
112 | .address = 0x3c, | ||
113 | .reg = 0x78, | ||
114 | .bit = VUSBPHY_CHARGE, | ||
115 | }, /* VUPY -> VLDOCNT Bit 1 */ | ||
116 | { | ||
117 | .address = 0x40, | ||
118 | .reg = 0x7b, | ||
119 | .bit = VR_MODE_NORMAL, | ||
120 | }, /* VRSO -> VREFSOCCNT*/ | ||
121 | { | ||
122 | .address = 0x44, | ||
123 | .reg = 0xA0, | ||
124 | .bit = VR_MODE_NORMAL, | ||
125 | }, /* VP1E -> VPROG1ECNT */ | ||
126 | { | ||
127 | .address = 0x48, | ||
128 | .reg = 0xA1, | ||
129 | .bit = VR_MODE_NORMAL, | ||
130 | }, /* VP1F -> VPROG1FCNT */ | ||
131 | { | ||
132 | .address = 0x4c, | ||
133 | .reg = 0xA2, | ||
134 | .bit = VR_MODE_NORMAL, | ||
135 | }, /* VP2D -> VPROG2DCNT */ | ||
136 | { | ||
137 | .address = 0x50, | ||
138 | .reg = 0xA3, | ||
139 | .bit = VR_MODE_NORMAL, | ||
140 | }, /* VP4A -> VPROG4ACNT */ | ||
141 | { | ||
142 | .address = 0x54, | ||
143 | .reg = 0xA4, | ||
144 | .bit = VR_MODE_NORMAL, | ||
145 | }, /* VP4B -> VPROG4BCNT */ | ||
146 | { | ||
147 | .address = 0x58, | ||
148 | .reg = 0xA5, | ||
149 | .bit = VR_MODE_NORMAL, | ||
150 | }, /* VP4C -> VPROG4CCNT */ | ||
151 | { | ||
152 | .address = 0x5c, | ||
153 | .reg = 0xA6, | ||
154 | .bit = VR_MODE_NORMAL, | ||
155 | }, /* VP4D -> VPROG4DCNT */ | ||
156 | { | ||
157 | .address = 0x60, | ||
158 | .reg = 0xA7, | ||
159 | .bit = VR_MODE_NORMAL, | ||
160 | }, /* VP5A -> VPROG5ACNT */ | ||
161 | { | ||
162 | .address = 0x64, | ||
163 | .reg = 0xA8, | ||
164 | .bit = VR_MODE_NORMAL, | ||
165 | }, /* VP5B -> VPROG5BCNT */ | ||
166 | { | ||
167 | .address = 0x68, | ||
168 | .reg = 0xA9, | ||
169 | .bit = VR_MODE_NORMAL, | ||
170 | }, /* VP6A -> VPROG6ACNT */ | ||
171 | { | ||
172 | .address = 0x6c, | ||
173 | .reg = 0xAA, | ||
174 | .bit = VR_MODE_NORMAL, | ||
175 | }, /* VP6B -> VPROG6BCNT */ | ||
176 | { | ||
177 | .address = 0x70, | ||
178 | .reg = 0x36, | ||
179 | .bit = BIT(2), | ||
180 | }, /* SDWN_N -> MODEMCTRL Bit 2 */ | ||
181 | { | ||
182 | .address = 0x74, | ||
183 | .reg = 0x36, | ||
184 | .bit = BIT(0), | ||
185 | } /* MOFF -> MODEMCTRL Bit 0 */ | ||
186 | }; | ||
187 | |||
188 | static struct pmic_table thermal_table[] = { | ||
189 | { | ||
190 | .address = 0x00, | ||
191 | .reg = 0x4F39 | ||
192 | }, | ||
193 | { | ||
194 | .address = 0x04, | ||
195 | .reg = 0x4F24 | ||
196 | }, | ||
197 | { | ||
198 | .address = 0x08, | ||
199 | .reg = 0x4F26 | ||
200 | }, | ||
201 | { | ||
202 | .address = 0x0c, | ||
203 | .reg = 0x4F3B | ||
204 | }, | ||
205 | { | ||
206 | .address = 0x10, | ||
207 | .reg = 0x4F28 | ||
208 | }, | ||
209 | { | ||
210 | .address = 0x14, | ||
211 | .reg = 0x4F2A | ||
212 | }, | ||
213 | { | ||
214 | .address = 0x18, | ||
215 | .reg = 0x4F3D | ||
216 | }, | ||
217 | { | ||
218 | .address = 0x1c, | ||
219 | .reg = 0x4F2C | ||
220 | }, | ||
221 | { | ||
222 | .address = 0x20, | ||
223 | .reg = 0x4F2E | ||
224 | }, | ||
225 | { | ||
226 | .address = 0x24, | ||
227 | .reg = 0x4F3F | ||
228 | }, | ||
229 | { | ||
230 | .address = 0x28, | ||
231 | .reg = 0x4F30 | ||
232 | }, | ||
233 | { | ||
234 | .address = 0x30, | ||
235 | .reg = 0x4F41 | ||
236 | }, | ||
237 | { | ||
238 | .address = 0x34, | ||
239 | .reg = 0x4F32 | ||
240 | }, | ||
241 | { | ||
242 | .address = 0x3c, | ||
243 | .reg = 0x4F43 | ||
244 | }, | ||
245 | { | ||
246 | .address = 0x40, | ||
247 | .reg = 0x4F34 | ||
248 | }, | ||
249 | { | ||
250 | .address = 0x48, | ||
251 | .reg = 0x4F6A, | ||
252 | .bit = 0, | ||
253 | }, | ||
254 | { | ||
255 | .address = 0x4C, | ||
256 | .reg = 0x4F6A, | ||
257 | .bit = 1 | ||
258 | }, | ||
259 | { | ||
260 | .address = 0x50, | ||
261 | .reg = 0x4F6A, | ||
262 | .bit = 2 | ||
263 | }, | ||
264 | { | ||
265 | .address = 0x54, | ||
266 | .reg = 0x4F6A, | ||
267 | .bit = 4 | ||
268 | }, | ||
269 | { | ||
270 | .address = 0x58, | ||
271 | .reg = 0x4F6A, | ||
272 | .bit = 5 | ||
273 | }, | ||
274 | { | ||
275 | .address = 0x5C, | ||
276 | .reg = 0x4F6A, | ||
277 | .bit = 3 | ||
278 | }, | ||
279 | }; | ||
280 | |||
281 | static int intel_bxtwc_pmic_get_power(struct regmap *regmap, int reg, | ||
282 | int bit, u64 *value) | ||
283 | { | ||
284 | int data; | ||
285 | |||
286 | if (regmap_read(regmap, reg, &data)) | ||
287 | return -EIO; | ||
288 | |||
289 | *value = (data & bit) ? 1 : 0; | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int intel_bxtwc_pmic_update_power(struct regmap *regmap, int reg, | ||
294 | int bit, bool on) | ||
295 | { | ||
296 | u8 val, mask = bit; | ||
297 | |||
298 | if (on) | ||
299 | val = 0xFF; | ||
300 | else | ||
301 | val = 0x0; | ||
302 | |||
303 | return regmap_update_bits(regmap, reg, mask, val); | ||
304 | } | ||
305 | |||
306 | static int intel_bxtwc_pmic_get_raw_temp(struct regmap *regmap, int reg) | ||
307 | { | ||
308 | unsigned int val, adc_val, reg_val; | ||
309 | u8 temp_l, temp_h, cursrc; | ||
310 | unsigned long rlsb; | ||
311 | static const unsigned long rlsb_array[] = { | ||
312 | 0, 260420, 130210, 65100, 32550, 16280, | ||
313 | 8140, 4070, 2030, 0, 260420, 130210 }; | ||
314 | |||
315 | if (regmap_read(regmap, reg, &val)) | ||
316 | return -EIO; | ||
317 | temp_l = (u8) val; | ||
318 | |||
319 | if (regmap_read(regmap, (reg - 1), &val)) | ||
320 | return -EIO; | ||
321 | temp_h = (u8) val; | ||
322 | |||
323 | reg_val = temp_l | WHISKEY_COVE_ADC_HIGH_BIT(temp_h); | ||
324 | cursrc = WHISKEY_COVE_ADC_CURSRC(temp_h); | ||
325 | rlsb = rlsb_array[cursrc]; | ||
326 | adc_val = reg_val * rlsb / 1000; | ||
327 | |||
328 | return adc_val; | ||
329 | } | ||
330 | |||
331 | static int | ||
332 | intel_bxtwc_pmic_update_aux(struct regmap *regmap, int reg, int raw) | ||
333 | { | ||
334 | u32 bsr_num; | ||
335 | u16 resi_val, count = 0, thrsh = 0; | ||
336 | u8 alrt_h, alrt_l, cursel = 0; | ||
337 | |||
338 | bsr_num = raw; | ||
339 | bsr_num /= (1 << 5); | ||
340 | |||
341 | count = fls(bsr_num) - 1; | ||
342 | |||
343 | cursel = clamp_t(s8, (count - 7), 0, 7); | ||
344 | thrsh = raw / (1 << (4 + cursel)); | ||
345 | |||
346 | resi_val = (cursel << 9) | thrsh; | ||
347 | alrt_h = (resi_val >> 8) & WHISKEY_COVE_ALRT_HIGH_BIT_MASK; | ||
348 | if (regmap_update_bits(regmap, | ||
349 | reg - 1, | ||
350 | WHISKEY_COVE_ALRT_HIGH_BIT_MASK, | ||
351 | alrt_h)) | ||
352 | return -EIO; | ||
353 | |||
354 | alrt_l = (u8)resi_val; | ||
355 | return regmap_write(regmap, reg, alrt_l); | ||
356 | } | ||
357 | |||
358 | static int | ||
359 | intel_bxtwc_pmic_get_policy(struct regmap *regmap, int reg, int bit, u64 *value) | ||
360 | { | ||
361 | u8 mask = BIT(bit); | ||
362 | unsigned int val; | ||
363 | |||
364 | if (regmap_read(regmap, reg, &val)) | ||
365 | return -EIO; | ||
366 | |||
367 | *value = (val & mask) >> bit; | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int | ||
372 | intel_bxtwc_pmic_update_policy(struct regmap *regmap, | ||
373 | int reg, int bit, int enable) | ||
374 | { | ||
375 | u8 mask = BIT(bit), val = enable << bit; | ||
376 | |||
377 | return regmap_update_bits(regmap, reg, mask, val); | ||
378 | } | ||
379 | |||
380 | static struct intel_pmic_opregion_data intel_bxtwc_pmic_opregion_data = { | ||
381 | .get_power = intel_bxtwc_pmic_get_power, | ||
382 | .update_power = intel_bxtwc_pmic_update_power, | ||
383 | .get_raw_temp = intel_bxtwc_pmic_get_raw_temp, | ||
384 | .update_aux = intel_bxtwc_pmic_update_aux, | ||
385 | .get_policy = intel_bxtwc_pmic_get_policy, | ||
386 | .update_policy = intel_bxtwc_pmic_update_policy, | ||
387 | .power_table = power_table, | ||
388 | .power_table_count = ARRAY_SIZE(power_table), | ||
389 | .thermal_table = thermal_table, | ||
390 | .thermal_table_count = ARRAY_SIZE(thermal_table), | ||
391 | }; | ||
392 | |||
393 | static int intel_bxtwc_pmic_opregion_probe(struct platform_device *pdev) | ||
394 | { | ||
395 | struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); | ||
396 | |||
397 | return intel_pmic_install_opregion_handler(&pdev->dev, | ||
398 | ACPI_HANDLE(pdev->dev.parent), | ||
399 | pmic->regmap, | ||
400 | &intel_bxtwc_pmic_opregion_data); | ||
401 | } | ||
402 | |||
403 | static struct platform_device_id bxt_wc_opregion_id_table[] = { | ||
404 | { .name = "bxt_wcove_region" }, | ||
405 | {}, | ||
406 | }; | ||
407 | |||
408 | static struct platform_driver intel_bxtwc_pmic_opregion_driver = { | ||
409 | .probe = intel_bxtwc_pmic_opregion_probe, | ||
410 | .driver = { | ||
411 | .name = "bxt_whiskey_cove_pmic", | ||
412 | }, | ||
413 | .id_table = bxt_wc_opregion_id_table, | ||
414 | }; | ||
415 | |||
416 | static int __init intel_bxtwc_pmic_opregion_driver_init(void) | ||
417 | { | ||
418 | return platform_driver_register(&intel_bxtwc_pmic_opregion_driver); | ||
419 | } | ||
420 | device_initcall(intel_bxtwc_pmic_opregion_driver_init); | ||
diff --git a/drivers/acpi/pmic/intel_pmic_crc.c b/drivers/acpi/pmic/intel_pmic_crc.c index fcd1852dcdee..d7f1761ab1bc 100644 --- a/drivers/acpi/pmic/intel_pmic_crc.c +++ b/drivers/acpi/pmic/intel_pmic_crc.c | |||
@@ -141,7 +141,8 @@ static int intel_crc_pmic_update_aux(struct regmap *regmap, int reg, int raw) | |||
141 | regmap_update_bits(regmap, reg - 1, 0x3, raw >> 8) ? -EIO : 0; | 141 | regmap_update_bits(regmap, reg - 1, 0x3, raw >> 8) ? -EIO : 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int intel_crc_pmic_get_policy(struct regmap *regmap, int reg, u64 *value) | 144 | static int intel_crc_pmic_get_policy(struct regmap *regmap, |
145 | int reg, int bit, u64 *value) | ||
145 | { | 146 | { |
146 | int pen; | 147 | int pen; |
147 | 148 | ||
@@ -152,7 +153,7 @@ static int intel_crc_pmic_get_policy(struct regmap *regmap, int reg, u64 *value) | |||
152 | } | 153 | } |
153 | 154 | ||
154 | static int intel_crc_pmic_update_policy(struct regmap *regmap, | 155 | static int intel_crc_pmic_update_policy(struct regmap *regmap, |
155 | int reg, int enable) | 156 | int reg, int bit, int enable) |
156 | { | 157 | { |
157 | int alert0; | 158 | int alert0; |
158 | 159 | ||
diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c index 6a082d4de12c..e6e991ac20f3 100644 --- a/drivers/acpi/pmic/intel_pmic_xpower.c +++ b/drivers/acpi/pmic/intel_pmic_xpower.c | |||
@@ -13,7 +13,7 @@ | |||
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/init.h> |
17 | #include <linux/acpi.h> | 17 | #include <linux/acpi.h> |
18 | #include <linux/mfd/axp20x.h> | 18 | #include <linux/mfd/axp20x.h> |
19 | #include <linux/regmap.h> | 19 | #include <linux/regmap.h> |
@@ -262,7 +262,4 @@ static int __init intel_xpower_pmic_opregion_driver_init(void) | |||
262 | { | 262 | { |
263 | return platform_driver_register(&intel_xpower_pmic_opregion_driver); | 263 | return platform_driver_register(&intel_xpower_pmic_opregion_driver); |
264 | } | 264 | } |
265 | module_init(intel_xpower_pmic_opregion_driver_init); | 265 | device_initcall(intel_xpower_pmic_opregion_driver_init); |
266 | |||
267 | MODULE_DESCRIPTION("XPower AXP288 ACPI operation region driver"); | ||
268 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 33a38d604630..9125d7d96372 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -108,13 +108,12 @@ static int map_gicc_mpidr(struct acpi_subtable_header *entry, | |||
108 | return -EINVAL; | 108 | return -EINVAL; |
109 | } | 109 | } |
110 | 110 | ||
111 | static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) | 111 | static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, |
112 | int type, u32 acpi_id) | ||
112 | { | 113 | { |
113 | unsigned long madt_end, entry; | 114 | unsigned long madt_end, entry; |
114 | phys_cpuid_t phys_id = PHYS_CPUID_INVALID; /* CPU hardware ID */ | 115 | phys_cpuid_t phys_id = PHYS_CPUID_INVALID; /* CPU hardware ID */ |
115 | struct acpi_table_madt *madt; | ||
116 | 116 | ||
117 | madt = get_madt_table(); | ||
118 | if (!madt) | 117 | if (!madt) |
119 | return phys_id; | 118 | return phys_id; |
120 | 119 | ||
@@ -145,6 +144,25 @@ static phys_cpuid_t map_madt_entry(int type, u32 acpi_id) | |||
145 | return phys_id; | 144 | return phys_id; |
146 | } | 145 | } |
147 | 146 | ||
147 | phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id) | ||
148 | { | ||
149 | struct acpi_table_madt *madt = NULL; | ||
150 | acpi_size tbl_size; | ||
151 | phys_cpuid_t rv; | ||
152 | |||
153 | acpi_get_table_with_size(ACPI_SIG_MADT, 0, | ||
154 | (struct acpi_table_header **)&madt, | ||
155 | &tbl_size); | ||
156 | if (!madt) | ||
157 | return PHYS_CPUID_INVALID; | ||
158 | |||
159 | rv = map_madt_entry(madt, 1, acpi_id); | ||
160 | |||
161 | early_acpi_os_unmap_memory(madt, tbl_size); | ||
162 | |||
163 | return rv; | ||
164 | } | ||
165 | |||
148 | static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) | 166 | static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) |
149 | { | 167 | { |
150 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 168 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
@@ -185,7 +203,7 @@ phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id) | |||
185 | 203 | ||
186 | phys_id = map_mat_entry(handle, type, acpi_id); | 204 | phys_id = map_mat_entry(handle, type, acpi_id); |
187 | if (invalid_phys_cpuid(phys_id)) | 205 | if (invalid_phys_cpuid(phys_id)) |
188 | phys_id = map_madt_entry(type, acpi_id); | 206 | phys_id = map_madt_entry(get_madt_table(), type, acpi_id); |
189 | 207 | ||
190 | return phys_id; | 208 | return phys_id; |
191 | } | 209 | } |
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index d2fa8cb82d2b..0ca14ac7bb28 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -90,7 +90,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) | |||
90 | pr->performance_platform_limit); | 90 | pr->performance_platform_limit); |
91 | break; | 91 | break; |
92 | case ACPI_PROCESSOR_NOTIFY_POWER: | 92 | case ACPI_PROCESSOR_NOTIFY_POWER: |
93 | acpi_processor_cst_has_changed(pr); | 93 | acpi_processor_power_state_has_changed(pr); |
94 | acpi_bus_generate_netlink_event(device->pnp.device_class, | 94 | acpi_bus_generate_netlink_event(device->pnp.device_class, |
95 | dev_name(&device->dev), event, 0); | 95 | dev_name(&device->dev), event, 0); |
96 | break; | 96 | break; |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 444e3745c8b3..cea52528aa18 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -59,6 +59,12 @@ module_param(latency_factor, uint, 0644); | |||
59 | 59 | ||
60 | static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); | 60 | static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); |
61 | 61 | ||
62 | struct cpuidle_driver acpi_idle_driver = { | ||
63 | .name = "acpi_idle", | ||
64 | .owner = THIS_MODULE, | ||
65 | }; | ||
66 | |||
67 | #ifdef CONFIG_ACPI_PROCESSOR_CSTATE | ||
62 | static | 68 | static |
63 | DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); | 69 | DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); |
64 | 70 | ||
@@ -297,7 +303,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | |||
297 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 303 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
298 | union acpi_object *cst; | 304 | union acpi_object *cst; |
299 | 305 | ||
300 | |||
301 | if (nocst) | 306 | if (nocst) |
302 | return -ENODEV; | 307 | return -ENODEV; |
303 | 308 | ||
@@ -570,7 +575,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
570 | return (working); | 575 | return (working); |
571 | } | 576 | } |
572 | 577 | ||
573 | static int acpi_processor_get_power_info(struct acpi_processor *pr) | 578 | static int acpi_processor_get_cstate_info(struct acpi_processor *pr) |
574 | { | 579 | { |
575 | unsigned int i; | 580 | unsigned int i; |
576 | int result; | 581 | int result; |
@@ -804,36 +809,12 @@ static void acpi_idle_enter_freeze(struct cpuidle_device *dev, | |||
804 | acpi_idle_do_entry(cx); | 809 | acpi_idle_do_entry(cx); |
805 | } | 810 | } |
806 | 811 | ||
807 | struct cpuidle_driver acpi_idle_driver = { | ||
808 | .name = "acpi_idle", | ||
809 | .owner = THIS_MODULE, | ||
810 | }; | ||
811 | |||
812 | /** | ||
813 | * acpi_processor_setup_cpuidle_cx - prepares and configures CPUIDLE | ||
814 | * device i.e. per-cpu data | ||
815 | * | ||
816 | * @pr: the ACPI processor | ||
817 | * @dev : the cpuidle device | ||
818 | */ | ||
819 | static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, | 812 | static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, |
820 | struct cpuidle_device *dev) | 813 | struct cpuidle_device *dev) |
821 | { | 814 | { |
822 | int i, count = CPUIDLE_DRIVER_STATE_START; | 815 | int i, count = CPUIDLE_DRIVER_STATE_START; |
823 | struct acpi_processor_cx *cx; | 816 | struct acpi_processor_cx *cx; |
824 | 817 | ||
825 | if (!pr->flags.power_setup_done) | ||
826 | return -EINVAL; | ||
827 | |||
828 | if (pr->flags.power == 0) { | ||
829 | return -EINVAL; | ||
830 | } | ||
831 | |||
832 | if (!dev) | ||
833 | return -EINVAL; | ||
834 | |||
835 | dev->cpu = pr->id; | ||
836 | |||
837 | if (max_cstate == 0) | 818 | if (max_cstate == 0) |
838 | max_cstate = 1; | 819 | max_cstate = 1; |
839 | 820 | ||
@@ -856,31 +837,13 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, | |||
856 | return 0; | 837 | return 0; |
857 | } | 838 | } |
858 | 839 | ||
859 | /** | 840 | static int acpi_processor_setup_cstates(struct acpi_processor *pr) |
860 | * acpi_processor_setup_cpuidle states- prepares and configures cpuidle | ||
861 | * global state data i.e. idle routines | ||
862 | * | ||
863 | * @pr: the ACPI processor | ||
864 | */ | ||
865 | static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | ||
866 | { | 841 | { |
867 | int i, count = CPUIDLE_DRIVER_STATE_START; | 842 | int i, count = CPUIDLE_DRIVER_STATE_START; |
868 | struct acpi_processor_cx *cx; | 843 | struct acpi_processor_cx *cx; |
869 | struct cpuidle_state *state; | 844 | struct cpuidle_state *state; |
870 | struct cpuidle_driver *drv = &acpi_idle_driver; | 845 | struct cpuidle_driver *drv = &acpi_idle_driver; |
871 | 846 | ||
872 | if (!pr->flags.power_setup_done) | ||
873 | return -EINVAL; | ||
874 | |||
875 | if (pr->flags.power == 0) | ||
876 | return -EINVAL; | ||
877 | |||
878 | drv->safe_state_index = -1; | ||
879 | for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) { | ||
880 | drv->states[i].name[0] = '\0'; | ||
881 | drv->states[i].desc[0] = '\0'; | ||
882 | } | ||
883 | |||
884 | if (max_cstate == 0) | 847 | if (max_cstate == 0) |
885 | max_cstate = 1; | 848 | max_cstate = 1; |
886 | 849 | ||
@@ -892,7 +855,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | |||
892 | 855 | ||
893 | state = &drv->states[count]; | 856 | state = &drv->states[count]; |
894 | snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); | 857 | snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); |
895 | strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); | 858 | strlcpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); |
896 | state->exit_latency = cx->latency; | 859 | state->exit_latency = cx->latency; |
897 | state->target_residency = cx->latency * latency_factor; | 860 | state->target_residency = cx->latency * latency_factor; |
898 | state->enter = acpi_idle_enter; | 861 | state->enter = acpi_idle_enter; |
@@ -925,6 +888,450 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | |||
925 | return 0; | 888 | return 0; |
926 | } | 889 | } |
927 | 890 | ||
891 | static inline void acpi_processor_cstate_first_run_checks(void) | ||
892 | { | ||
893 | acpi_status status; | ||
894 | static int first_run; | ||
895 | |||
896 | if (first_run) | ||
897 | return; | ||
898 | dmi_check_system(processor_power_dmi_table); | ||
899 | max_cstate = acpi_processor_cstate_check(max_cstate); | ||
900 | if (max_cstate < ACPI_C_STATES_MAX) | ||
901 | pr_notice("ACPI: processor limited to max C-state %d\n", | ||
902 | max_cstate); | ||
903 | first_run++; | ||
904 | |||
905 | if (acpi_gbl_FADT.cst_control && !nocst) { | ||
906 | status = acpi_os_write_port(acpi_gbl_FADT.smi_command, | ||
907 | acpi_gbl_FADT.cst_control, 8); | ||
908 | if (ACPI_FAILURE(status)) | ||
909 | ACPI_EXCEPTION((AE_INFO, status, | ||
910 | "Notifying BIOS of _CST ability failed")); | ||
911 | } | ||
912 | } | ||
913 | #else | ||
914 | |||
915 | static inline int disabled_by_idle_boot_param(void) { return 0; } | ||
916 | static inline void acpi_processor_cstate_first_run_checks(void) { } | ||
917 | static int acpi_processor_get_cstate_info(struct acpi_processor *pr) | ||
918 | { | ||
919 | return -ENODEV; | ||
920 | } | ||
921 | |||
922 | static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, | ||
923 | struct cpuidle_device *dev) | ||
924 | { | ||
925 | return -EINVAL; | ||
926 | } | ||
927 | |||
928 | static int acpi_processor_setup_cstates(struct acpi_processor *pr) | ||
929 | { | ||
930 | return -EINVAL; | ||
931 | } | ||
932 | |||
933 | #endif /* CONFIG_ACPI_PROCESSOR_CSTATE */ | ||
934 | |||
935 | struct acpi_lpi_states_array { | ||
936 | unsigned int size; | ||
937 | unsigned int composite_states_size; | ||
938 | struct acpi_lpi_state *entries; | ||
939 | struct acpi_lpi_state *composite_states[ACPI_PROCESSOR_MAX_POWER]; | ||
940 | }; | ||
941 | |||
942 | static int obj_get_integer(union acpi_object *obj, u32 *value) | ||
943 | { | ||
944 | if (obj->type != ACPI_TYPE_INTEGER) | ||
945 | return -EINVAL; | ||
946 | |||
947 | *value = obj->integer.value; | ||
948 | return 0; | ||
949 | } | ||
950 | |||
951 | static int acpi_processor_evaluate_lpi(acpi_handle handle, | ||
952 | struct acpi_lpi_states_array *info) | ||
953 | { | ||
954 | acpi_status status; | ||
955 | int ret = 0; | ||
956 | int pkg_count, state_idx = 1, loop; | ||
957 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
958 | union acpi_object *lpi_data; | ||
959 | struct acpi_lpi_state *lpi_state; | ||
960 | |||
961 | status = acpi_evaluate_object(handle, "_LPI", NULL, &buffer); | ||
962 | if (ACPI_FAILURE(status)) { | ||
963 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No _LPI, giving up\n")); | ||
964 | return -ENODEV; | ||
965 | } | ||
966 | |||
967 | lpi_data = buffer.pointer; | ||
968 | |||
969 | /* There must be at least 4 elements = 3 elements + 1 package */ | ||
970 | if (!lpi_data || lpi_data->type != ACPI_TYPE_PACKAGE || | ||
971 | lpi_data->package.count < 4) { | ||
972 | pr_debug("not enough elements in _LPI\n"); | ||
973 | ret = -ENODATA; | ||
974 | goto end; | ||
975 | } | ||
976 | |||
977 | pkg_count = lpi_data->package.elements[2].integer.value; | ||
978 | |||
979 | /* Validate number of power states. */ | ||
980 | if (pkg_count < 1 || pkg_count != lpi_data->package.count - 3) { | ||
981 | pr_debug("count given by _LPI is not valid\n"); | ||
982 | ret = -ENODATA; | ||
983 | goto end; | ||
984 | } | ||
985 | |||
986 | lpi_state = kcalloc(pkg_count, sizeof(*lpi_state), GFP_KERNEL); | ||
987 | if (!lpi_state) { | ||
988 | ret = -ENOMEM; | ||
989 | goto end; | ||
990 | } | ||
991 | |||
992 | info->size = pkg_count; | ||
993 | info->entries = lpi_state; | ||
994 | |||
995 | /* LPI States start at index 3 */ | ||
996 | for (loop = 3; state_idx <= pkg_count; loop++, state_idx++, lpi_state++) { | ||
997 | union acpi_object *element, *pkg_elem, *obj; | ||
998 | |||
999 | element = &lpi_data->package.elements[loop]; | ||
1000 | if (element->type != ACPI_TYPE_PACKAGE || element->package.count < 7) | ||
1001 | continue; | ||
1002 | |||
1003 | pkg_elem = element->package.elements; | ||
1004 | |||
1005 | obj = pkg_elem + 6; | ||
1006 | if (obj->type == ACPI_TYPE_BUFFER) { | ||
1007 | struct acpi_power_register *reg; | ||
1008 | |||
1009 | reg = (struct acpi_power_register *)obj->buffer.pointer; | ||
1010 | if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO && | ||
1011 | reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) | ||
1012 | continue; | ||
1013 | |||
1014 | lpi_state->address = reg->address; | ||
1015 | lpi_state->entry_method = | ||
1016 | reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE ? | ||
1017 | ACPI_CSTATE_FFH : ACPI_CSTATE_SYSTEMIO; | ||
1018 | } else if (obj->type == ACPI_TYPE_INTEGER) { | ||
1019 | lpi_state->entry_method = ACPI_CSTATE_INTEGER; | ||
1020 | lpi_state->address = obj->integer.value; | ||
1021 | } else { | ||
1022 | continue; | ||
1023 | } | ||
1024 | |||
1025 | /* elements[7,8] skipped for now i.e. Residency/Usage counter*/ | ||
1026 | |||
1027 | obj = pkg_elem + 9; | ||
1028 | if (obj->type == ACPI_TYPE_STRING) | ||
1029 | strlcpy(lpi_state->desc, obj->string.pointer, | ||
1030 | ACPI_CX_DESC_LEN); | ||
1031 | |||
1032 | lpi_state->index = state_idx; | ||
1033 | if (obj_get_integer(pkg_elem + 0, &lpi_state->min_residency)) { | ||
1034 | pr_debug("No min. residency found, assuming 10 us\n"); | ||
1035 | lpi_state->min_residency = 10; | ||
1036 | } | ||
1037 | |||
1038 | if (obj_get_integer(pkg_elem + 1, &lpi_state->wake_latency)) { | ||
1039 | pr_debug("No wakeup residency found, assuming 10 us\n"); | ||
1040 | lpi_state->wake_latency = 10; | ||
1041 | } | ||
1042 | |||
1043 | if (obj_get_integer(pkg_elem + 2, &lpi_state->flags)) | ||
1044 | lpi_state->flags = 0; | ||
1045 | |||
1046 | if (obj_get_integer(pkg_elem + 3, &lpi_state->arch_flags)) | ||
1047 | lpi_state->arch_flags = 0; | ||
1048 | |||
1049 | if (obj_get_integer(pkg_elem + 4, &lpi_state->res_cnt_freq)) | ||
1050 | lpi_state->res_cnt_freq = 1; | ||
1051 | |||
1052 | if (obj_get_integer(pkg_elem + 5, &lpi_state->enable_parent_state)) | ||
1053 | lpi_state->enable_parent_state = 0; | ||
1054 | } | ||
1055 | |||
1056 | acpi_handle_debug(handle, "Found %d power states\n", state_idx); | ||
1057 | end: | ||
1058 | kfree(buffer.pointer); | ||
1059 | return ret; | ||
1060 | } | ||
1061 | |||
1062 | /* | ||
1063 | * flat_state_cnt - the number of composite LPI states after the process of flattening | ||
1064 | */ | ||
1065 | static int flat_state_cnt; | ||
1066 | |||
1067 | /** | ||
1068 | * combine_lpi_states - combine local and parent LPI states to form a composite LPI state | ||
1069 | * | ||
1070 | * @local: local LPI state | ||
1071 | * @parent: parent LPI state | ||
1072 | * @result: composite LPI state | ||
1073 | */ | ||
1074 | static bool combine_lpi_states(struct acpi_lpi_state *local, | ||
1075 | struct acpi_lpi_state *parent, | ||
1076 | struct acpi_lpi_state *result) | ||
1077 | { | ||
1078 | if (parent->entry_method == ACPI_CSTATE_INTEGER) { | ||
1079 | if (!parent->address) /* 0 means autopromotable */ | ||
1080 | return false; | ||
1081 | result->address = local->address + parent->address; | ||
1082 | } else { | ||
1083 | result->address = parent->address; | ||
1084 | } | ||
1085 | |||
1086 | result->min_residency = max(local->min_residency, parent->min_residency); | ||
1087 | result->wake_latency = local->wake_latency + parent->wake_latency; | ||
1088 | result->enable_parent_state = parent->enable_parent_state; | ||
1089 | result->entry_method = local->entry_method; | ||
1090 | |||
1091 | result->flags = parent->flags; | ||
1092 | result->arch_flags = parent->arch_flags; | ||
1093 | result->index = parent->index; | ||
1094 | |||
1095 | strlcpy(result->desc, local->desc, ACPI_CX_DESC_LEN); | ||
1096 | strlcat(result->desc, "+", ACPI_CX_DESC_LEN); | ||
1097 | strlcat(result->desc, parent->desc, ACPI_CX_DESC_LEN); | ||
1098 | return true; | ||
1099 | } | ||
1100 | |||
1101 | #define ACPI_LPI_STATE_FLAGS_ENABLED BIT(0) | ||
1102 | |||
1103 | static void stash_composite_state(struct acpi_lpi_states_array *curr_level, | ||
1104 | struct acpi_lpi_state *t) | ||
1105 | { | ||
1106 | curr_level->composite_states[curr_level->composite_states_size++] = t; | ||
1107 | } | ||
1108 | |||
1109 | static int flatten_lpi_states(struct acpi_processor *pr, | ||
1110 | struct acpi_lpi_states_array *curr_level, | ||
1111 | struct acpi_lpi_states_array *prev_level) | ||
1112 | { | ||
1113 | int i, j, state_count = curr_level->size; | ||
1114 | struct acpi_lpi_state *p, *t = curr_level->entries; | ||
1115 | |||
1116 | curr_level->composite_states_size = 0; | ||
1117 | for (j = 0; j < state_count; j++, t++) { | ||
1118 | struct acpi_lpi_state *flpi; | ||
1119 | |||
1120 | if (!(t->flags & ACPI_LPI_STATE_FLAGS_ENABLED)) | ||
1121 | continue; | ||
1122 | |||
1123 | if (flat_state_cnt >= ACPI_PROCESSOR_MAX_POWER) { | ||
1124 | pr_warn("Limiting number of LPI states to max (%d)\n", | ||
1125 | ACPI_PROCESSOR_MAX_POWER); | ||
1126 | pr_warn("Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n"); | ||
1127 | break; | ||
1128 | } | ||
1129 | |||
1130 | flpi = &pr->power.lpi_states[flat_state_cnt]; | ||
1131 | |||
1132 | if (!prev_level) { /* leaf/processor node */ | ||
1133 | memcpy(flpi, t, sizeof(*t)); | ||
1134 | stash_composite_state(curr_level, flpi); | ||
1135 | flat_state_cnt++; | ||
1136 | continue; | ||
1137 | } | ||
1138 | |||
1139 | for (i = 0; i < prev_level->composite_states_size; i++) { | ||
1140 | p = prev_level->composite_states[i]; | ||
1141 | if (t->index <= p->enable_parent_state && | ||
1142 | combine_lpi_states(p, t, flpi)) { | ||
1143 | stash_composite_state(curr_level, flpi); | ||
1144 | flat_state_cnt++; | ||
1145 | flpi++; | ||
1146 | } | ||
1147 | } | ||
1148 | } | ||
1149 | |||
1150 | kfree(curr_level->entries); | ||
1151 | return 0; | ||
1152 | } | ||
1153 | |||
1154 | static int acpi_processor_get_lpi_info(struct acpi_processor *pr) | ||
1155 | { | ||
1156 | int ret, i; | ||
1157 | acpi_status status; | ||
1158 | acpi_handle handle = pr->handle, pr_ahandle; | ||
1159 | struct acpi_device *d = NULL; | ||
1160 | struct acpi_lpi_states_array info[2], *tmp, *prev, *curr; | ||
1161 | |||
1162 | if (!osc_pc_lpi_support_confirmed) | ||
1163 | return -EOPNOTSUPP; | ||
1164 | |||
1165 | if (!acpi_has_method(handle, "_LPI")) | ||
1166 | return -EINVAL; | ||
1167 | |||
1168 | flat_state_cnt = 0; | ||
1169 | prev = &info[0]; | ||
1170 | curr = &info[1]; | ||
1171 | handle = pr->handle; | ||
1172 | ret = acpi_processor_evaluate_lpi(handle, prev); | ||
1173 | if (ret) | ||
1174 | return ret; | ||
1175 | flatten_lpi_states(pr, prev, NULL); | ||
1176 | |||
1177 | status = acpi_get_parent(handle, &pr_ahandle); | ||
1178 | while (ACPI_SUCCESS(status)) { | ||
1179 | acpi_bus_get_device(pr_ahandle, &d); | ||
1180 | handle = pr_ahandle; | ||
1181 | |||
1182 | if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID)) | ||
1183 | break; | ||
1184 | |||
1185 | /* can be optional ? */ | ||
1186 | if (!acpi_has_method(handle, "_LPI")) | ||
1187 | break; | ||
1188 | |||
1189 | ret = acpi_processor_evaluate_lpi(handle, curr); | ||
1190 | if (ret) | ||
1191 | break; | ||
1192 | |||
1193 | /* flatten all the LPI states in this level of hierarchy */ | ||
1194 | flatten_lpi_states(pr, curr, prev); | ||
1195 | |||
1196 | tmp = prev, prev = curr, curr = tmp; | ||
1197 | |||
1198 | status = acpi_get_parent(handle, &pr_ahandle); | ||
1199 | } | ||
1200 | |||
1201 | pr->power.count = flat_state_cnt; | ||
1202 | /* reset the index after flattening */ | ||
1203 | for (i = 0; i < pr->power.count; i++) | ||
1204 | pr->power.lpi_states[i].index = i; | ||
1205 | |||
1206 | /* Tell driver that _LPI is supported. */ | ||
1207 | pr->flags.has_lpi = 1; | ||
1208 | pr->flags.power = 1; | ||
1209 | |||
1210 | return 0; | ||
1211 | } | ||
1212 | |||
1213 | int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu) | ||
1214 | { | ||
1215 | return -ENODEV; | ||
1216 | } | ||
1217 | |||
1218 | int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi) | ||
1219 | { | ||
1220 | return -ENODEV; | ||
1221 | } | ||
1222 | |||
1223 | /** | ||
1224 | * acpi_idle_lpi_enter - enters an ACPI any LPI state | ||
1225 | * @dev: the target CPU | ||
1226 | * @drv: cpuidle driver containing cpuidle state info | ||
1227 | * @index: index of target state | ||
1228 | * | ||
1229 | * Return: 0 for success or negative value for error | ||
1230 | */ | ||
1231 | static int acpi_idle_lpi_enter(struct cpuidle_device *dev, | ||
1232 | struct cpuidle_driver *drv, int index) | ||
1233 | { | ||
1234 | struct acpi_processor *pr; | ||
1235 | struct acpi_lpi_state *lpi; | ||
1236 | |||
1237 | pr = __this_cpu_read(processors); | ||
1238 | |||
1239 | if (unlikely(!pr)) | ||
1240 | return -EINVAL; | ||
1241 | |||
1242 | lpi = &pr->power.lpi_states[index]; | ||
1243 | if (lpi->entry_method == ACPI_CSTATE_FFH) | ||
1244 | return acpi_processor_ffh_lpi_enter(lpi); | ||
1245 | |||
1246 | return -EINVAL; | ||
1247 | } | ||
1248 | |||
1249 | static int acpi_processor_setup_lpi_states(struct acpi_processor *pr) | ||
1250 | { | ||
1251 | int i; | ||
1252 | struct acpi_lpi_state *lpi; | ||
1253 | struct cpuidle_state *state; | ||
1254 | struct cpuidle_driver *drv = &acpi_idle_driver; | ||
1255 | |||
1256 | if (!pr->flags.has_lpi) | ||
1257 | return -EOPNOTSUPP; | ||
1258 | |||
1259 | for (i = 0; i < pr->power.count && i < CPUIDLE_STATE_MAX; i++) { | ||
1260 | lpi = &pr->power.lpi_states[i]; | ||
1261 | |||
1262 | state = &drv->states[i]; | ||
1263 | snprintf(state->name, CPUIDLE_NAME_LEN, "LPI-%d", i); | ||
1264 | strlcpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN); | ||
1265 | state->exit_latency = lpi->wake_latency; | ||
1266 | state->target_residency = lpi->min_residency; | ||
1267 | if (lpi->arch_flags) | ||
1268 | state->flags |= CPUIDLE_FLAG_TIMER_STOP; | ||
1269 | state->enter = acpi_idle_lpi_enter; | ||
1270 | drv->safe_state_index = i; | ||
1271 | } | ||
1272 | |||
1273 | drv->state_count = i; | ||
1274 | |||
1275 | return 0; | ||
1276 | } | ||
1277 | |||
1278 | /** | ||
1279 | * acpi_processor_setup_cpuidle_states- prepares and configures cpuidle | ||
1280 | * global state data i.e. idle routines | ||
1281 | * | ||
1282 | * @pr: the ACPI processor | ||
1283 | */ | ||
1284 | static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | ||
1285 | { | ||
1286 | int i; | ||
1287 | struct cpuidle_driver *drv = &acpi_idle_driver; | ||
1288 | |||
1289 | if (!pr->flags.power_setup_done || !pr->flags.power) | ||
1290 | return -EINVAL; | ||
1291 | |||
1292 | drv->safe_state_index = -1; | ||
1293 | for (i = CPUIDLE_DRIVER_STATE_START; i < CPUIDLE_STATE_MAX; i++) { | ||
1294 | drv->states[i].name[0] = '\0'; | ||
1295 | drv->states[i].desc[0] = '\0'; | ||
1296 | } | ||
1297 | |||
1298 | if (pr->flags.has_lpi) | ||
1299 | return acpi_processor_setup_lpi_states(pr); | ||
1300 | |||
1301 | return acpi_processor_setup_cstates(pr); | ||
1302 | } | ||
1303 | |||
1304 | /** | ||
1305 | * acpi_processor_setup_cpuidle_dev - prepares and configures CPUIDLE | ||
1306 | * device i.e. per-cpu data | ||
1307 | * | ||
1308 | * @pr: the ACPI processor | ||
1309 | * @dev : the cpuidle device | ||
1310 | */ | ||
1311 | static int acpi_processor_setup_cpuidle_dev(struct acpi_processor *pr, | ||
1312 | struct cpuidle_device *dev) | ||
1313 | { | ||
1314 | if (!pr->flags.power_setup_done || !pr->flags.power || !dev) | ||
1315 | return -EINVAL; | ||
1316 | |||
1317 | dev->cpu = pr->id; | ||
1318 | if (pr->flags.has_lpi) | ||
1319 | return acpi_processor_ffh_lpi_probe(pr->id); | ||
1320 | |||
1321 | return acpi_processor_setup_cpuidle_cx(pr, dev); | ||
1322 | } | ||
1323 | |||
1324 | static int acpi_processor_get_power_info(struct acpi_processor *pr) | ||
1325 | { | ||
1326 | int ret; | ||
1327 | |||
1328 | ret = acpi_processor_get_lpi_info(pr); | ||
1329 | if (ret) | ||
1330 | ret = acpi_processor_get_cstate_info(pr); | ||
1331 | |||
1332 | return ret; | ||
1333 | } | ||
1334 | |||
928 | int acpi_processor_hotplug(struct acpi_processor *pr) | 1335 | int acpi_processor_hotplug(struct acpi_processor *pr) |
929 | { | 1336 | { |
930 | int ret = 0; | 1337 | int ret = 0; |
@@ -933,18 +1340,15 @@ int acpi_processor_hotplug(struct acpi_processor *pr) | |||
933 | if (disabled_by_idle_boot_param()) | 1340 | if (disabled_by_idle_boot_param()) |
934 | return 0; | 1341 | return 0; |
935 | 1342 | ||
936 | if (nocst) | ||
937 | return -ENODEV; | ||
938 | |||
939 | if (!pr->flags.power_setup_done) | 1343 | if (!pr->flags.power_setup_done) |
940 | return -ENODEV; | 1344 | return -ENODEV; |
941 | 1345 | ||
942 | dev = per_cpu(acpi_cpuidle_device, pr->id); | 1346 | dev = per_cpu(acpi_cpuidle_device, pr->id); |
943 | cpuidle_pause_and_lock(); | 1347 | cpuidle_pause_and_lock(); |
944 | cpuidle_disable_device(dev); | 1348 | cpuidle_disable_device(dev); |
945 | acpi_processor_get_power_info(pr); | 1349 | ret = acpi_processor_get_power_info(pr); |
946 | if (pr->flags.power) { | 1350 | if (!ret && pr->flags.power) { |
947 | acpi_processor_setup_cpuidle_cx(pr, dev); | 1351 | acpi_processor_setup_cpuidle_dev(pr, dev); |
948 | ret = cpuidle_enable_device(dev); | 1352 | ret = cpuidle_enable_device(dev); |
949 | } | 1353 | } |
950 | cpuidle_resume_and_unlock(); | 1354 | cpuidle_resume_and_unlock(); |
@@ -952,7 +1356,7 @@ int acpi_processor_hotplug(struct acpi_processor *pr) | |||
952 | return ret; | 1356 | return ret; |
953 | } | 1357 | } |
954 | 1358 | ||
955 | int acpi_processor_cst_has_changed(struct acpi_processor *pr) | 1359 | int acpi_processor_power_state_has_changed(struct acpi_processor *pr) |
956 | { | 1360 | { |
957 | int cpu; | 1361 | int cpu; |
958 | struct acpi_processor *_pr; | 1362 | struct acpi_processor *_pr; |
@@ -961,9 +1365,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
961 | if (disabled_by_idle_boot_param()) | 1365 | if (disabled_by_idle_boot_param()) |
962 | return 0; | 1366 | return 0; |
963 | 1367 | ||
964 | if (nocst) | ||
965 | return -ENODEV; | ||
966 | |||
967 | if (!pr->flags.power_setup_done) | 1368 | if (!pr->flags.power_setup_done) |
968 | return -ENODEV; | 1369 | return -ENODEV; |
969 | 1370 | ||
@@ -1000,7 +1401,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1000 | acpi_processor_get_power_info(_pr); | 1401 | acpi_processor_get_power_info(_pr); |
1001 | if (_pr->flags.power) { | 1402 | if (_pr->flags.power) { |
1002 | dev = per_cpu(acpi_cpuidle_device, cpu); | 1403 | dev = per_cpu(acpi_cpuidle_device, cpu); |
1003 | acpi_processor_setup_cpuidle_cx(_pr, dev); | 1404 | acpi_processor_setup_cpuidle_dev(_pr, dev); |
1004 | cpuidle_enable_device(dev); | 1405 | cpuidle_enable_device(dev); |
1005 | } | 1406 | } |
1006 | } | 1407 | } |
@@ -1015,35 +1416,16 @@ static int acpi_processor_registered; | |||
1015 | 1416 | ||
1016 | int acpi_processor_power_init(struct acpi_processor *pr) | 1417 | int acpi_processor_power_init(struct acpi_processor *pr) |
1017 | { | 1418 | { |
1018 | acpi_status status; | ||
1019 | int retval; | 1419 | int retval; |
1020 | struct cpuidle_device *dev; | 1420 | struct cpuidle_device *dev; |
1021 | static int first_run; | ||
1022 | 1421 | ||
1023 | if (disabled_by_idle_boot_param()) | 1422 | if (disabled_by_idle_boot_param()) |
1024 | return 0; | 1423 | return 0; |
1025 | 1424 | ||
1026 | if (!first_run) { | 1425 | acpi_processor_cstate_first_run_checks(); |
1027 | dmi_check_system(processor_power_dmi_table); | ||
1028 | max_cstate = acpi_processor_cstate_check(max_cstate); | ||
1029 | if (max_cstate < ACPI_C_STATES_MAX) | ||
1030 | printk(KERN_NOTICE | ||
1031 | "ACPI: processor limited to max C-state %d\n", | ||
1032 | max_cstate); | ||
1033 | first_run++; | ||
1034 | } | ||
1035 | |||
1036 | if (acpi_gbl_FADT.cst_control && !nocst) { | ||
1037 | status = | ||
1038 | acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8); | ||
1039 | if (ACPI_FAILURE(status)) { | ||
1040 | ACPI_EXCEPTION((AE_INFO, status, | ||
1041 | "Notifying BIOS of _CST ability failed")); | ||
1042 | } | ||
1043 | } | ||
1044 | 1426 | ||
1045 | acpi_processor_get_power_info(pr); | 1427 | if (!acpi_processor_get_power_info(pr)) |
1046 | pr->flags.power_setup_done = 1; | 1428 | pr->flags.power_setup_done = 1; |
1047 | 1429 | ||
1048 | /* | 1430 | /* |
1049 | * Install the idle handler if processor power management is supported. | 1431 | * Install the idle handler if processor power management is supported. |
@@ -1066,7 +1448,7 @@ int acpi_processor_power_init(struct acpi_processor *pr) | |||
1066 | return -ENOMEM; | 1448 | return -ENOMEM; |
1067 | per_cpu(acpi_cpuidle_device, pr->id) = dev; | 1449 | per_cpu(acpi_cpuidle_device, pr->id) = dev; |
1068 | 1450 | ||
1069 | acpi_processor_setup_cpuidle_cx(pr, dev); | 1451 | acpi_processor_setup_cpuidle_dev(pr, dev); |
1070 | 1452 | ||
1071 | /* Register per-cpu cpuidle_device. Cpuidle driver | 1453 | /* Register per-cpu cpuidle_device. Cpuidle driver |
1072 | * must already be registered before registering device | 1454 | * must already be registered before registering device |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5f28cf778349..405056b95b05 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -494,6 +494,8 @@ static void acpi_device_del(struct acpi_device *device) | |||
494 | device_del(&device->dev); | 494 | device_del(&device->dev); |
495 | } | 495 | } |
496 | 496 | ||
497 | static BLOCKING_NOTIFIER_HEAD(acpi_reconfig_chain); | ||
498 | |||
497 | static LIST_HEAD(acpi_device_del_list); | 499 | static LIST_HEAD(acpi_device_del_list); |
498 | static DEFINE_MUTEX(acpi_device_del_lock); | 500 | static DEFINE_MUTEX(acpi_device_del_lock); |
499 | 501 | ||
@@ -514,6 +516,9 @@ static void acpi_device_del_work_fn(struct work_struct *work_not_used) | |||
514 | 516 | ||
515 | mutex_unlock(&acpi_device_del_lock); | 517 | mutex_unlock(&acpi_device_del_lock); |
516 | 518 | ||
519 | blocking_notifier_call_chain(&acpi_reconfig_chain, | ||
520 | ACPI_RECONFIG_DEVICE_REMOVE, adev); | ||
521 | |||
517 | acpi_device_del(adev); | 522 | acpi_device_del(adev); |
518 | /* | 523 | /* |
519 | * Drop references to all power resources that might have been | 524 | * Drop references to all power resources that might have been |
@@ -1406,7 +1411,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
1406 | acpi_bus_get_flags(device); | 1411 | acpi_bus_get_flags(device); |
1407 | device->flags.match_driver = false; | 1412 | device->flags.match_driver = false; |
1408 | device->flags.initialized = true; | 1413 | device->flags.initialized = true; |
1409 | device->flags.visited = false; | 1414 | acpi_device_clear_enumerated(device); |
1410 | device_initialize(&device->dev); | 1415 | device_initialize(&device->dev); |
1411 | dev_set_uevent_suppress(&device->dev, true); | 1416 | dev_set_uevent_suppress(&device->dev, true); |
1412 | acpi_init_coherency(device); | 1417 | acpi_init_coherency(device); |
@@ -1676,15 +1681,20 @@ static void acpi_default_enumeration(struct acpi_device *device) | |||
1676 | bool is_spi_i2c_slave = false; | 1681 | bool is_spi_i2c_slave = false; |
1677 | 1682 | ||
1678 | /* | 1683 | /* |
1679 | * Do not enemerate SPI/I2C slaves as they will be enuerated by their | 1684 | * Do not enumerate SPI/I2C slaves as they will be enumerated by their |
1680 | * respective parents. | 1685 | * respective parents. |
1681 | */ | 1686 | */ |
1682 | INIT_LIST_HEAD(&resource_list); | 1687 | INIT_LIST_HEAD(&resource_list); |
1683 | acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave, | 1688 | acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave, |
1684 | &is_spi_i2c_slave); | 1689 | &is_spi_i2c_slave); |
1685 | acpi_dev_free_resource_list(&resource_list); | 1690 | acpi_dev_free_resource_list(&resource_list); |
1686 | if (!is_spi_i2c_slave) | 1691 | if (!is_spi_i2c_slave) { |
1687 | acpi_create_platform_device(device); | 1692 | acpi_create_platform_device(device); |
1693 | acpi_device_set_enumerated(device); | ||
1694 | } else { | ||
1695 | blocking_notifier_call_chain(&acpi_reconfig_chain, | ||
1696 | ACPI_RECONFIG_DEVICE_ADD, device); | ||
1697 | } | ||
1688 | } | 1698 | } |
1689 | 1699 | ||
1690 | static const struct acpi_device_id generic_device_ids[] = { | 1700 | static const struct acpi_device_id generic_device_ids[] = { |
@@ -1751,7 +1761,7 @@ static void acpi_bus_attach(struct acpi_device *device) | |||
1751 | acpi_bus_get_status(device); | 1761 | acpi_bus_get_status(device); |
1752 | /* Skip devices that are not present. */ | 1762 | /* Skip devices that are not present. */ |
1753 | if (!acpi_device_is_present(device)) { | 1763 | if (!acpi_device_is_present(device)) { |
1754 | device->flags.visited = false; | 1764 | acpi_device_clear_enumerated(device); |
1755 | device->flags.power_manageable = 0; | 1765 | device->flags.power_manageable = 0; |
1756 | return; | 1766 | return; |
1757 | } | 1767 | } |
@@ -1766,7 +1776,7 @@ static void acpi_bus_attach(struct acpi_device *device) | |||
1766 | 1776 | ||
1767 | device->flags.initialized = true; | 1777 | device->flags.initialized = true; |
1768 | } | 1778 | } |
1769 | device->flags.visited = false; | 1779 | |
1770 | ret = acpi_scan_attach_handler(device); | 1780 | ret = acpi_scan_attach_handler(device); |
1771 | if (ret < 0) | 1781 | if (ret < 0) |
1772 | return; | 1782 | return; |
@@ -1780,7 +1790,6 @@ static void acpi_bus_attach(struct acpi_device *device) | |||
1780 | if (!ret && device->pnp.type.platform_id) | 1790 | if (!ret && device->pnp.type.platform_id) |
1781 | acpi_default_enumeration(device); | 1791 | acpi_default_enumeration(device); |
1782 | } | 1792 | } |
1783 | device->flags.visited = true; | ||
1784 | 1793 | ||
1785 | ok: | 1794 | ok: |
1786 | list_for_each_entry(child, &device->children, node) | 1795 | list_for_each_entry(child, &device->children, node) |
@@ -1872,7 +1881,7 @@ void acpi_bus_trim(struct acpi_device *adev) | |||
1872 | */ | 1881 | */ |
1873 | acpi_device_set_power(adev, ACPI_STATE_D3_COLD); | 1882 | acpi_device_set_power(adev, ACPI_STATE_D3_COLD); |
1874 | adev->flags.initialized = false; | 1883 | adev->flags.initialized = false; |
1875 | adev->flags.visited = false; | 1884 | acpi_device_clear_enumerated(adev); |
1876 | } | 1885 | } |
1877 | EXPORT_SYMBOL_GPL(acpi_bus_trim); | 1886 | EXPORT_SYMBOL_GPL(acpi_bus_trim); |
1878 | 1887 | ||
@@ -1916,6 +1925,8 @@ static int acpi_bus_scan_fixed(void) | |||
1916 | return result < 0 ? result : 0; | 1925 | return result < 0 ? result : 0; |
1917 | } | 1926 | } |
1918 | 1927 | ||
1928 | static bool acpi_scan_initialized; | ||
1929 | |||
1919 | int __init acpi_scan_init(void) | 1930 | int __init acpi_scan_init(void) |
1920 | { | 1931 | { |
1921 | int result; | 1932 | int result; |
@@ -1960,6 +1971,8 @@ int __init acpi_scan_init(void) | |||
1960 | 1971 | ||
1961 | acpi_update_all_gpes(); | 1972 | acpi_update_all_gpes(); |
1962 | 1973 | ||
1974 | acpi_scan_initialized = true; | ||
1975 | |||
1963 | out: | 1976 | out: |
1964 | mutex_unlock(&acpi_scan_lock); | 1977 | mutex_unlock(&acpi_scan_lock); |
1965 | return result; | 1978 | return result; |
@@ -2003,3 +2016,57 @@ int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr) | |||
2003 | 2016 | ||
2004 | return count; | 2017 | return count; |
2005 | } | 2018 | } |
2019 | |||
2020 | struct acpi_table_events_work { | ||
2021 | struct work_struct work; | ||
2022 | void *table; | ||
2023 | u32 event; | ||
2024 | }; | ||
2025 | |||
2026 | static void acpi_table_events_fn(struct work_struct *work) | ||
2027 | { | ||
2028 | struct acpi_table_events_work *tew; | ||
2029 | |||
2030 | tew = container_of(work, struct acpi_table_events_work, work); | ||
2031 | |||
2032 | if (tew->event == ACPI_TABLE_EVENT_LOAD) { | ||
2033 | acpi_scan_lock_acquire(); | ||
2034 | acpi_bus_scan(ACPI_ROOT_OBJECT); | ||
2035 | acpi_scan_lock_release(); | ||
2036 | } | ||
2037 | |||
2038 | kfree(tew); | ||
2039 | } | ||
2040 | |||
2041 | void acpi_scan_table_handler(u32 event, void *table, void *context) | ||
2042 | { | ||
2043 | struct acpi_table_events_work *tew; | ||
2044 | |||
2045 | if (!acpi_scan_initialized) | ||
2046 | return; | ||
2047 | |||
2048 | if (event != ACPI_TABLE_EVENT_LOAD) | ||
2049 | return; | ||
2050 | |||
2051 | tew = kmalloc(sizeof(*tew), GFP_KERNEL); | ||
2052 | if (!tew) | ||
2053 | return; | ||
2054 | |||
2055 | INIT_WORK(&tew->work, acpi_table_events_fn); | ||
2056 | tew->table = table; | ||
2057 | tew->event = event; | ||
2058 | |||
2059 | schedule_work(&tew->work); | ||
2060 | } | ||
2061 | |||
2062 | int acpi_reconfig_notifier_register(struct notifier_block *nb) | ||
2063 | { | ||
2064 | return blocking_notifier_chain_register(&acpi_reconfig_chain, nb); | ||
2065 | } | ||
2066 | EXPORT_SYMBOL(acpi_reconfig_notifier_register); | ||
2067 | |||
2068 | int acpi_reconfig_notifier_unregister(struct notifier_block *nb) | ||
2069 | { | ||
2070 | return blocking_notifier_chain_unregister(&acpi_reconfig_chain, nb); | ||
2071 | } | ||
2072 | EXPORT_SYMBOL(acpi_reconfig_notifier_unregister); | ||
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 7a2e4d45b266..2b38c1bb0446 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -47,15 +47,32 @@ static void acpi_sleep_tts_switch(u32 acpi_state) | |||
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
50 | static int tts_notify_reboot(struct notifier_block *this, | 50 | static void acpi_sleep_pts_switch(u32 acpi_state) |
51 | { | ||
52 | acpi_status status; | ||
53 | |||
54 | status = acpi_execute_simple_method(NULL, "\\_PTS", acpi_state); | ||
55 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | ||
56 | /* | ||
57 | * OS can't evaluate the _PTS object correctly. Some warning | ||
58 | * message will be printed. But it won't break anything. | ||
59 | */ | ||
60 | printk(KERN_NOTICE "Failure in evaluating _PTS object\n"); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | static int sleep_notify_reboot(struct notifier_block *this, | ||
51 | unsigned long code, void *x) | 65 | unsigned long code, void *x) |
52 | { | 66 | { |
53 | acpi_sleep_tts_switch(ACPI_STATE_S5); | 67 | acpi_sleep_tts_switch(ACPI_STATE_S5); |
68 | |||
69 | acpi_sleep_pts_switch(ACPI_STATE_S5); | ||
70 | |||
54 | return NOTIFY_DONE; | 71 | return NOTIFY_DONE; |
55 | } | 72 | } |
56 | 73 | ||
57 | static struct notifier_block tts_notifier = { | 74 | static struct notifier_block sleep_notifier = { |
58 | .notifier_call = tts_notify_reboot, | 75 | .notifier_call = sleep_notify_reboot, |
59 | .next = NULL, | 76 | .next = NULL, |
60 | .priority = 0, | 77 | .priority = 0, |
61 | }; | 78 | }; |
@@ -899,9 +916,9 @@ int __init acpi_sleep_init(void) | |||
899 | pr_info(PREFIX "(supports%s)\n", supported); | 916 | pr_info(PREFIX "(supports%s)\n", supported); |
900 | 917 | ||
901 | /* | 918 | /* |
902 | * Register the tts_notifier to reboot notifier list so that the _TTS | 919 | * Register the sleep_notifier to reboot notifier list so that the _TTS |
903 | * object can also be evaluated when the system enters S5. | 920 | * and _PTS object can also be evaluated when the system enters S5. |
904 | */ | 921 | */ |
905 | register_reboot_notifier(&tts_notifier); | 922 | register_reboot_notifier(&sleep_notifier); |
906 | return 0; | 923 | return 0; |
907 | } | 924 | } |
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 4b3a9e27f1b6..358165e9f5b8 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c | |||
@@ -378,8 +378,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | |||
378 | return; | 378 | return; |
379 | } | 379 | } |
380 | 380 | ||
381 | static acpi_status | 381 | acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context) |
382 | acpi_sysfs_table_handler(u32 event, void *table, void *context) | ||
383 | { | 382 | { |
384 | struct acpi_table_attr *table_attr; | 383 | struct acpi_table_attr *table_attr; |
385 | 384 | ||
@@ -452,9 +451,8 @@ static int acpi_tables_sysfs_init(void) | |||
452 | 451 | ||
453 | kobject_uevent(tables_kobj, KOBJ_ADD); | 452 | kobject_uevent(tables_kobj, KOBJ_ADD); |
454 | kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); | 453 | kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); |
455 | status = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); | ||
456 | 454 | ||
457 | return ACPI_FAILURE(status) ? -EINVAL : 0; | 455 | return 0; |
458 | err_dynamic_tables: | 456 | err_dynamic_tables: |
459 | kobject_put(tables_kobj); | 457 | kobject_put(tables_kobj); |
460 | err: | 458 | err: |
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index a372f9eaa15d..9f0ad6ebb368 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/bootmem.h> | 34 | #include <linux/bootmem.h> |
35 | #include <linux/earlycpio.h> | 35 | #include <linux/earlycpio.h> |
36 | #include <linux/memblock.h> | 36 | #include <linux/memblock.h> |
37 | #include <linux/initrd.h> | ||
38 | #include <linux/acpi.h> | ||
37 | #include "internal.h" | 39 | #include "internal.h" |
38 | 40 | ||
39 | #ifdef CONFIG_ACPI_CUSTOM_DSDT | 41 | #ifdef CONFIG_ACPI_CUSTOM_DSDT |
@@ -481,8 +483,10 @@ static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES); | |||
481 | 483 | ||
482 | #define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT) | 484 | #define MAP_CHUNK_SIZE (NR_FIX_BTMAPS << PAGE_SHIFT) |
483 | 485 | ||
484 | static void __init acpi_table_initrd_init(void *data, size_t size) | 486 | void __init acpi_table_upgrade(void) |
485 | { | 487 | { |
488 | void *data = (void *)initrd_start; | ||
489 | size_t size = initrd_end - initrd_start; | ||
486 | int sig, no, table_nr = 0, total_offset = 0; | 490 | int sig, no, table_nr = 0, total_offset = 0; |
487 | long offset = 0; | 491 | long offset = 0; |
488 | struct acpi_table_header *table; | 492 | struct acpi_table_header *table; |
@@ -540,7 +544,7 @@ static void __init acpi_table_initrd_init(void *data, size_t size) | |||
540 | return; | 544 | return; |
541 | 545 | ||
542 | acpi_tables_addr = | 546 | acpi_tables_addr = |
543 | memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT, | 547 | memblock_find_in_range(0, ACPI_TABLE_UPGRADE_MAX_PHYS, |
544 | all_tables_size, PAGE_SIZE); | 548 | all_tables_size, PAGE_SIZE); |
545 | if (!acpi_tables_addr) { | 549 | if (!acpi_tables_addr) { |
546 | WARN_ON(1); | 550 | WARN_ON(1); |
@@ -578,10 +582,10 @@ static void __init acpi_table_initrd_init(void *data, size_t size) | |||
578 | clen = size; | 582 | clen = size; |
579 | if (clen > MAP_CHUNK_SIZE - slop) | 583 | if (clen > MAP_CHUNK_SIZE - slop) |
580 | clen = MAP_CHUNK_SIZE - slop; | 584 | clen = MAP_CHUNK_SIZE - slop; |
581 | dest_p = early_ioremap(dest_addr & PAGE_MASK, | 585 | dest_p = early_memremap(dest_addr & PAGE_MASK, |
582 | clen + slop); | 586 | clen + slop); |
583 | memcpy(dest_p + slop, src_p, clen); | 587 | memcpy(dest_p + slop, src_p, clen); |
584 | early_iounmap(dest_p, clen + slop); | 588 | early_memunmap(dest_p, clen + slop); |
585 | src_p += clen; | 589 | src_p += clen; |
586 | dest_addr += clen; | 590 | dest_addr += clen; |
587 | size -= clen; | 591 | size -= clen; |
@@ -696,10 +700,6 @@ next_table: | |||
696 | } | 700 | } |
697 | } | 701 | } |
698 | #else | 702 | #else |
699 | static void __init acpi_table_initrd_init(void *data, size_t size) | ||
700 | { | ||
701 | } | ||
702 | |||
703 | static acpi_status | 703 | static acpi_status |
704 | acpi_table_initrd_override(struct acpi_table_header *existing_table, | 704 | acpi_table_initrd_override(struct acpi_table_header *existing_table, |
705 | acpi_physical_address *address, | 705 | acpi_physical_address *address, |
@@ -742,11 +742,6 @@ acpi_os_table_override(struct acpi_table_header *existing_table, | |||
742 | return AE_OK; | 742 | return AE_OK; |
743 | } | 743 | } |
744 | 744 | ||
745 | void __init early_acpi_table_init(void *data, size_t size) | ||
746 | { | ||
747 | acpi_table_initrd_init(data, size); | ||
748 | } | ||
749 | |||
750 | /* | 745 | /* |
751 | * acpi_table_init() | 746 | * acpi_table_init() |
752 | * | 747 | * |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 82707f9824ca..f4ebe39539af 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -1259,7 +1259,8 @@ static int __init acpi_thermal_init(void) | |||
1259 | return -ENODEV; | 1259 | return -ENODEV; |
1260 | } | 1260 | } |
1261 | 1261 | ||
1262 | acpi_thermal_pm_queue = create_workqueue("acpi_thermal_pm"); | 1262 | acpi_thermal_pm_queue = alloc_workqueue("acpi_thermal_pm", |
1263 | WQ_HIGHPRI | WQ_MEM_RECLAIM, 0); | ||
1263 | if (!acpi_thermal_pm_queue) | 1264 | if (!acpi_thermal_pm_queue) |
1264 | return -ENODEV; | 1265 | return -ENODEV; |
1265 | 1266 | ||
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 3d1327615f72..a6b36fc53aec 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
@@ -167,6 +167,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { | |||
167 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"), | 167 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"), |
168 | }, | 168 | }, |
169 | }, | 169 | }, |
170 | { | ||
171 | .callback = video_detect_force_video, | ||
172 | .ident = "ThinkPad X201T", | ||
173 | .matches = { | ||
174 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
175 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201T"), | ||
176 | }, | ||
177 | }, | ||
170 | 178 | ||
171 | /* The native backlight controls do not work on some older machines */ | 179 | /* The native backlight controls do not work on some older machines */ |
172 | { | 180 | { |