summaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/Kconfig4
-rw-r--r--arch/i386/kernel/acpi/boot.c2
-rw-r--r--arch/i386/kernel/acpi/wakeup.S5
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c9
-rw-r--r--arch/i386/kernel/head.S14
-rw-r--r--arch/i386/kernel/hpet.c2
-rw-r--r--arch/i386/kernel/irq.c5
-rw-r--r--arch/i386/kernel/setup.c32
-rw-r--r--arch/i386/kernel/traps.c29
-rw-r--r--arch/i386/pci/common.c5
-rw-r--r--arch/i386/pci/init.c8
-rw-r--r--arch/i386/pci/mmconfig.c36
-rw-r--r--arch/i386/pci/pci.h3
13 files changed, 70 insertions, 84 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index f71fb4a029cb..b2751eadbc56 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -142,6 +142,7 @@ config X86_SUMMIT
In particular, it is needed for the x440.
If you don't have one of these computers, you should say N here.
+ If you want to build a NUMA kernel, you must select ACPI.
config X86_BIGSMP
bool "Support for other sub-arch SMP systems with more than 8 CPUs"
@@ -169,6 +170,7 @@ config X86_GENERICARCH
help
This option compiles in the Summit, bigsmp, ES7000, default subarchitectures.
It is intended for a generic binary kernel.
+ If you want a NUMA kernel, select ACPI. We need SRAT for NUMA.
config X86_ES7000
bool "Support for Unisys ES7000 IA32 series"
@@ -542,7 +544,7 @@ config X86_PAE
# Common NUMA Features
config NUMA
bool "Numa Memory Allocation and Scheduler Support"
- depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
+ depends on SMP && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI)
default n if X86_PC
default y if (X86_NUMAQ || X86_SUMMIT)
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 0db6387025ca..ee003bc0e8b1 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -59,7 +59,7 @@ static inline int gsi_irq_sharing(int gsi) { return gsi; }
#define BAD_MADT_ENTRY(entry, end) ( \
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
- ((acpi_table_entry_header *)entry)->length != sizeof(*entry))
+ ((acpi_table_entry_header *)entry)->length < sizeof(*entry))
#define PREFIX "ACPI: "
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S
index 9f408eee4e6f..b781b38131c0 100644
--- a/arch/i386/kernel/acpi/wakeup.S
+++ b/arch/i386/kernel/acpi/wakeup.S
@@ -292,7 +292,10 @@ ENTRY(do_suspend_lowlevel)
pushl $3
call acpi_enter_sleep_state
addl $4, %esp
- ret
+
+# In case of S3 failure, we'll emerge here. Jump
+# to ret_point to recover
+ jmp ret_point
.p2align 4,,7
ret_point:
call restore_registers
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index efb41e81351c..e6ea00edcb54 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -567,16 +567,11 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
static int __init
acpi_cpufreq_init (void)
{
- int result = 0;
-
dprintk("acpi_cpufreq_init\n");
- result = acpi_cpufreq_early_init_acpi();
+ acpi_cpufreq_early_init_acpi();
- if (!result)
- result = cpufreq_register_driver(&acpi_cpufreq_driver);
-
- return (result);
+ return cpufreq_register_driver(&acpi_cpufreq_driver);
}
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index eb79aa2fa8bb..a6b8bd89aa27 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -317,20 +317,14 @@ is386: movl $2,%ecx # set MP
movl %eax,%gs
lldt %ax
cld # gcc2 wants the direction flag cleared at all times
+ pushl %eax # fake return address
#ifdef CONFIG_SMP
movb ready, %cl
movb $1, ready
- cmpb $0,%cl
- je 1f # the first CPU calls start_kernel
- # all other CPUs call initialize_secondary
- call initialize_secondary
- jmp L6
-1:
+ cmpb $0,%cl # the first CPU calls start_kernel
+ jne initialize_secondary # all other CPUs call initialize_secondary
#endif /* CONFIG_SMP */
- call start_kernel
-L6:
- jmp L6 # main should never return here, but
- # just in case, we know what happens.
+ jmp start_kernel
/*
* We depend on ET to be correct. This checks for 287/387.
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c
index c6737c35815d..17647a530b2f 100644
--- a/arch/i386/kernel/hpet.c
+++ b/arch/i386/kernel/hpet.c
@@ -35,7 +35,7 @@ static int __init init_hpet_clocksource(void)
void __iomem* hpet_base;
u64 tmp;
- if (!hpet_address)
+ if (!is_hpet_enabled())
return -ENODEV;
/* calculate the hpet address: */
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 6cb529f60dcc..5fe547cd8f9f 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -82,10 +82,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
}
#endif
- if (!irq_desc[irq].handle_irq) {
- __do_IRQ(irq, regs);
- goto out_exit;
- }
#ifdef CONFIG_4KSTACKS
curctx = (union irq_ctx *) current_thread_info();
@@ -125,7 +121,6 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
#endif
__do_IRQ(irq, regs);
-out_exit:
irq_exit();
return 1;
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index f1682206d304..345ffb7d904d 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -956,38 +956,6 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
return 0;
}
- /*
- * This function checks if the entire range <start,end> is mapped with type.
- *
- * Note: this function only works correct if the e820 table is sorted and
- * not-overlapping, which is the case
- */
-int __init
-e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
-{
- u64 start = s;
- u64 end = e;
- int i;
- for (i = 0; i < e820.nr_map; i++) {
- struct e820entry *ei = &e820.map[i];
- if (type && ei->type != type)
- continue;
- /* is the region (part) in overlap with the current region ?*/
- if (ei->addr >= end || ei->addr + ei->size <= start)
- continue;
- /* if the region is at the beginning of <start,end> we move
- * start to the end of the region since it's ok until there
- */
- if (ei->addr <= start)
- start = ei->addr + ei->size;
- /* if start is now at or beyond end, we're done, full
- * coverage */
- if (start >= end)
- return 1; /* we're done */
- }
- return 0;
-}
-
/*
* Find the highest page frame number we have available
*/
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 0d4005dc06c5..7e9edafffd8a 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -92,7 +92,11 @@ asmlinkage void spurious_interrupt_bug(void);
asmlinkage void machine_check(void);
static int kstack_depth_to_print = 24;
+#ifdef CONFIG_STACK_UNWIND
static int call_trace = 1;
+#else
+#define call_trace (-1)
+#endif
ATOMIC_NOTIFIER_HEAD(i386die_chain);
int register_die_notifier(struct notifier_block *nb)
@@ -187,22 +191,21 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
if (unwind_init_blocked(&info, task) == 0)
unw_ret = show_trace_unwind(&info, log_lvl);
}
- if (unw_ret > 0 && !arch_unw_user_mode(&info)) {
-#ifdef CONFIG_STACK_UNWIND
- print_symbol("DWARF2 unwinder stuck at %s\n",
- UNW_PC(&info));
- if (call_trace == 1) {
- printk("Leftover inexact backtrace:\n");
- if (UNW_SP(&info))
+ if (unw_ret > 0) {
+ if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+ print_symbol("DWARF2 unwinder stuck at %s\n",
+ UNW_PC(&info));
+ if (UNW_SP(&info) >= PAGE_OFFSET) {
+ printk("Leftover inexact backtrace:\n");
stack = (void *)UNW_SP(&info);
- } else if (call_trace > 1)
+ } else
+ printk("Full inexact backtrace again:\n");
+ } else if (call_trace >= 1)
return;
else
printk("Full inexact backtrace again:\n");
-#else
+ } else
printk("Inexact backtrace:\n");
-#endif
- }
}
if (task == current) {
@@ -454,7 +457,7 @@ void die(const char * str, struct pt_regs * regs, long err)
panic("Fatal exception in interrupt");
if (panic_on_oops)
- panic("Fatal exception: panic_on_oops");
+ panic("Fatal exception");
oops_exit();
do_exit(SIGSEGV);
@@ -1241,6 +1244,7 @@ static int __init kstack_setup(char *s)
}
__setup("kstack=", kstack_setup);
+#ifdef CONFIG_STACK_UNWIND
static int __init call_trace_setup(char *s)
{
if (strcmp(s, "old") == 0)
@@ -1254,3 +1258,4 @@ static int __init call_trace_setup(char *s)
return 1;
}
__setup("call_trace=", call_trace_setup);
+#endif
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 0a362e3aeac5..1220dd828ce3 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -237,6 +237,11 @@ char * __devinit pcibios_setup(char *str)
pci_probe &= ~PCI_PROBE_MMCONF;
return NULL;
}
+ /* override DMI blacklist */
+ else if (!strcmp(str, "mmconf")) {
+ pci_probe |= PCI_PROBE_MMCONF_FORCE;
+ return NULL;
+ }
#endif
else if (!strcmp(str, "noacpi")) {
acpi_noirq_set();
diff --git a/arch/i386/pci/init.c b/arch/i386/pci/init.c
index c7650a7e0b07..51087a9d9172 100644
--- a/arch/i386/pci/init.c
+++ b/arch/i386/pci/init.c
@@ -14,8 +14,12 @@ static __init int pci_access_init(void)
#ifdef CONFIG_PCI_BIOS
pci_pcbios_init();
#endif
- if (raw_pci_ops)
- return 0;
+ /*
+ * don't check for raw_pci_ops here because we want pcbios as last
+ * fallback, yet it's needed to run first to set pcibios_last_bus
+ * in case legacy PCI probing is used. otherwise detecting peer busses
+ * fails.
+ */
#ifdef CONFIG_PCI_DIRECT
pci_direct_init();
#endif
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index e545b0992c48..ef5a2faa7d82 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -12,6 +12,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/dmi.h>
#include <asm/e820.h>
#include "pci.h"
@@ -178,7 +179,7 @@ static __init void unreachable_devices(void)
pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
if (addr == 0 ||
readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
- set_bit(i, fallback_slots);
+ set_bit(i + 32*k, fallback_slots);
printk(KERN_NOTICE
"PCI: No mmconfig possible on %x:%x\n", k, i);
}
@@ -187,9 +188,31 @@ static __init void unreachable_devices(void)
}
}
+static int disable_mcfg(struct dmi_system_id *d)
+{
+ printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
+ pci_probe &= ~PCI_PROBE_MMCONF;
+ return 0;
+}
+
+static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
+ /* Has broken MCFG table that makes the system hang when used */
+ {
+ .callback = disable_mcfg,
+ .ident = "Intel D3C5105 SDV",
+ .matches = {
+ DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
+ DMI_MATCH(DMI_BOARD_NAME, "D26928"),
+ },
+ },
+ {}
+};
+
void __init pci_mmcfg_init(void)
{
- if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+ dmi_check_system(dmi_bad_mcfg);
+
+ if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0)
return;
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
@@ -198,15 +221,6 @@ void __init pci_mmcfg_init(void)
(pci_mmcfg_config[0].base_address == 0))
return;
- if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
- pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
- E820_RESERVED)) {
- printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
- pci_mmcfg_config[0].base_address);
- printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
- return;
- }
-
printk(KERN_INFO "PCI: Using MMCONFIG\n");
raw_pci_ops = &pci_mmcfg;
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index bf4e79335388..49a849b3a241 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -16,7 +16,8 @@
#define PCI_PROBE_CONF1 0x0002
#define PCI_PROBE_CONF2 0x0004
#define PCI_PROBE_MMCONF 0x0008
-#define PCI_PROBE_MASK 0x000f
+#define PCI_PROBE_MMCONF_FORCE 0x0010
+#define PCI_PROBE_MASK 0x00ff
#define PCI_NO_SORT 0x0100
#define PCI_BIOS_SORT 0x0200