Commit 381b26f0 authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] Workaround "_BBN 0" BIOS bug

enhance "pci=noacpi" to skip ACPI PCI configuration and interrupt config
add "acpi=noirq" to skip just ACPI interrupt config (David Shaohua Li)
http://bugzilla.kernel.org/show_bug.cgi?id=1662
parent f7e2224a
...@@ -91,13 +91,14 @@ running once the system is up. ...@@ -91,13 +91,14 @@ running once the system is up.
acpi= [HW,ACPI] Advanced Configuration and Power Interface acpi= [HW,ACPI] Advanced Configuration and Power Interface
Format: { force | off | ht | strict } Format: { force | off | ht | strict }
force -- enables ACPI for systems with default off force -- enable ACPI if default was off
off -- disabled ACPI for systems with default on off -- disable ACPI if default was on
noirq -- do not use ACPI for IRQ routing
ht -- run only enough ACPI to enable Hyper Threading ht -- run only enough ACPI to enable Hyper Threading
strict -- Be less tolerant of platforms that are not strict -- Be less tolerant of platforms that are not
strictly ACPI specification compliant. strictly ACPI specification compliant.
See also Documentation/pm.txt. See also Documentation/pm.txt, pci=noacpi
acpi_sleep= [HW,ACPI] Sleep options acpi_sleep= [HW,ACPI] Sleep options
Format: { s3_bios, s3_mode } Format: { s3_bios, s3_mode }
...@@ -831,7 +832,8 @@ running once the system is up. ...@@ -831,7 +832,8 @@ running once the system is up.
and Omnibook XE3 notebooks. This will and Omnibook XE3 notebooks. This will
have no effect if ACPI IRQ routing is have no effect if ACPI IRQ routing is
enabled. enabled.
noacpi [IA-32] Do not use ACPI for IRQ routing. noacpi [IA-32] Do not use ACPI for IRQ routing
or for PCI scanning.
pcmv= [HW,PCMCIA] BadgePAD 4 pcmv= [HW,PCMCIA] BadgePAD 4
......
...@@ -53,7 +53,13 @@ static inline int ioapic_setup_disabled(void) { return 0; } ...@@ -53,7 +53,13 @@ static inline int ioapic_setup_disabled(void) { return 0; }
#define PREFIX "ACPI: " #define PREFIX "ACPI: "
#ifdef CONFIG_ACPI_PCI
int acpi_noirq __initdata; /* skip ACPI IRQ initialization */ int acpi_noirq __initdata; /* skip ACPI IRQ initialization */
int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */
#else
int acpi_noirq __initdata = 1;
int acpi_pci_disabled __initdata = 1;
#endif
int acpi_ht __initdata = 1; /* enable HT */ int acpi_ht __initdata = 1; /* enable HT */
int acpi_lapic; int acpi_lapic;
......
...@@ -531,12 +531,18 @@ static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d) ...@@ -531,12 +531,18 @@ static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d)
#endif #endif
#ifdef CONFIG_ACPI_PCI #ifdef CONFIG_ACPI_PCI
static __init int disable_acpi_irq(struct dmi_blacklist *d)
{
printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n", d->ident);
acpi_noirq_set();
return 0;
}
static __init int disable_acpi_pci(struct dmi_blacklist *d) static __init int disable_acpi_pci(struct dmi_blacklist *d)
{ {
printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", d->ident); printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", d->ident);
acpi_noirq_set(); acpi_disable_pci();
return 0; return 0;
} }
#endif #endif
/* /*
...@@ -951,13 +957,21 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={ ...@@ -951,13 +957,21 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={
* Boxes that need ACPI PCI IRQ routing disabled * Boxes that need ACPI PCI IRQ routing disabled
*/ */
{ disable_acpi_pci, "ASUS A7V", { { disable_acpi_irq, "ASUS A7V", {
MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"), MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
MATCH(DMI_BOARD_NAME, "<A7V>"), MATCH(DMI_BOARD_NAME, "<A7V>"),
/* newer BIOS, Revision 1011, does work */ /* newer BIOS, Revision 1011, does work */
MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"), MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
NO_MATCH }}, NO_MATCH }},
/*
* Boxes that need ACPI PCI IRQ routing and PCI scan disabled
*/
{ disable_acpi_pci, "ASUS PR-DLS", { /* _BBN 0 bug */
MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
MATCH(DMI_BOARD_NAME, "PR-DLS"),
MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
MATCH(DMI_BIOS_DATE, "03/21/2003") }},
#endif #endif
{ NULL, } { NULL, }
......
...@@ -596,9 +596,13 @@ static void __init parse_cmdline_early (char ** cmdline_p) ...@@ -596,9 +596,13 @@ static void __init parse_cmdline_early (char ** cmdline_p)
disable_acpi(); disable_acpi();
acpi_ht = 1; acpi_ht = 1;
} }
/* "pci=noacpi" disables ACPI interrupt routing */ /* "pci=noacpi" disable ACPI IRQ routing and PCI scan */
else if (!memcmp(from, "pci=noacpi", 10)) { else if (!memcmp(from, "pci=noacpi", 10)) {
acpi_disable_pci();
}
/* "acpi=noirq" disables ACPI interrupt routing */
else if (!memcmp(from, "acpi=noirq", 10)) {
acpi_noirq_set(); acpi_noirq_set();
} }
......
...@@ -64,8 +64,8 @@ struct cpuinfo_x86 boot_cpu_data; ...@@ -64,8 +64,8 @@ struct cpuinfo_x86 boot_cpu_data;
unsigned long mmu_cr4_features; unsigned long mmu_cr4_features;
EXPORT_SYMBOL_GPL(mmu_cr4_features); EXPORT_SYMBOL_GPL(mmu_cr4_features);
int acpi_disabled = 0; int acpi_disabled;
EXPORT_SYMBOL(acpi_disabled);
#ifdef CONFIG_ACPI_BOOT #ifdef CONFIG_ACPI_BOOT
extern int __initdata acpi_ht; extern int __initdata acpi_ht;
extern acpi_interrupt_flags acpi_sci_flags; extern acpi_interrupt_flags acpi_sci_flags;
...@@ -217,7 +217,7 @@ static __init void parse_cmdline_early (char ** cmdline_p) ...@@ -217,7 +217,7 @@ static __init void parse_cmdline_early (char ** cmdline_p)
#ifdef CONFIG_ACPI_BOOT #ifdef CONFIG_ACPI_BOOT
/* "acpi=off" disables both ACPI table parsing and interpreter init */ /* "acpi=off" disables both ACPI table parsing and interpreter init */
if (!memcmp(from, "acpi=off", 8)) if (!memcmp(from, "acpi=off", 8))
acpi_disabled = 1; disable_acpi();
if (!memcmp(from, "acpi=force", 10)) { if (!memcmp(from, "acpi=force", 10)) {
/* add later when we do DMI horrors: */ /* add later when we do DMI horrors: */
...@@ -231,7 +231,9 @@ static __init void parse_cmdline_early (char ** cmdline_p) ...@@ -231,7 +231,9 @@ static __init void parse_cmdline_early (char ** cmdline_p)
acpi_ht = 1; acpi_ht = 1;
} }
else if (!memcmp(from, "pci=noacpi", 10)) else if (!memcmp(from, "pci=noacpi", 10))
acpi_noirq_set(); acpi_disable_pci();
else if (!memcmp(from, "acpi=noirq", 10))
acpi_noirq_set();
else if (!memcmp(from, "acpi_sci=edge", 13)) else if (!memcmp(from, "acpi_sci=edge", 13))
acpi_sci_flags.trigger = 1; acpi_sci_flags.trigger = 1;
......
...@@ -793,7 +793,7 @@ static int __init acpi_pci_link_init (void) ...@@ -793,7 +793,7 @@ static int __init acpi_pci_link_init (void)
{ {
ACPI_FUNCTION_TRACE("acpi_pci_link_init"); ACPI_FUNCTION_TRACE("acpi_pci_link_init");
if (acpi_disabled) if (acpi_pci_disabled)
return_VALUE(0); return_VALUE(0);
acpi_link.count = 0; acpi_link.count = 0;
......
...@@ -119,6 +119,7 @@ acpi_pci_root_add ( ...@@ -119,6 +119,7 @@ acpi_pci_root_add (
{ {
int result = 0; int result = 0;
struct acpi_pci_root *root = NULL; struct acpi_pci_root *root = NULL;
struct acpi_pci_root *tmp;
acpi_status status = AE_OK; acpi_status status = AE_OK;
unsigned long value = 0; unsigned long value = 0;
acpi_handle handle = NULL; acpi_handle handle = NULL;
...@@ -186,6 +187,13 @@ acpi_pci_root_add ( ...@@ -186,6 +187,13 @@ acpi_pci_root_add (
goto end; goto end;
} }
/* Some systems have wrong _BBN */
list_for_each_entry(tmp, &acpi_pci_roots, node) {
if ((tmp->id.segment == root->id.segment)
&& (tmp->id.bus == root->id.bus))
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
}
/* /*
* Device & Function * Device & Function
* ----------------- * -----------------
...@@ -272,7 +280,7 @@ static int __init acpi_pci_root_init (void) ...@@ -272,7 +280,7 @@ static int __init acpi_pci_root_init (void)
{ {
ACPI_FUNCTION_TRACE("acpi_pci_root_init"); ACPI_FUNCTION_TRACE("acpi_pci_root_init");
if (acpi_disabled) if (acpi_pci_disabled)
return_VALUE(0); return_VALUE(0);
/* DEBUG: /* DEBUG:
......
...@@ -109,7 +109,14 @@ extern int acpi_noirq; ...@@ -109,7 +109,14 @@ extern int acpi_noirq;
extern int acpi_strict; extern int acpi_strict;
extern int acpi_disabled; extern int acpi_disabled;
extern int acpi_ht; extern int acpi_ht;
static inline void disable_acpi(void) { acpi_disabled = 1; acpi_ht = 0; } extern int acpi_pci_disabled;
static inline void disable_acpi(void)
{
acpi_disabled = 1;
acpi_ht = 0;
acpi_pci_disabled = 1;
acpi_noirq = 1;
}
/* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */ /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */
#define FIX_ACPI_PAGES 4 #define FIX_ACPI_PAGES 4
...@@ -143,9 +150,15 @@ static inline void disable_ioapic_setup(void) ...@@ -143,9 +150,15 @@ static inline void disable_ioapic_setup(void)
#ifdef CONFIG_ACPI_PCI #ifdef CONFIG_ACPI_PCI
static inline void acpi_noirq_set(void) { acpi_noirq = 1; } static inline void acpi_noirq_set(void) { acpi_noirq = 1; }
static inline void acpi_disable_pci(void)
{
acpi_pci_disabled = 1;
acpi_noirq_set();
}
extern int acpi_irq_balance_set(char *str); extern int acpi_irq_balance_set(char *str);
#else #else
static inline void acpi_noirq_set(void) { } static inline void acpi_noirq_set(void) { }
static inline void acpi_disable_pci(void) { }
static inline int acpi_irq_balance_set(char *str) { return 0; } static inline int acpi_irq_balance_set(char *str) { return 0; }
#endif #endif
......
...@@ -89,6 +89,7 @@ ia64_acpi_release_global_lock (unsigned int *lock) ...@@ -89,6 +89,7 @@ ia64_acpi_release_global_lock (unsigned int *lock)
((Acq) = ia64_acpi_release_global_lock((unsigned int *) GLptr)) ((Acq) = ia64_acpi_release_global_lock((unsigned int *) GLptr))
#define acpi_disabled 0 /* ACPI always enabled on IA64 */ #define acpi_disabled 0 /* ACPI always enabled on IA64 */
#define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */
#define acpi_strict 1 /* no ACPI spec workarounds on IA64 */ #define acpi_strict 1 /* no ACPI spec workarounds on IA64 */
static inline void disable_acpi(void) { } static inline void disable_acpi(void) { }
......
...@@ -106,8 +106,15 @@ extern int acpi_ioapic; ...@@ -106,8 +106,15 @@ extern int acpi_ioapic;
extern int acpi_noirq; extern int acpi_noirq;
extern int acpi_strict; extern int acpi_strict;
extern int acpi_disabled; extern int acpi_disabled;
extern int acpi_pci_disabled;
extern int acpi_ht; extern int acpi_ht;
static inline void disable_acpi(void) { acpi_disabled = 1; acpi_ht = 0; } static inline void disable_acpi(void)
{
acpi_disabled = 1;
acpi_ht = 0;
acpi_pci_disabled = 1;
acpi_noirq = 1;
}
/* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */ /* Fixmap pages to reserve for ACPI boot-time tables (see fixmap.h) */
#define FIX_ACPI_PAGES 4 #define FIX_ACPI_PAGES 4
...@@ -121,9 +128,15 @@ extern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq); ...@@ -121,9 +128,15 @@ extern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq);
#ifdef CONFIG_ACPI_PCI #ifdef CONFIG_ACPI_PCI
static inline void acpi_noirq_set(void) { acpi_noirq = 1; } static inline void acpi_noirq_set(void) { acpi_noirq = 1; }
static inline void acpi_disable_pci(void)
{
acpi_pci_disabled = 1;
acpi_noirq_set();
}
extern int acpi_irq_balance_set(char *str); extern int acpi_irq_balance_set(char *str);
#else #else
static inline void acpi_noirq_set(void) { } static inline void acpi_noirq_set(void) { }
static inline void acpi_disable_pci(void) { }
static inline int acpi_irq_balance_set(char *str) { return 0; } static inline int acpi_irq_balance_set(char *str) { return 0; }
#endif #endif
...@@ -144,6 +157,7 @@ extern void acpi_reserve_bootmem(void); ...@@ -144,6 +157,7 @@ extern void acpi_reserve_bootmem(void);
#define boot_cpu_physical_apicid boot_cpu_id #define boot_cpu_physical_apicid boot_cpu_id
extern int acpi_disabled; extern int acpi_disabled;
extern int acpi_pci_disabled;
#define dmi_broken (0) #define dmi_broken (0)
#define BROKEN_ACPI_Sx 0x0001 #define BROKEN_ACPI_Sx 0x0001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment