Introduce a new function that takes a table_header pointer acquired from acpi_table_parse(). This eliminates the need to get the table pointer again by traversing the whole list of tables. e.g. as in acpi_table_parse_madt().
Signed-off-by: Ashwin Chaugule ashwin.chaugule@linaro.org --- drivers/acpi/tables.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 4 ++++ 2 files changed, 59 insertions(+)
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index be6a7d7..eaf805b 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -203,6 +203,61 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) } }
+int __init +acpi_parse_entries(unsigned long table_size, + acpi_tbl_entry_handler handler, + struct acpi_table_header *table_header, + int entry_id, unsigned int max_entries) +{ + struct acpi_subtable_header *entry; + unsigned int count = 0; + unsigned long table_end; + acpi_size tbl_size = table_header->length; + + if (acpi_disabled) + return -ENODEV; + + if (!table_header) { + pr_warn(PREFIX "Table header not present\n"); + return -ENODEV; + } + + table_end = (unsigned long)table_header + table_header->length; + + /* Parse all entries looking for a match. */ + entry = (struct acpi_subtable_header *) + ((unsigned long)table_header + table_size); + + while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < + table_end) { + if (entry->type == entry_id + && (!max_entries || count++ < max_entries)) + if (handler(entry, table_end)) + goto err; + + /* + * If entry->length is 0, break from this loop to avoid + * infinite loop. + */ + if (entry->length == 0) { + pr_err(PREFIX "[0x%02x] Invalid zero length\n", entry_id); + goto err; + } + + entry = (struct acpi_subtable_header *) + ((unsigned long)entry + entry->length); + } + if (max_entries && count > max_entries) { + pr_warn(PREFIX "[0x%02x] ignored %i entries of %i found\n", + entry_id, count - max_entries, count); + } + + early_acpi_os_unmap_memory((char *)table_header, tbl_size); + return count; +err: + early_acpi_os_unmap_memory((char *)table_header, tbl_size); + return -EINVAL; +}
int __init acpi_table_parse_entries(char *id, diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 372038a..7d5dba2 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -122,6 +122,10 @@ int acpi_numa_init (void);
int acpi_table_init (void); int acpi_table_parse(char *id, acpi_tbl_table_handler handler); +int __init acpi_parse_entries(unsigned long table_size, + acpi_tbl_entry_handler handler, + struct acpi_table_header *table_header, + int entry_id, unsigned int max_entries); int __init acpi_table_parse_entries(char *id, unsigned long table_size, int entry_id, acpi_tbl_entry_handler handler,