aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukasz Anaczkowski <lukasz.anaczkowski@intel.com>2015-09-09 09:47:28 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-10-14 19:29:39 -0400
commit9b3fedde27d3d63055c43c05e8254e252e58ba48 (patch)
tree0ce3f5e0b33bc55ecb395fd4644058086c17da97
parent6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff)
ACPI / tables: Add acpi_subtable_proc to ACPI table parsers
ACPI subtable parsing needs to be extended to allow two or more handlers to be run in the same ACPI table walk, thus adding acpi_subtable_proc structure which stores () ACPI table id () handler that processes table () counter how many items has been processed and passing it to acpi_parse_entries_array() and acpi_table_parse_entries_array(). This is needed to fix CPU enumeration when APIC/X2APIC entries are interleaved. Signed-off-by: Lukasz Anaczkowski <lukasz.anaczkowski@intel.com> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> Tested-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/tables.c93
-rw-r--r--include/linux/acpi.h19
2 files changed, 91 insertions, 21 deletions
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 17a6fa01a338..c1ff58de99e9 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -210,20 +210,39 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
210 } 210 }
211} 211}
212 212
213int __init 213/**
214acpi_parse_entries(char *id, unsigned long table_size, 214 * acpi_parse_entries_array - for each proc_num find a suitable subtable
215 acpi_tbl_entry_handler handler, 215 *
216 * @id: table id (for debugging purposes)
217 * @table_size: single entry size
218 * @table_header: where does the table start?
219 * @proc: array of acpi_subtable_proc struct containing entry id
220 * and associated handler with it
221 * @proc_num: how big proc is?
222 * @max_entries: how many entries can we process?
223 *
224 * For each proc_num find a subtable with proc->id and run proc->handler
225 * on it. Assumption is that there's only single handler for particular
226 * entry id.
227 *
228 * On success returns sum of all matching entries for all proc handlers.
229 * Otherwise, -ENODEV or -EINVAL is returned.
230 */
231static int __init
232acpi_parse_entries_array(char *id, unsigned long table_size,
216 struct acpi_table_header *table_header, 233 struct acpi_table_header *table_header,
217 int entry_id, unsigned int max_entries) 234 struct acpi_subtable_proc *proc, int proc_num,
235 unsigned int max_entries)
218{ 236{
219 struct acpi_subtable_header *entry; 237 struct acpi_subtable_header *entry;
220 int count = 0;
221 unsigned long table_end; 238 unsigned long table_end;
239 int count = 0;
240 int i;
222 241
223 if (acpi_disabled) 242 if (acpi_disabled)
224 return -ENODEV; 243 return -ENODEV;
225 244
226 if (!id || !handler) 245 if (!id)
227 return -EINVAL; 246 return -EINVAL;
228 247
229 if (!table_size) 248 if (!table_size)
@@ -243,20 +262,27 @@ acpi_parse_entries(char *id, unsigned long table_size,
243 262
244 while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < 263 while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
245 table_end) { 264 table_end) {
246 if (entry->type == entry_id 265 if (max_entries && count >= max_entries)
247 && (!max_entries || count < max_entries)) { 266 break;
248 if (handler(entry, table_end)) 267
268 for (i = 0; i < proc_num; i++) {
269 if (entry->type != proc[i].id)
270 continue;
271 if (!proc->handler || proc[i].handler(entry, table_end))
249 return -EINVAL; 272 return -EINVAL;
250 273
251 count++; 274 proc->count++;
275 break;
252 } 276 }
277 if (i != proc_num)
278 count++;
253 279
254 /* 280 /*
255 * If entry->length is 0, break from this loop to avoid 281 * If entry->length is 0, break from this loop to avoid
256 * infinite loop. 282 * infinite loop.
257 */ 283 */
258 if (entry->length == 0) { 284 if (entry->length == 0) {
259 pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, entry_id); 285 pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
260 return -EINVAL; 286 return -EINVAL;
261 } 287 }
262 288
@@ -266,17 +292,32 @@ acpi_parse_entries(char *id, unsigned long table_size,
266 292
267 if (max_entries && count > max_entries) { 293 if (max_entries && count > max_entries) {
268 pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n", 294 pr_warn("[%4.4s:0x%02x] ignored %i entries of %i found\n",
269 id, entry_id, count - max_entries, count); 295 id, proc->id, count - max_entries, count);
270 } 296 }
271 297
272 return count; 298 return count;
273} 299}
274 300
275int __init 301int __init
276acpi_table_parse_entries(char *id, 302acpi_parse_entries(char *id,
303 unsigned long table_size,
304 acpi_tbl_entry_handler handler,
305 struct acpi_table_header *table_header,
306 int entry_id, unsigned int max_entries)
307{
308 struct acpi_subtable_proc proc = {
309 .id = entry_id,
310 .handler = handler,
311 };
312
313 return acpi_parse_entries_array(id, table_size, table_header,
314 &proc, 1, max_entries);
315}
316
317int __init
318acpi_table_parse_entries_array(char *id,
277 unsigned long table_size, 319 unsigned long table_size,
278 int entry_id, 320 struct acpi_subtable_proc *proc, int proc_num,
279 acpi_tbl_entry_handler handler,
280 unsigned int max_entries) 321 unsigned int max_entries)
281{ 322{
282 struct acpi_table_header *table_header = NULL; 323 struct acpi_table_header *table_header = NULL;
@@ -287,7 +328,7 @@ acpi_table_parse_entries(char *id,
287 if (acpi_disabled) 328 if (acpi_disabled)
288 return -ENODEV; 329 return -ENODEV;
289 330
290 if (!id || !handler) 331 if (!id)
291 return -EINVAL; 332 return -EINVAL;
292 333
293 if (!strncmp(id, ACPI_SIG_MADT, 4)) 334 if (!strncmp(id, ACPI_SIG_MADT, 4))
@@ -299,14 +340,30 @@ acpi_table_parse_entries(char *id,
299 return -ENODEV; 340 return -ENODEV;
300 } 341 }
301 342
302 count = acpi_parse_entries(id, table_size, handler, table_header, 343 count = acpi_parse_entries_array(id, table_size, table_header,
303 entry_id, max_entries); 344 proc, proc_num, max_entries);
304 345
305 early_acpi_os_unmap_memory((char *)table_header, tbl_size); 346 early_acpi_os_unmap_memory((char *)table_header, tbl_size);
306 return count; 347 return count;
307} 348}
308 349
309int __init 350int __init
351acpi_table_parse_entries(char *id,
352 unsigned long table_size,
353 int entry_id,
354 acpi_tbl_entry_handler handler,
355 unsigned int max_entries)
356{
357 struct acpi_subtable_proc proc = {
358 .id = entry_id,
359 .handler = handler,
360 };
361
362 return acpi_table_parse_entries_array(id, table_size, &proc, 1,
363 max_entries);
364}
365
366int __init
310acpi_table_parse_madt(enum acpi_madt_type id, 367acpi_table_parse_madt(enum acpi_madt_type id,
311 acpi_tbl_entry_handler handler, unsigned int max_entries) 368 acpi_tbl_entry_handler handler, unsigned int max_entries)
312{ 369{
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 7235c4851460..b0299f8db660 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -131,6 +131,12 @@ static inline void acpi_initrd_override(void *data, size_t size)
131 (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ 131 (!entry) || (unsigned long)entry + sizeof(*entry) > end || \
132 ((struct acpi_subtable_header *)entry)->length < sizeof(*entry)) 132 ((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
133 133
134struct acpi_subtable_proc {
135 int id;
136 acpi_tbl_entry_handler handler;
137 int count;
138};
139
134char * __acpi_map_table (unsigned long phys_addr, unsigned long size); 140char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
135void __acpi_unmap_table(char *map, unsigned long size); 141void __acpi_unmap_table(char *map, unsigned long size);
136int early_acpi_boot_init(void); 142int early_acpi_boot_init(void);
@@ -146,9 +152,16 @@ int __init acpi_parse_entries(char *id, unsigned long table_size,
146 struct acpi_table_header *table_header, 152 struct acpi_table_header *table_header,
147 int entry_id, unsigned int max_entries); 153 int entry_id, unsigned int max_entries);
148int __init acpi_table_parse_entries(char *id, unsigned long table_size, 154int __init acpi_table_parse_entries(char *id, unsigned long table_size,
149 int entry_id, 155 int entry_id,
150 acpi_tbl_entry_handler handler, 156 acpi_tbl_entry_handler handler,
151 unsigned int max_entries); 157 unsigned int max_entries);
158int __init acpi_table_parse_entries(char *id, unsigned long table_size,
159 int entry_id,
160 acpi_tbl_entry_handler handler,
161 unsigned int max_entries);
162int __init acpi_table_parse_entries_array(char *id, unsigned long table_size,
163 struct acpi_subtable_proc *proc, int proc_num,
164 unsigned int max_entries);
152int acpi_table_parse_madt(enum acpi_madt_type id, 165int acpi_table_parse_madt(enum acpi_madt_type id,
153 acpi_tbl_entry_handler handler, 166 acpi_tbl_entry_handler handler,
154 unsigned int max_entries); 167 unsigned int max_entries);