diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 72dfd9e7de0ffc470e3922fab11927b8e3fd0916..1c118b72df3c5a3ed02f05ad2f5596240850a613 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -11,6 +11,7 @@ * Copyright (C) 2001 Jenna Hall * Copyright (C) 2001 Takayoshi Kochi * Copyright (C) 2002 Erich Focht + * Copyright (C) 2004 Ashok Raj * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -67,6 +68,11 @@ EXPORT_SYMBOL(pm_power_off); unsigned char acpi_kbd_controller_present = 1; unsigned char acpi_legacy_devices; +static unsigned int __initdata acpi_madt_rev; + +unsigned int acpi_cpei_override; +unsigned int acpi_cpei_phys_cpuid; + #define MAX_SAPICS 256 u16 ia64_acpiid_to_sapicid[MAX_SAPICS] = { [0 ... MAX_SAPICS - 1] = -1 }; @@ -267,10 +273,56 @@ acpi_parse_plat_int_src ( (plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); platform_intr_list[plintsrc->type] = vector; + if (acpi_madt_rev > 1) { + acpi_cpei_override = plintsrc->plint_flags.cpei_override_flag; + } + + /* + * Save the physical id, so we can check when its being removed + */ + acpi_cpei_phys_cpuid = ((plintsrc->id << 8) | (plintsrc->eid)) & 0xffff; + return 0; } +unsigned int can_cpei_retarget(void) +{ + extern int cpe_vector; + + /* + * Only if CPEI is supported and the override flag + * is present, otherwise return that its re-targettable + * if we are in polling mode. + */ + if (cpe_vector > 0 && !acpi_cpei_override) + return 0; + else + return 1; +} + +unsigned int is_cpu_cpei_target(unsigned int cpu) +{ + unsigned int logical_id; + + logical_id = cpu_logical_id(acpi_cpei_phys_cpuid); + + if (logical_id == cpu) + return 1; + else + return 0; +} + +void set_cpei_target_cpu(unsigned int cpu) +{ + acpi_cpei_phys_cpuid = cpu_physical_id(cpu); +} + +unsigned int get_cpei_target_cpu(void) +{ + return acpi_cpei_phys_cpuid; +} + static int __init acpi_parse_int_src_ovr ( acpi_table_entry_header *header, const unsigned long end) @@ -328,6 +380,8 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size) acpi_madt = (struct acpi_table_madt *) __va(phys_addr); + acpi_madt_rev = acpi_madt->header.revision; + /* remember the value for reference after free_initmem() */ #ifdef CONFIG_ITANIUM has_8259 = 1; /* Firmware on old Itanium systems is broken */ diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 736e328b5e612865d1173d84ff054dc21bbbfde9..4ebbf3974381af2b7669c98c198d670c8e460fa7 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -271,7 +271,7 @@ ia64_mca_log_sal_error_record(int sal_info_type) #ifdef CONFIG_ACPI -static int cpe_vector = -1; +int cpe_vector = -1; static irqreturn_t ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index f1aafd4c05f91eb4d451e73dcd54e49f2a35c9a5..d8030f3bd8658810d9a81eda25933e46a2ff31a4 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -36,6 +36,13 @@ int arch_register_cpu(int num) parent = &sysfs_nodes[cpu_to_node(num)]; #endif /* CONFIG_NUMA */ + /* + * If CPEI cannot be re-targetted, and this is + * CPEI target, then dont create the control file + */ + if (!can_cpei_retarget() && is_cpu_cpei_target(num)) + sysfs_cpus[num].cpu.no_control = 1; + return register_cpu(&sysfs_cpus[num].cpu, num, parent); } diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h index 6a26a977f253fea03a2d6a42738243166636e7bf..4c06d455139c776f0cc2f78838dfcbeb2e24d48c 100644 --- a/include/asm-ia64/acpi.h +++ b/include/asm-ia64/acpi.h @@ -98,6 +98,15 @@ const char *acpi_get_sysname (void); int acpi_request_vector (u32 int_type); int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); +/* + * Record the cpei override flag and current logical cpu. This is + * useful for CPU removal. + */ +extern unsigned int can_cpei_retarget(void); +extern unsigned int is_cpu_cpei_target(unsigned int cpu); +extern void set_cpei_target_cpu(unsigned int cpu); +extern unsigned int get_cpei_target_cpu(void); + #ifdef CONFIG_ACPI_NUMA /* Proximity bitmap length; _PXM is at most 255 (8 bit)*/ #define MAX_PXM_DOMAINS (256) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index b123cc08773d30fccf89c1d0a0aa4e79fcaa2512..70b3c52b75d794ecd64db4dfe4280b89e3a8921a 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -206,7 +206,10 @@ struct acpi_table_plat_int_src { u8 eid; u8 iosapic_vector; u32 global_irq; - u32 reserved; + struct { + u32 cpei_override_flag:1; + u32 reserved:31; + } plint_flags; } __attribute__ ((packed)); enum acpi_interrupt_id {