From 7f8f97c3cc75d5783d0b45cf323dedf17684be19 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 10 Feb 2007 21:28:03 -0500 Subject: ACPI: acpi_table_parse() now returns success/fail, not count Returning count for tables that are supposed to be unique was useless and confusing. Signed-off-by: Len Brown --- drivers/acpi/tables.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/acpi/tables.c') diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index ba4cb200314a..2075ec7b827b 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -226,6 +226,15 @@ acpi_table_parse_madt(enum acpi_madt_type id, handler, max_entries); } +/** + * acpi_table_parse - find table with @id, run @handler on it + * + * @id: table id to find + * @handler: handler to run + * + * Scan the ACPI System Descriptor Table (STD) for a table matching @id, + * run @handler on it. Return 0 if table found, return on if not. + */ int __init acpi_table_parse(char *id, acpi_table_handler handler) { struct acpi_table_header *table = NULL; @@ -235,9 +244,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) acpi_get_table(id, 0, &table); if (table) { handler(table); - return 1; - } else return 0; + } else + return 1; } /* -- cgit From 5a8765a84c31ea51baf1f6c78116cd877bd8cd64 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 10 Feb 2007 21:35:47 -0500 Subject: ACPI: acpi_madt_entry_handler() is not MADT specific acpi_madt_entry_handler() is also used for the SRAT, so re-name it acpi_table_entry_handler(). cosmetic only. Signed-off-by: Len Brown --- drivers/acpi/numa.c | 4 ++-- drivers/acpi/tables.c | 4 ++-- include/linux/acpi.h | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/acpi/tables.c') diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index bb6caab24322..44e411e78ed4 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -48,7 +48,7 @@ int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] extern int __init acpi_table_parse_madt_family(char *id, unsigned long madt_size, int entry_id, - acpi_madt_entry_handler handler, + acpi_table_entry_handler handler, unsigned int max_entries); int __cpuinit pxm_to_node(int pxm) @@ -208,7 +208,7 @@ static int __init acpi_parse_srat(struct acpi_table_header *table) int __init acpi_table_parse_srat(enum acpi_srat_type id, - acpi_madt_entry_handler handler, unsigned int max_entries) + acpi_table_entry_handler handler, unsigned int max_entries) { return acpi_table_parse_madt_family(ACPI_SIG_SRAT, sizeof(struct acpi_table_srat), id, diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 2075ec7b827b..f211fa35374c 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -173,7 +173,7 @@ int __init acpi_table_parse_madt_family(char *id, unsigned long madt_size, int entry_id, - acpi_madt_entry_handler handler, + acpi_table_entry_handler handler, unsigned int max_entries) { struct acpi_table_header *madt = NULL; @@ -219,7 +219,7 @@ acpi_table_parse_madt_family(char *id, int __init acpi_table_parse_madt(enum acpi_madt_type id, - acpi_madt_entry_handler handler, unsigned int max_entries) + acpi_table_entry_handler handler, unsigned int max_entries) { return acpi_table_parse_madt_family(ACPI_SIG_MADT, sizeof(struct acpi_table_madt), id, diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 815f1fb4ce21..15a23b6be449 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -75,7 +75,7 @@ enum acpi_address_range_id { typedef int (*acpi_table_handler) (struct acpi_table_header *table); -typedef int (*acpi_madt_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); +typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); char * __acpi_map_table (unsigned long phys_addr, unsigned long size); unsigned long acpi_find_rsdp (void); @@ -85,8 +85,8 @@ int acpi_numa_init (void); int acpi_table_init (void); int acpi_table_parse (char *id, acpi_table_handler handler); -int acpi_table_parse_madt (enum acpi_madt_type id, acpi_madt_entry_handler handler, unsigned int max_entries); -int acpi_table_parse_srat (enum acpi_srat_type id, acpi_madt_entry_handler handler, unsigned int max_entries); +int acpi_table_parse_madt (enum acpi_madt_type id, acpi_table_entry_handler handler, unsigned int max_entries); +int acpi_table_parse_srat (enum acpi_srat_type id, acpi_table_entry_handler handler, unsigned int max_entries); int acpi_parse_mcfg (struct acpi_table_header *header); void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); void acpi_table_print_srat_entry (struct acpi_subtable_header *srat); -- cgit From 6eb87fed52b7f6ac200eaa649cc3221e239d0113 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 10 Feb 2007 22:17:07 -0500 Subject: ACPI: acpi_table_parse_madt_family() is not MADT specific acpi_table_parse_madt_family() is also used to parse SRAT entries. So re-name it to acpi_table_parse_entries(), and re-name the madt-specific variables within it accordingly. cosmetic only. Signed-off-by: Len Brown --- drivers/acpi/numa.c | 8 +------- drivers/acpi/tables.c | 24 ++++++++++++------------ include/linux/acpi.h | 2 ++ 3 files changed, 15 insertions(+), 19 deletions(-) (limited to 'drivers/acpi/tables.c') diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 44e411e78ed4..8fcd6a15517f 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -45,12 +45,6 @@ int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; -extern int __init acpi_table_parse_madt_family(char *id, - unsigned long madt_size, - int entry_id, - acpi_table_entry_handler handler, - unsigned int max_entries); - int __cpuinit pxm_to_node(int pxm) { if (pxm < 0) @@ -210,7 +204,7 @@ int __init acpi_table_parse_srat(enum acpi_srat_type id, acpi_table_entry_handler handler, unsigned int max_entries) { - return acpi_table_parse_madt_family(ACPI_SIG_SRAT, + return acpi_table_parse_entries(ACPI_SIG_SRAT, sizeof(struct acpi_table_srat), id, handler, max_entries); } diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index f211fa35374c..4ed640031e9a 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -170,40 +170,40 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header * header) int __init -acpi_table_parse_madt_family(char *id, - unsigned long madt_size, +acpi_table_parse_entries(char *id, + unsigned long table_size, int entry_id, acpi_table_entry_handler handler, unsigned int max_entries) { - struct acpi_table_header *madt = NULL; + struct acpi_table_header *table_header = NULL; struct acpi_subtable_header *entry; unsigned int count = 0; - unsigned long madt_end; + unsigned long table_end; if (!handler) return -EINVAL; - /* Locate the MADT (if exists). There should only be one. */ - acpi_get_table(id, 0, &madt); + /* Locate the table (if exists). There should only be one. */ + acpi_get_table(id, 0, &table_header); - if (!madt) { + if (!table_header) { printk(KERN_WARNING PREFIX "%4.4s not present\n", id); return -ENODEV; } - madt_end = (unsigned long)madt + madt->length; + table_end = (unsigned long)table_header + table_header->length; /* Parse all entries looking for a match. */ entry = (struct acpi_subtable_header *) - ((unsigned long)madt + madt_size); + ((unsigned long)table_header + table_size); while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < - madt_end) { + table_end) { if (entry->type == entry_id && (!max_entries || count++ < max_entries)) - if (handler(entry, madt_end)) + if (handler(entry, table_end)) return -EINVAL; entry = (struct acpi_subtable_header *) @@ -221,7 +221,7 @@ int __init acpi_table_parse_madt(enum acpi_madt_type id, acpi_table_entry_handler handler, unsigned int max_entries) { - return acpi_table_parse_madt_family(ACPI_SIG_MADT, + return acpi_table_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt), id, handler, max_entries); } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 15a23b6be449..8bcfaa4c66ae 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -85,6 +85,8 @@ int acpi_numa_init (void); int acpi_table_init (void); int acpi_table_parse (char *id, acpi_table_handler handler); +int __init acpi_table_parse_entries(char *id, unsigned long table_size, + int entry_id, acpi_table_entry_handler handler, unsigned int max_entries); int acpi_table_parse_madt (enum acpi_madt_type id, acpi_table_entry_handler handler, unsigned int max_entries); int acpi_table_parse_srat (enum acpi_srat_type id, acpi_table_entry_handler handler, unsigned int max_entries); int acpi_parse_mcfg (struct acpi_table_header *header); -- cgit From a1fdcc0d2714b6622e3fd5c00db1635213d6c41a Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sun, 11 Mar 2007 03:26:14 -0400 Subject: ACPI: Add support to parse 2nd MADT When a BIOS bug presents multiple APIC/MADTs, Linux currently uses the 1st and ignores the 2nd. But some machines work better if we use the 2nd. http://bugzilla.kernel.org/show_bug.cgi?id=7465 Add a warning and boot parameter "acpi_apic_instance=2" to allow parsing the 2nd. No change to default behaviour in this patch. Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 6 ++++ drivers/acpi/tables.c | 57 +++++++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 5 deletions(-) (limited to 'drivers/acpi/tables.c') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 856c8b114e71..22c6b8ccaea5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -138,6 +138,12 @@ and is between 256 and 4096 characters. It is defined in the file See also Documentation/pm.txt, pci=noacpi + acpi_apic_instance= [ACPI, IOAPIC] + Format: + 2: use 2nd APIC table, if available + 1,0: use 1st APIC table + default: 0 + acpi_sleep= [HW,ACPI] Sleep options Format: { s3_bios, s3_mode } See Documentation/power/video.txt diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 849e2c361804..c3419182c9a7 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -42,7 +42,9 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; -void acpi_table_print_madt_entry(struct acpi_subtable_header * header) +static int acpi_apic_instance __initdata; + +void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { if (!header) return; @@ -183,8 +185,10 @@ acpi_table_parse_entries(char *id, if (!handler) return -EINVAL; - /* Locate the table (if exists). There should only be one. */ - acpi_get_table(id, 0, &table_header); + if (strncmp(id, ACPI_SIG_MADT, 4) == 0) + acpi_get_table(id, acpi_apic_instance, &table_header); + else + acpi_get_table(id, 0, &table_header); if (!table_header) { printk(KERN_WARNING PREFIX "%4.4s not present\n", id); @@ -237,10 +241,15 @@ acpi_table_parse_madt(enum acpi_madt_type id, int __init acpi_table_parse(char *id, acpi_table_handler handler) { struct acpi_table_header *table = NULL; + if (!handler) return -EINVAL; - acpi_get_table(id, 0, &table); + if (strncmp(id, ACPI_SIG_MADT, 4) == 0) + acpi_get_table(id, acpi_apic_instance, &table); + else + acpi_get_table(id, 0, &table); + if (table) { handler(table); return 0; @@ -248,6 +257,31 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) return 1; } +/* + * The BIOS is supposed to supply a single APIC/MADT, + * but some report two. Provide a knob to use either. + * (don't you wish instance 0 and 1 were not the same?) + */ +static void __init check_multiple_madt(void) +{ + struct acpi_table_header *table = NULL; + + acpi_get_table(ACPI_SIG_MADT, 2, &table); + if (table) { + printk(KERN_WARNING PREFIX + "BIOS bug: multiple APIC/MADT found," + " using %d\n", acpi_apic_instance); + printk(KERN_WARNING PREFIX + "If \"acpi_apic_instance=%d\" works better, " + "notify linux-acpi@vger.kernel.org\n", + acpi_apic_instance ? 0 : 2); + + } else + acpi_apic_instance = 0; + + return; +} + /* * acpi_table_init() * @@ -257,9 +291,22 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) * result: sdt_entry[] is initialized */ - int __init acpi_table_init(void) { acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); + check_multiple_madt(); + return 0; +} + +static int __init acpi_parse_apic_instance(char *str) +{ + + acpi_apic_instance = simple_strtoul(str, NULL, 0); + + printk(KERN_NOTICE PREFIX "Shall use APIC/MADT table %d\n", + acpi_apic_instance); + return 0; } + +early_param("acpi_apic_instance", acpi_parse_apic_instance); -- cgit From 09fe58356d148ff66901ddf639e725ca1a48a0af Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sun, 11 Mar 2007 03:32:00 -0400 Subject: ACPI: parse 2nd MADT by default http://bugzilla.kernel.org/show_bug.cgi?id=7465 Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 2 +- drivers/acpi/tables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi/tables.c') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 22c6b8ccaea5..f0b7a5e5740a 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -142,7 +142,7 @@ and is between 256 and 4096 characters. It is defined in the file Format: 2: use 2nd APIC table, if available 1,0: use 1st APIC table - default: 0 + default: 2 acpi_sleep= [HW,ACPI] Sleep options Format: { s3_bios, s3_mode } diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index c3419182c9a7..96792a6cc164 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -42,7 +42,7 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; -static int acpi_apic_instance __initdata; +static int acpi_apic_instance __initdata = 2; void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { -- cgit From 4e381a4f06e3c7b350b55a2636b9d45691780eba Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 30 Mar 2007 14:16:10 -0400 Subject: Revert "ACPI: parse 2nd MADT by default" This reverts commit 09fe58356d148ff66901ddf639e725ca1a48a0af. http://bugzilla.kernel.org/show_bug.cgi?id=8283 Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 2 +- drivers/acpi/tables.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/acpi/tables.c') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ef2ffded1392..12533a958c51 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -142,7 +142,7 @@ and is between 256 and 4096 characters. It is defined in the file Format: 2: use 2nd APIC table, if available 1,0: use 1st APIC table - default: 2 + default: 0 acpi_sleep= [HW,ACPI] Sleep options Format: { s3_bios, s3_mode } diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 96792a6cc164..c3419182c9a7 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -42,7 +42,7 @@ static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; -static int acpi_apic_instance __initdata = 2; +static int acpi_apic_instance __initdata; void acpi_table_print_madt_entry(struct acpi_subtable_header *header) { -- cgit