diff options
-rw-r--r-- | drivers/acpi/Kconfig | 13 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 8 | ||||
-rw-r--r-- | drivers/acpi/tables.c | 68 | ||||
-rw-r--r-- | drivers/acpi/utils.c | 5 | ||||
-rw-r--r-- | include/linux/acpi.h | 4 |
5 files changed, 67 insertions, 31 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b23fe37f67c0..79078b8f5697 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -360,15 +360,14 @@ config ACPI_BGRT | |||
360 | config ACPI_REDUCED_HARDWARE_ONLY | 360 | config ACPI_REDUCED_HARDWARE_ONLY |
361 | bool "Hardware-reduced ACPI support only" if EXPERT | 361 | bool "Hardware-reduced ACPI support only" if EXPERT |
362 | def_bool n | 362 | def_bool n |
363 | depends on ACPI | ||
364 | help | 363 | help |
365 | This config item changes the way the ACPI code is built. When this | 364 | This config item changes the way the ACPI code is built. When this |
366 | option is selected, the kernel will use a specialized version of | 365 | option is selected, the kernel will use a specialized version of |
367 | ACPICA that ONLY supports the ACPI "reduced hardware" mode. The | 366 | ACPICA that ONLY supports the ACPI "reduced hardware" mode. The |
368 | resulting kernel will be smaller but it will also be restricted to | 367 | resulting kernel will be smaller but it will also be restricted to |
369 | running in ACPI reduced hardware mode ONLY. | 368 | running in ACPI reduced hardware mode ONLY. |
370 | 369 | ||
371 | If you are unsure what to do, do not enable this option. | 370 | If you are unsure what to do, do not enable this option. |
372 | 371 | ||
373 | source "drivers/acpi/apei/Kconfig" | 372 | source "drivers/acpi/apei/Kconfig" |
374 | 373 | ||
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 9964f70be98d..f9eeae871593 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -436,7 +436,7 @@ static void acpi_os_drop_map_ref(struct acpi_ioremap *map) | |||
436 | static void acpi_os_map_cleanup(struct acpi_ioremap *map) | 436 | static void acpi_os_map_cleanup(struct acpi_ioremap *map) |
437 | { | 437 | { |
438 | if (!map->refcount) { | 438 | if (!map->refcount) { |
439 | synchronize_rcu(); | 439 | synchronize_rcu_expedited(); |
440 | acpi_unmap(map->phys, map->virt); | 440 | acpi_unmap(map->phys, map->virt); |
441 | kfree(map); | 441 | kfree(map); |
442 | } | 442 | } |
@@ -1188,6 +1188,12 @@ EXPORT_SYMBOL(acpi_os_execute); | |||
1188 | 1188 | ||
1189 | void acpi_os_wait_events_complete(void) | 1189 | void acpi_os_wait_events_complete(void) |
1190 | { | 1190 | { |
1191 | /* | ||
1192 | * Make sure the GPE handler or the fixed event handler is not used | ||
1193 | * on another CPU after removal. | ||
1194 | */ | ||
1195 | if (acpi_irq_handler) | ||
1196 | synchronize_hardirq(acpi_gbl_FADT.sci_interrupt); | ||
1191 | flush_workqueue(kacpid_wq); | 1197 | flush_workqueue(kacpid_wq); |
1192 | flush_workqueue(kacpi_notify_wq); | 1198 | flush_workqueue(kacpi_notify_wq); |
1193 | } | 1199 | } |
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 6d5a6cda0734..93b81523a2fe 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c | |||
@@ -190,30 +190,24 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) | |||
190 | } | 190 | } |
191 | } | 191 | } |
192 | 192 | ||
193 | |||
194 | int __init | 193 | int __init |
195 | acpi_table_parse_entries(char *id, | 194 | acpi_parse_entries(char *id, unsigned long table_size, |
196 | unsigned long table_size, | 195 | acpi_tbl_entry_handler handler, |
197 | int entry_id, | 196 | struct acpi_table_header *table_header, |
198 | acpi_tbl_entry_handler handler, | 197 | int entry_id, unsigned int max_entries) |
199 | unsigned int max_entries) | ||
200 | { | 198 | { |
201 | struct acpi_table_header *table_header = NULL; | ||
202 | struct acpi_subtable_header *entry; | 199 | struct acpi_subtable_header *entry; |
203 | unsigned int count = 0; | 200 | int count = 0; |
204 | unsigned long table_end; | 201 | unsigned long table_end; |
205 | acpi_size tbl_size; | ||
206 | 202 | ||
207 | if (acpi_disabled) | 203 | if (acpi_disabled) |
208 | return -ENODEV; | 204 | return -ENODEV; |
209 | 205 | ||
210 | if (!handler) | 206 | if (!id || !handler) |
211 | return -EINVAL; | 207 | return -EINVAL; |
212 | 208 | ||
213 | if (strncmp(id, ACPI_SIG_MADT, 4) == 0) | 209 | if (!table_size) |
214 | acpi_get_table_with_size(id, acpi_apic_instance, &table_header, &tbl_size); | 210 | return -EINVAL; |
215 | else | ||
216 | acpi_get_table_with_size(id, 0, &table_header, &tbl_size); | ||
217 | 211 | ||
218 | if (!table_header) { | 212 | if (!table_header) { |
219 | pr_warn("%4.4s not present\n", id); | 213 | pr_warn("%4.4s not present\n", id); |
@@ -230,9 +224,12 @@ acpi_table_parse_entries(char *id, | |||
230 | while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < | 224 | while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < |
231 | table_end) { | 225 | table_end) { |
232 | if (entry->type == entry_id | 226 | if (entry->type == entry_id |
233 | && (!max_entries || count++ < max_entries)) | 227 | && (!max_entries || count < max_entries)) { |
234 | if (handler(entry, table_end)) | 228 | if (handler(entry, table_end)) |
235 | goto err; | 229 | return -EINVAL; |
230 | |||
231 | count++; | ||
232 | } | ||
236 | 233 | ||
237 | /* | 234 | /* |
238 | * If entry->length is 0, break from this loop to avoid | 235 | * If entry->length is 0, break from this loop to avoid |
@@ -240,22 +237,53 @@ acpi_table_parse_entries(char *id, | |||
240 | */ | 237 | */ |
241 | if (entry->length == 0) { | 238 | if (entry->length == 0) { |
242 | pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); | 239 | pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); |
243 | goto err; | 240 | return -EINVAL; |
244 | } | 241 | } |
245 | 242 | ||
246 | entry = (struct acpi_subtable_header *) | 243 | entry = (struct acpi_subtable_header *) |
247 | ((unsigned long)entry + entry->length); | 244 | ((unsigned long)entry + entry->length); |
248 | } | 245 | } |
246 | |||
249 | if (max_entries && count > max_entries) { | 247 | if (max_entries && count > max_entries) { |
250 | pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n", | 248 | pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n", |
251 | id, entry_id, count - max_entries, count); | 249 | id, entry_id, count - max_entries, count); |
252 | } | 250 | } |
253 | 251 | ||
254 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | ||
255 | return count; | 252 | return count; |
256 | err: | 253 | } |
254 | |||
255 | int __init | ||
256 | acpi_table_parse_entries(char *id, | ||
257 | unsigned long table_size, | ||
258 | int entry_id, | ||
259 | acpi_tbl_entry_handler handler, | ||
260 | unsigned int max_entries) | ||
261 | { | ||
262 | struct acpi_table_header *table_header = NULL; | ||
263 | acpi_size tbl_size; | ||
264 | int count; | ||
265 | u32 instance = 0; | ||
266 | |||
267 | if (acpi_disabled) | ||
268 | return -ENODEV; | ||
269 | |||
270 | if (!id || !handler) | ||
271 | return -EINVAL; | ||
272 | |||
273 | if (!strncmp(id, ACPI_SIG_MADT, 4)) | ||
274 | instance = acpi_apic_instance; | ||
275 | |||
276 | acpi_get_table_with_size(id, instance, &table_header, &tbl_size); | ||
277 | if (!table_header) { | ||
278 | pr_warn("%4.4s not present\n", id); | ||
279 | return -ENODEV; | ||
280 | } | ||
281 | |||
282 | count = acpi_parse_entries(id, table_size, handler, table_header, | ||
283 | entry_id, max_entries); | ||
284 | |||
257 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | 285 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); |
258 | return -EINVAL; | 286 | return count; |
259 | } | 287 | } |
260 | 288 | ||
261 | int __init | 289 | int __init |
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 371ac12d25b1..dd8ff63ee2b4 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c | |||
@@ -136,8 +136,7 @@ acpi_extract_package(union acpi_object *package, | |||
136 | break; | 136 | break; |
137 | case 'B': | 137 | case 'B': |
138 | size_required += | 138 | size_required += |
139 | sizeof(u8 *) + | 139 | sizeof(u8 *) + element->buffer.length; |
140 | (element->buffer.length * sizeof(u8)); | ||
141 | tail_offset += sizeof(u8 *); | 140 | tail_offset += sizeof(u8 *); |
142 | break; | 141 | break; |
143 | default: | 142 | default: |
@@ -255,7 +254,7 @@ acpi_extract_package(union acpi_object *package, | |||
255 | memcpy(tail, element->buffer.pointer, | 254 | memcpy(tail, element->buffer.pointer, |
256 | element->buffer.length); | 255 | element->buffer.length); |
257 | head += sizeof(u8 *); | 256 | head += sizeof(u8 *); |
258 | tail += element->buffer.length * sizeof(u8); | 257 | tail += element->buffer.length; |
259 | break; | 258 | break; |
260 | default: | 259 | default: |
261 | /* Should never get here */ | 260 | /* Should never get here */ |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 10f2ed95645c..0ccaa093010c 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -124,6 +124,10 @@ int acpi_numa_init (void); | |||
124 | 124 | ||
125 | int acpi_table_init (void); | 125 | int acpi_table_init (void); |
126 | int acpi_table_parse(char *id, acpi_tbl_table_handler handler); | 126 | int acpi_table_parse(char *id, acpi_tbl_table_handler handler); |
127 | int __init acpi_parse_entries(char *id, unsigned long table_size, | ||
128 | acpi_tbl_entry_handler handler, | ||
129 | struct acpi_table_header *table_header, | ||
130 | int entry_id, unsigned int max_entries); | ||
127 | int __init acpi_table_parse_entries(char *id, unsigned long table_size, | 131 | int __init acpi_table_parse_entries(char *id, unsigned long table_size, |
128 | int entry_id, | 132 | int entry_id, |
129 | acpi_tbl_entry_handler handler, | 133 | acpi_tbl_entry_handler handler, |