Commit 1b9b89e7 authored by Yinghai Lu's avatar Yinghai Lu Committed by Ingo Molnar

x86: add apic probe for genapic 64bit, v2

introducing an APIC handling probing abstraction:

 static struct genapic *apic_probe[] __initdata = {
	&apic_x2apic_uv_x,
	&apic_x2apic_phys,
	&apic_x2apic_cluster,
	&apic_physflat,
	NULL,
 };

This way we can remove UV, x2apic specific code from genapic_64.c and
move them to their specific genapic files.

[ v2: fix compiling when CONFIG_ACPI is not set ]
Signed-off-by: default avatarYinghai Lu <yhlu.kernel@gmail.com>
Cc: Jack Steiner <steiner@sgi.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 76c3bb15
...@@ -16,62 +16,37 @@ ...@@ -16,62 +16,37 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include <linux/dmar.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/ipi.h> #include <asm/ipi.h>
#include <asm/genapic.h> #include <asm/genapic.h>
#ifdef CONFIG_ACPI extern struct genapic apic_flat;
#include <acpi/acpi_bus.h> extern struct genapic apic_physflat;
#endif extern struct genapic apic_x2xpic_uv_x;
extern struct genapic apic_x2apic_phys;
DEFINE_PER_CPU(int, x2apic_extra_bits); extern struct genapic apic_x2apic_cluster;
struct genapic __read_mostly *genapic = &apic_flat; struct genapic __read_mostly *genapic = &apic_flat;
static int x2apic_phys = 0; static struct genapic *apic_probe[] __initdata = {
&apic_x2apic_uv_x,
static int set_x2apic_phys_mode(char *arg) &apic_x2apic_phys,
{ &apic_x2apic_cluster,
x2apic_phys = 1; &apic_physflat,
return 0; NULL,
} };
early_param("x2apic_phys", set_x2apic_phys_mode);
static enum uv_system_type uv_system_type;
/* /*
* Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
*/ */
void __init setup_apic_routing(void) void __init setup_apic_routing(void)
{ {
if (uv_system_type == UV_NON_UNIQUE_APIC) if (genapic == &apic_flat) {
genapic = &apic_x2apic_uv_x; if (max_physical_apicid >= 8)
else if (cpu_has_x2apic && intr_remapping_enabled) {
if (x2apic_phys)
genapic = &apic_x2apic_phys;
else
genapic = &apic_x2apic_cluster;
} else
#ifdef CONFIG_ACPI
/*
* Quirk: some x86_64 machines can only use physical APIC mode
* regardless of how many processors are present (x86_64 ES7000
* is an example).
*/
if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
genapic = &apic_physflat; genapic = &apic_physflat;
else
#endif
if (max_physical_apicid < 8)
genapic = &apic_flat;
else
genapic = &apic_physflat;
printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name); printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
}
} }
/* Same for both flat and physical. */ /* Same for both flat and physical. */
...@@ -83,23 +58,15 @@ void apic_send_IPI_self(int vector) ...@@ -83,23 +58,15 @@ void apic_send_IPI_self(int vector)
int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{ {
if (!strcmp(oem_id, "SGI")) { int i;
if (!strcmp(oem_table_id, "UVL"))
uv_system_type = UV_LEGACY_APIC; for (i = 0; apic_probe[i]; ++i) {
else if (!strcmp(oem_table_id, "UVX")) if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
uv_system_type = UV_X2APIC; genapic = apic_probe[i];
else if (!strcmp(oem_table_id, "UVH")) printk(KERN_INFO "Setting APIC routing to %s.\n",
uv_system_type = UV_NON_UNIQUE_APIC; genapic->name);
return 1;
}
} }
return 0; return 0;
} }
enum uv_system_type get_uv_system_type(void)
{
return uv_system_type;
}
int is_uv_system(void)
{
return uv_system_type != UV_NONE;
}
...@@ -21,6 +21,15 @@ ...@@ -21,6 +21,15 @@
#include <asm/genapic.h> #include <asm/genapic.h>
#include <mach_apicdef.h> #include <mach_apicdef.h>
#ifdef CONFIG_ACPI
#include <acpi/acpi_bus.h>
#endif
static int __init flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
return 1;
}
static cpumask_t flat_target_cpus(void) static cpumask_t flat_target_cpus(void)
{ {
return cpu_online_map; return cpu_online_map;
...@@ -138,6 +147,7 @@ static unsigned int phys_pkg_id(int index_msb) ...@@ -138,6 +147,7 @@ static unsigned int phys_pkg_id(int index_msb)
struct genapic apic_flat = { struct genapic apic_flat = {
.name = "flat", .name = "flat",
.acpi_madt_oem_check = flat_acpi_madt_oem_check,
.int_delivery_mode = dest_LowestPrio, .int_delivery_mode = dest_LowestPrio,
.int_dest_mode = (APIC_DEST_LOGICAL != 0), .int_dest_mode = (APIC_DEST_LOGICAL != 0),
.target_cpus = flat_target_cpus, .target_cpus = flat_target_cpus,
...@@ -160,6 +170,21 @@ struct genapic apic_flat = { ...@@ -160,6 +170,21 @@ struct genapic apic_flat = {
* We cannot use logical delivery in this case because the mask * We cannot use logical delivery in this case because the mask
* overflows, so use physical mode. * overflows, so use physical mode.
*/ */
static int __init physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
#ifdef CONFIG_ACPI
/*
* Quirk: some x86_64 machines can only use physical APIC mode
* regardless of how many processors are present (x86_64 ES7000
* is an example).
*/
if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL))
return 1;
#endif
return 0;
}
static cpumask_t physflat_target_cpus(void) static cpumask_t physflat_target_cpus(void)
{ {
...@@ -206,6 +231,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask) ...@@ -206,6 +231,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
struct genapic apic_physflat = { struct genapic apic_physflat = {
.name = "physical flat", .name = "physical flat",
.acpi_madt_oem_check = physflat_acpi_madt_oem_check,
.int_delivery_mode = dest_Fixed, .int_delivery_mode = dest_Fixed,
.int_dest_mode = (APIC_DEST_PHYSICAL != 0), .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
.target_cpus = physflat_target_cpus, .target_cpus = physflat_target_cpus,
......
...@@ -4,12 +4,22 @@ ...@@ -4,12 +4,22 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/dmar.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/ipi.h> #include <asm/ipi.h>
#include <asm/genapic.h> #include <asm/genapic.h>
DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid); DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
if (cpu_has_x2apic && intr_remapping_enabled)
return 1;
return 0;
}
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
static cpumask_t x2apic_target_cpus(void) static cpumask_t x2apic_target_cpus(void)
...@@ -135,6 +145,7 @@ static void init_x2apic_ldr(void) ...@@ -135,6 +145,7 @@ static void init_x2apic_ldr(void)
struct genapic apic_x2apic_cluster = { struct genapic apic_x2apic_cluster = {
.name = "cluster x2apic", .name = "cluster x2apic",
.acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
.int_delivery_mode = dest_LowestPrio, .int_delivery_mode = dest_LowestPrio,
.int_dest_mode = (APIC_DEST_LOGICAL != 0), .int_dest_mode = (APIC_DEST_LOGICAL != 0),
.target_cpus = x2apic_target_cpus, .target_cpus = x2apic_target_cpus,
......
...@@ -4,10 +4,30 @@ ...@@ -4,10 +4,30 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/dmar.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/ipi.h> #include <asm/ipi.h>
#include <asm/genapic.h> #include <asm/genapic.h>
DEFINE_PER_CPU(int, x2apic_extra_bits);
static int x2apic_phys;
static int set_x2apic_phys_mode(char *arg)
{
x2apic_phys = 1;
return 0;
}
early_param("x2apic_phys", set_x2apic_phys_mode);
static int __init x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
if (cpu_has_x2apic && intr_remapping_enabled && x2apic_phys)
return 1;
return 0;
}
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */ /* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
...@@ -122,6 +142,7 @@ void init_x2apic_ldr(void) ...@@ -122,6 +142,7 @@ void init_x2apic_ldr(void)
struct genapic apic_x2apic_phys = { struct genapic apic_x2apic_phys = {
.name = "physical x2apic", .name = "physical x2apic",
.acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
.int_delivery_mode = dest_Fixed, .int_delivery_mode = dest_Fixed,
.int_dest_mode = (APIC_DEST_PHYSICAL != 0), .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
.target_cpus = x2apic_target_cpus, .target_cpus = x2apic_target_cpus,
......
...@@ -27,6 +27,33 @@ ...@@ -27,6 +27,33 @@
#include <asm/uv/uv_hub.h> #include <asm/uv/uv_hub.h>
#include <asm/uv/bios.h> #include <asm/uv/bios.h>
static enum uv_system_type uv_system_type;
static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
if (!strcmp(oem_id, "SGI")) {
if (!strcmp(oem_table_id, "UVL"))
uv_system_type = UV_LEGACY_APIC;
else if (!strcmp(oem_table_id, "UVX"))
uv_system_type = UV_X2APIC;
else if (!strcmp(oem_table_id, "UVH")) {
uv_system_type = UV_NON_UNIQUE_APIC;
return 1;
}
}
return 0;
}
enum uv_system_type get_uv_system_type(void)
{
return uv_system_type;
}
int is_uv_system(void)
{
return uv_system_type != UV_NONE;
}
DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);
...@@ -153,7 +180,7 @@ static unsigned int get_apic_id(unsigned long x) ...@@ -153,7 +180,7 @@ static unsigned int get_apic_id(unsigned long x)
return id; return id;
} }
static long set_apic_id(unsigned int id) static unsigned long set_apic_id(unsigned int id)
{ {
unsigned long x; unsigned long x;
...@@ -182,6 +209,7 @@ static void uv_send_IPI_self(int vector) ...@@ -182,6 +209,7 @@ static void uv_send_IPI_self(int vector)
struct genapic apic_x2apic_uv_x = { struct genapic apic_x2apic_uv_x = {
.name = "UV large system", .name = "UV large system",
.acpi_madt_oem_check = uv_acpi_madt_oem_check,
.int_delivery_mode = dest_Fixed, .int_delivery_mode = dest_Fixed,
.int_dest_mode = (APIC_DEST_PHYSICAL != 0), .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
.target_cpus = uv_target_cpus, .target_cpus = uv_target_cpus,
...@@ -433,3 +461,5 @@ void __cpuinit uv_cpu_init(void) ...@@ -433,3 +461,5 @@ void __cpuinit uv_cpu_init(void)
if (get_uv_system_type() == UV_NON_UNIQUE_APIC) if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
set_x2apic_extra_bits(uv_hub_info->pnode); set_x2apic_extra_bits(uv_hub_info->pnode);
} }
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
struct genapic { struct genapic {
char *name; char *name;
int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
u32 int_delivery_mode; u32 int_delivery_mode;
u32 int_dest_mode; u32 int_dest_mode;
int (*apic_id_registered)(void); int (*apic_id_registered)(void);
......
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