diff options
| -rw-r--r-- | drivers/acpi/tables.c | 63 | ||||
| -rw-r--r-- | include/linux/acpi.h | 4 |
2 files changed, 48 insertions, 19 deletions
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 6d5a6cda0734..f1debe97dcfc 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); |
| @@ -232,7 +226,7 @@ acpi_table_parse_entries(char *id, | |||
| 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; |
| 236 | 230 | ||
| 237 | /* | 231 | /* |
| 238 | * If entry->length is 0, break from this loop to avoid | 232 | * If entry->length is 0, break from this loop to avoid |
| @@ -240,22 +234,53 @@ acpi_table_parse_entries(char *id, | |||
| 240 | */ | 234 | */ |
| 241 | if (entry->length == 0) { | 235 | if (entry->length == 0) { |
| 242 | pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); | 236 | pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); |
| 243 | goto err; | 237 | return -EINVAL; |
| 244 | } | 238 | } |
| 245 | 239 | ||
| 246 | entry = (struct acpi_subtable_header *) | 240 | entry = (struct acpi_subtable_header *) |
| 247 | ((unsigned long)entry + entry->length); | 241 | ((unsigned long)entry + entry->length); |
| 248 | } | 242 | } |
| 243 | |||
| 249 | if (max_entries && count > max_entries) { | 244 | if (max_entries && count > max_entries) { |
| 250 | pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n", | 245 | pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n", |
| 251 | id, entry_id, count - max_entries, count); | 246 | id, entry_id, count - max_entries, count); |
| 252 | } | 247 | } |
| 253 | 248 | ||
| 254 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | ||
| 255 | return count; | 249 | return count; |
| 256 | err: | 250 | } |
| 251 | |||
| 252 | int __init | ||
| 253 | acpi_table_parse_entries(char *id, | ||
| 254 | unsigned long table_size, | ||
| 255 | int entry_id, | ||
| 256 | acpi_tbl_entry_handler handler, | ||
| 257 | unsigned int max_entries) | ||
| 258 | { | ||
| 259 | struct acpi_table_header *table_header = NULL; | ||
| 260 | acpi_size tbl_size; | ||
| 261 | int count; | ||
| 262 | u32 instance = 0; | ||
| 263 | |||
| 264 | if (acpi_disabled) | ||
| 265 | return -ENODEV; | ||
| 266 | |||
| 267 | if (!id || !handler) | ||
| 268 | return -EINVAL; | ||
| 269 | |||
| 270 | if (!strncmp(id, ACPI_SIG_MADT, 4)) | ||
| 271 | instance = acpi_apic_instance; | ||
| 272 | |||
| 273 | acpi_get_table_with_size(id, instance, &table_header, &tbl_size); | ||
| 274 | if (!table_header) { | ||
| 275 | pr_warn("%4.4s not present\n", id); | ||
| 276 | return -ENODEV; | ||
| 277 | } | ||
| 278 | |||
| 279 | count = acpi_parse_entries(id, table_size, handler, table_header, | ||
| 280 | entry_id, max_entries); | ||
| 281 | |||
| 257 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); | 282 | early_acpi_os_unmap_memory((char *)table_header, tbl_size); |
| 258 | return -EINVAL; | 283 | return count; |
| 259 | } | 284 | } |
| 260 | 285 | ||
| 261 | int __init | 286 | int __init |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 407a12f663eb..3bd0c59e1fb9 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -123,6 +123,10 @@ int acpi_numa_init (void); | |||
| 123 | 123 | ||
| 124 | int acpi_table_init (void); | 124 | int acpi_table_init (void); |
| 125 | int acpi_table_parse(char *id, acpi_tbl_table_handler handler); | 125 | int acpi_table_parse(char *id, acpi_tbl_table_handler handler); |
| 126 | int __init acpi_parse_entries(char *id, unsigned long table_size, | ||
| 127 | acpi_tbl_entry_handler handler, | ||
| 128 | struct acpi_table_header *table_header, | ||
| 129 | int entry_id, unsigned int max_entries); | ||
| 126 | int __init acpi_table_parse_entries(char *id, unsigned long table_size, | 130 | int __init acpi_table_parse_entries(char *id, unsigned long table_size, |
| 127 | int entry_id, | 131 | int entry_id, |
| 128 | acpi_tbl_entry_handler handler, | 132 | acpi_tbl_entry_handler handler, |
