diff options
author | Ashwin Chaugule <ashwin.chaugule@linaro.org> | 2014-11-26 09:01:13 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-11-26 20:06:17 -0500 |
commit | f08bb472bff3c0397fb7d6f47bc5cec41dad76e3 (patch) | |
tree | d1e3c7a64a591f9f1c6fa14c38b2d0b595583654 /drivers/acpi/tables.c | |
parent | 5d01410fe4d92081f349b013a2e7a95429e4f2c9 (diff) |
ACPI / table: Add new function to get table entries
The acpi_table_parse() function has a callback that
passes a pointer to a table_header. Add a new function
which takes this pointer and parses its entries. This
eliminates the need to re-traverse all the tables for
each call. e.g. as in acpi_table_parse_madt() which is
normally called after acpi_table_parse().
Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Ashwin Chaugule <ashwin.chaugule@linaro.org>
Signed-off-by: Tomasz Nowicki <tomasz.nowicki@linaro.org>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/tables.c')
-rw-r--r-- | drivers/acpi/tables.c | 63 |
1 files changed, 44 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 |