diff options
Diffstat (limited to 'arch/x86/mach-generic')
-rw-r--r-- | arch/x86/mach-generic/Makefile | 8 | ||||
-rw-r--r-- | arch/x86/mach-generic/bigsmp.c | 57 | ||||
-rw-r--r-- | arch/x86/mach-generic/default.c | 26 | ||||
-rw-r--r-- | arch/x86/mach-generic/es7000.c | 69 | ||||
-rw-r--r-- | arch/x86/mach-generic/probe.c | 125 | ||||
-rw-r--r-- | arch/x86/mach-generic/summit.c | 27 |
6 files changed, 312 insertions, 0 deletions
diff --git a/arch/x86/mach-generic/Makefile b/arch/x86/mach-generic/Makefile new file mode 100644 index 00000000000..19d6d407737 --- /dev/null +++ b/arch/x86/mach-generic/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the generic architecture +# + +EXTRA_CFLAGS := -Iarch/x86/kernel + +obj-y := probe.o summit.o bigsmp.o es7000.o default.o +obj-y += ../../x86/mach-es7000/ diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c new file mode 100644 index 00000000000..292a225edab --- /dev/null +++ b/arch/x86/mach-generic/bigsmp.c @@ -0,0 +1,57 @@ +/* + * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs. + * Drives the local APIC in "clustered mode". + */ +#define APIC_DEFINITION 1 +#include <linux/threads.h> +#include <linux/cpumask.h> +#include <asm/smp.h> +#include <asm/mpspec.h> +#include <asm/genapic.h> +#include <asm/fixmap.h> +#include <asm/apicdef.h> +#include <linux/kernel.h> +#include <linux/smp.h> +#include <linux/init.h> +#include <linux/dmi.h> +#include <asm/mach-bigsmp/mach_apic.h> +#include <asm/mach-bigsmp/mach_apicdef.h> +#include <asm/mach-bigsmp/mach_ipi.h> +#include <asm/mach-default/mach_mpparse.h> + +static int dmi_bigsmp; /* can be set by dmi scanners */ + +static int hp_ht_bigsmp(const struct dmi_system_id *d) +{ +#ifdef CONFIG_X86_GENERICARCH + printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident); + dmi_bigsmp = 1; +#endif + return 0; +} + + +static const struct dmi_system_id bigsmp_dmi_table[] = { + { hp_ht_bigsmp, "HP ProLiant DL760 G2", { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_BIOS_VERSION, "P44-"), + }}, + + { hp_ht_bigsmp, "HP ProLiant DL740", { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_BIOS_VERSION, "P47-"), + }}, + { } +}; + + +static int probe_bigsmp(void) +{ + if (def_to_bigsmp) + dmi_bigsmp = 1; + else + dmi_check_system(bigsmp_dmi_table); + return dmi_bigsmp; +} + +struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp); diff --git a/arch/x86/mach-generic/default.c b/arch/x86/mach-generic/default.c new file mode 100644 index 00000000000..8685208d851 --- /dev/null +++ b/arch/x86/mach-generic/default.c @@ -0,0 +1,26 @@ +/* + * Default generic APIC driver. This handles upto 8 CPUs. + */ +#define APIC_DEFINITION 1 +#include <linux/threads.h> +#include <linux/cpumask.h> +#include <asm/mpspec.h> +#include <asm/mach-default/mach_apicdef.h> +#include <asm/genapic.h> +#include <asm/fixmap.h> +#include <asm/apicdef.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/smp.h> +#include <linux/init.h> +#include <asm/mach-default/mach_apic.h> +#include <asm/mach-default/mach_ipi.h> +#include <asm/mach-default/mach_mpparse.h> + +/* should be called last. */ +static int probe_default(void) +{ + return 1; +} + +struct genapic apic_default = APIC_INIT("default", probe_default); diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c new file mode 100644 index 00000000000..4742626f08c --- /dev/null +++ b/arch/x86/mach-generic/es7000.c @@ -0,0 +1,69 @@ +/* + * APIC driver for the Unisys ES7000 chipset. + */ +#define APIC_DEFINITION 1 +#include <linux/threads.h> +#include <linux/cpumask.h> +#include <asm/smp.h> +#include <asm/mpspec.h> +#include <asm/genapic.h> +#include <asm/fixmap.h> +#include <asm/apicdef.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/smp.h> +#include <linux/init.h> +#include <asm/mach-es7000/mach_apicdef.h> +#include <asm/mach-es7000/mach_apic.h> +#include <asm/mach-es7000/mach_ipi.h> +#include <asm/mach-es7000/mach_mpparse.h> +#include <asm/mach-es7000/mach_wakecpu.h> + +static int probe_es7000(void) +{ + /* probed later in mptable/ACPI hooks */ + return 0; +} + +extern void es7000_sw_apic(void); +static void __init enable_apic_mode(void) +{ + es7000_sw_apic(); + return; +} + +static __init int mps_oem_check(struct mp_config_table *mpc, char *oem, + char *productid) +{ + if (mpc->mpc_oemptr) { + struct mp_config_oemtable *oem_table = + (struct mp_config_oemtable *)mpc->mpc_oemptr; + if (!strncmp(oem, "UNISYS", 6)) + return parse_unisys_oem((char *)oem_table); + } + return 0; +} + +#ifdef CONFIG_ACPI +/* Hook from generic ACPI tables.c */ +static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + unsigned long oem_addr; + if (!find_unisys_acpi_oem_table(&oem_addr)) { + if (es7000_check_dsdt()) + return parse_unisys_oem((char *)oem_addr); + else { + setup_unisys(); + return 1; + } + } + return 0; +} +#else +static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + return 0; +} +#endif + +struct genapic __initdata_refok apic_es7000 = APIC_INIT("es7000", probe_es7000); diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c new file mode 100644 index 00000000000..74f3da63442 --- /dev/null +++ b/arch/x86/mach-generic/probe.c @@ -0,0 +1,125 @@ +/* Copyright 2003 Andi Kleen, SuSE Labs. + * Subject to the GNU Public License, v.2 + * + * Generic x86 APIC driver probe layer. + */ +#include <linux/threads.h> +#include <linux/cpumask.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/ctype.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <asm/fixmap.h> +#include <asm/mpspec.h> +#include <asm/apicdef.h> +#include <asm/genapic.h> + +extern struct genapic apic_summit; +extern struct genapic apic_bigsmp; +extern struct genapic apic_es7000; +extern struct genapic apic_default; + +struct genapic *genapic = &apic_default; + +struct genapic *apic_probe[] __initdata = { + &apic_summit, + &apic_bigsmp, + &apic_es7000, + &apic_default, /* must be last */ + NULL, +}; + +static int cmdline_apic __initdata; +static int __init parse_apic(char *arg) +{ + int i; + + if (!arg) + return -EINVAL; + + for (i = 0; apic_probe[i]; i++) { + if (!strcmp(apic_probe[i]->name, arg)) { + genapic = apic_probe[i]; + cmdline_apic = 1; + return 0; + } + } + + /* Parsed again by __setup for debug/verbose */ + return 0; +} +early_param("apic", parse_apic); + +void __init generic_bigsmp_probe(void) +{ + /* + * This routine is used to switch to bigsmp mode when + * - There is no apic= option specified by the user + * - generic_apic_probe() has choosen apic_default as the sub_arch + * - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support + */ + + if (!cmdline_apic && genapic == &apic_default) + if (apic_bigsmp.probe()) { + genapic = &apic_bigsmp; + printk(KERN_INFO "Overriding APIC driver with %s\n", + genapic->name); + } +} + +void __init generic_apic_probe(void) +{ + if (!cmdline_apic) { + int i; + for (i = 0; apic_probe[i]; i++) { + if (apic_probe[i]->probe()) { + genapic = apic_probe[i]; + break; + } + } + /* Not visible without early console */ + if (!apic_probe[i]) + panic("Didn't find an APIC driver"); + } + printk(KERN_INFO "Using APIC driver %s\n", genapic->name); +} + +/* These functions can switch the APIC even after the initial ->probe() */ + +int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) +{ + int i; + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) { + if (!cmdline_apic) { + genapic = apic_probe[i]; + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + genapic->name); + } + return 1; + } + } + return 0; +} + +int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + int i; + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { + if (!cmdline_apic) { + genapic = apic_probe[i]; + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + genapic->name); + } + return 1; + } + } + return 0; +} + +int hard_smp_processor_id(void) +{ + return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); +} diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c new file mode 100644 index 00000000000..74883ccb8f7 --- /dev/null +++ b/arch/x86/mach-generic/summit.c @@ -0,0 +1,27 @@ +/* + * APIC driver for the IBM "Summit" chipset. + */ +#define APIC_DEFINITION 1 +#include <linux/threads.h> +#include <linux/cpumask.h> +#include <asm/smp.h> +#include <asm/mpspec.h> +#include <asm/genapic.h> +#include <asm/fixmap.h> +#include <asm/apicdef.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/smp.h> +#include <linux/init.h> +#include <asm/mach-summit/mach_apic.h> +#include <asm/mach-summit/mach_apicdef.h> +#include <asm/mach-summit/mach_ipi.h> +#include <asm/mach-summit/mach_mpparse.h> + +static int probe_summit(void) +{ + /* probed later in mptable/ACPI hooks */ + return 0; +} + +struct genapic apic_summit = APIC_INIT("summit", probe_summit); |