Skip to content

Commit

Permalink
x86: add apic probe for genapic 64bit, v2
Browse files Browse the repository at this point in the history
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: Yinghai Lu <yhlu.kernel@gmail.com>
Cc: Jack Steiner <steiner@sgi.com>
Cc: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Yinghai Lu authored and Ingo Molnar committed Jul 22, 2008
1 parent 76c3bb1 commit 1b9b89e
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 60 deletions.
85 changes: 26 additions & 59 deletions arch/x86/kernel/genapic_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,62 +16,37 @@
#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/hardirq.h>
#include <linux/dmar.h>

#include <asm/smp.h>
#include <asm/ipi.h>
#include <asm/genapic.h>

#ifdef CONFIG_ACPI
#include <acpi/acpi_bus.h>
#endif

DEFINE_PER_CPU(int, x2apic_extra_bits);
extern struct genapic apic_flat;
extern struct genapic apic_physflat;
extern struct genapic apic_x2xpic_uv_x;
extern struct genapic apic_x2apic_phys;
extern struct genapic apic_x2apic_cluster;

struct genapic __read_mostly *genapic = &apic_flat;

static int x2apic_phys = 0;

static int set_x2apic_phys_mode(char *arg)
{
x2apic_phys = 1;
return 0;
}
early_param("x2apic_phys", set_x2apic_phys_mode);

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

/*
* Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
*/
void __init setup_apic_routing(void)
{
if (uv_system_type == UV_NON_UNIQUE_APIC)
genapic = &apic_x2apic_uv_x;
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;
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);
if (genapic == &apic_flat) {
if (max_physical_apicid >= 8)
genapic = &apic_physflat;
printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
}
}

/* Same for both flat and physical. */
Expand All @@ -83,23 +58,15 @@ void apic_send_IPI_self(int vector)

int __init 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;
int i;

for (i = 0; apic_probe[i]; ++i) {
if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
genapic = apic_probe[i];
printk(KERN_INFO "Setting APIC routing to %s.\n",
genapic->name);
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;
}
26 changes: 26 additions & 0 deletions arch/x86/kernel/genapic_flat_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@
#include <asm/genapic.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)
{
return cpu_online_map;
Expand Down Expand Up @@ -138,6 +147,7 @@ static unsigned int phys_pkg_id(int index_msb)

struct genapic apic_flat = {
.name = "flat",
.acpi_madt_oem_check = flat_acpi_madt_oem_check,
.int_delivery_mode = dest_LowestPrio,
.int_dest_mode = (APIC_DEST_LOGICAL != 0),
.target_cpus = flat_target_cpus,
Expand All @@ -160,6 +170,21 @@ struct genapic apic_flat = {
* We cannot use logical delivery in this case because the mask
* 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)
{
Expand Down Expand Up @@ -206,6 +231,7 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)

struct genapic apic_physflat = {
.name = "physical flat",
.acpi_madt_oem_check = physflat_acpi_madt_oem_check,
.int_delivery_mode = dest_Fixed,
.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
.target_cpus = physflat_target_cpus,
Expand Down
11 changes: 11 additions & 0 deletions arch/x86/kernel/genx2apic_cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/dmar.h>

#include <asm/smp.h>
#include <asm/ipi.h>
#include <asm/genapic.h>

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. */

static cpumask_t x2apic_target_cpus(void)
Expand Down Expand Up @@ -135,6 +145,7 @@ static void init_x2apic_ldr(void)

struct genapic apic_x2apic_cluster = {
.name = "cluster x2apic",
.acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
.int_delivery_mode = dest_LowestPrio,
.int_dest_mode = (APIC_DEST_LOGICAL != 0),
.target_cpus = x2apic_target_cpus,
Expand Down
21 changes: 21 additions & 0 deletions arch/x86/kernel/genx2apic_phys.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,30 @@
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/dmar.h>

#include <asm/smp.h>
#include <asm/ipi.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. */

Expand Down Expand Up @@ -122,6 +142,7 @@ void init_x2apic_ldr(void)

struct genapic apic_x2apic_phys = {
.name = "physical x2apic",
.acpi_madt_oem_check = x2apic_acpi_madt_oem_check,
.int_delivery_mode = dest_Fixed,
.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
.target_cpus = x2apic_target_cpus,
Expand Down
32 changes: 31 additions & 1 deletion arch/x86/kernel/genx2apic_uv_x.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,33 @@
#include <asm/uv/uv_hub.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);
EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);

Expand Down Expand Up @@ -153,7 +180,7 @@ static unsigned int get_apic_id(unsigned long x)
return id;
}

static long set_apic_id(unsigned int id)
static unsigned long set_apic_id(unsigned int id)
{
unsigned long x;

Expand Down Expand Up @@ -182,6 +209,7 @@ static void uv_send_IPI_self(int vector)

struct genapic apic_x2apic_uv_x = {
.name = "UV large system",
.acpi_madt_oem_check = uv_acpi_madt_oem_check,
.int_delivery_mode = dest_Fixed,
.int_dest_mode = (APIC_DEST_PHYSICAL != 0),
.target_cpus = uv_target_cpus,
Expand Down Expand Up @@ -433,3 +461,5 @@ void __cpuinit uv_cpu_init(void)
if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
set_x2apic_extra_bits(uv_hub_info->pnode);
}


1 change: 1 addition & 0 deletions include/asm-x86/genapic_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

struct genapic {
char *name;
int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
u32 int_delivery_mode;
u32 int_dest_mode;
int (*apic_id_registered)(void);
Expand Down

0 comments on commit 1b9b89e

Please sign in to comment.