X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fia64%2Fkernel%2Facpi.c;h=6e012ba5587984dbb9202570f28179494b3bbe41;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=28d4fdcb29de7010981e5d2931f930d6a8386d56;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 28d4fdcb2..6e012ba55 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -52,16 +52,25 @@ #include #include +#define BAD_MADT_ENTRY(entry, end) ( \ + (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ + ((acpi_table_entry_header *)entry)->length != sizeof(*entry)) #define PREFIX "ACPI: " void (*pm_idle) (void); EXPORT_SYMBOL(pm_idle); void (*pm_power_off) (void); +EXPORT_SYMBOL(pm_power_off); unsigned char acpi_kbd_controller_present = 1; unsigned char acpi_legacy_devices; +#define MAX_SAPICS 256 +u16 ia64_acpiid_to_sapicid[MAX_SAPICS] = + { [0 ... MAX_SAPICS - 1] = -1 }; +EXPORT_SYMBOL(ia64_acpiid_to_sapicid); + const char * acpi_get_sysname (void) { @@ -158,67 +167,56 @@ static u8 has_8259; static int __init -acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header) +acpi_parse_lapic_addr_ovr ( + acpi_table_entry_header *header, const unsigned long end) { struct acpi_table_lapic_addr_ovr *lapic; lapic = (struct acpi_table_lapic_addr_ovr *) header; - if (!lapic) - return -EINVAL; - acpi_table_print_madt_entry(header); + if (BAD_MADT_ENTRY(lapic, end)) + return -EINVAL; if (lapic->address) { - iounmap((void *) ipi_base_addr); - ipi_base_addr = (unsigned long) ioremap(lapic->address, 0); + iounmap(ipi_base_addr); + ipi_base_addr = ioremap(lapic->address, 0); } return 0; } static int __init -acpi_parse_lsapic (acpi_table_entry_header *header) +acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end) { struct acpi_table_lsapic *lsapic; lsapic = (struct acpi_table_lsapic *) header; - if (!lsapic) - return -EINVAL; - acpi_table_print_madt_entry(header); - - printk(KERN_INFO "CPU %d (0x%04x)", total_cpus, (lsapic->id << 8) | lsapic->eid); + if (BAD_MADT_ENTRY(lsapic, end)) + return -EINVAL; - if (!lsapic->flags.enabled) - printk(" disabled"); - else { - printk(" enabled"); + if (lsapic->flags.enabled) { #ifdef CONFIG_SMP smp_boot_data.cpu_phys_id[available_cpus] = (lsapic->id << 8) | lsapic->eid; - if (hard_smp_processor_id() - == (unsigned int) smp_boot_data.cpu_phys_id[available_cpus]) - printk(" (BSP)"); #endif + ia64_acpiid_to_sapicid[lsapic->acpi_id] = (lsapic->id << 8) | lsapic->eid; ++available_cpus; } - printk("\n"); - total_cpus++; return 0; } static int __init -acpi_parse_lapic_nmi (acpi_table_entry_header *header) +acpi_parse_lapic_nmi (acpi_table_entry_header *header, const unsigned long end) { struct acpi_table_lapic_nmi *lacpi_nmi; lacpi_nmi = (struct acpi_table_lapic_nmi*) header; - if (!lacpi_nmi) - return -EINVAL; - acpi_table_print_madt_entry(header); + if (BAD_MADT_ENTRY(lacpi_nmi, end)) + return -EINVAL; /* TBD: Support lapic_nmi entries */ return 0; @@ -226,15 +224,14 @@ acpi_parse_lapic_nmi (acpi_table_entry_header *header) static int __init -acpi_parse_iosapic (acpi_table_entry_header *header) +acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end) { struct acpi_table_iosapic *iosapic; iosapic = (struct acpi_table_iosapic *) header; - if (!iosapic) - return -EINVAL; - acpi_table_print_madt_entry(header); + if (BAD_MADT_ENTRY(iosapic, end)) + return -EINVAL; iosapic_init(iosapic->address, iosapic->global_irq_base); @@ -243,16 +240,16 @@ acpi_parse_iosapic (acpi_table_entry_header *header) static int __init -acpi_parse_plat_int_src (acpi_table_entry_header *header) +acpi_parse_plat_int_src ( + acpi_table_entry_header *header, const unsigned long end) { struct acpi_table_plat_int_src *plintsrc; int vector; plintsrc = (struct acpi_table_plat_int_src *) header; - if (!plintsrc) - return -EINVAL; - acpi_table_print_madt_entry(header); + if (BAD_MADT_ENTRY(plintsrc, end)) + return -EINVAL; /* * Get vector assignment for this interrupt, set attributes, @@ -272,15 +269,15 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header) static int __init -acpi_parse_int_src_ovr (acpi_table_entry_header *header) +acpi_parse_int_src_ovr ( + acpi_table_entry_header *header, const unsigned long end) { struct acpi_table_int_src_ovr *p; p = (struct acpi_table_int_src_ovr *) header; - if (!p) - return -EINVAL; - acpi_table_print_madt_entry(header); + if (BAD_MADT_ENTRY(p, end)) + return -EINVAL; iosapic_override_isa_irq(p->bus_irq, p->global_irq, (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, @@ -290,34 +287,33 @@ acpi_parse_int_src_ovr (acpi_table_entry_header *header) static int __init -acpi_parse_nmi_src (acpi_table_entry_header *header) +acpi_parse_nmi_src (acpi_table_entry_header *header, const unsigned long end) { struct acpi_table_nmi_src *nmi_src; nmi_src = (struct acpi_table_nmi_src*) header; - if (!nmi_src) - return -EINVAL; - acpi_table_print_madt_entry(header); + if (BAD_MADT_ENTRY(nmi_src, end)) + return -EINVAL; /* TBD: Support nimsrc entries */ return 0; } -/* Hook from generic ACPI tables.c */ -void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static void __init +acpi_madt_oem_check (char *oem_id, char *oem_table_id) { if (!strncmp(oem_id, "IBM", 3) && - (!strncmp(oem_table_id, "SERMOW", 6))){ + (!strncmp(oem_table_id, "SERMOW", 6))) { - /* Unfortunatly ITC_DRIFT is not yet part of the + /* + * Unfortunately ITC_DRIFT is not yet part of the * official SAL spec, so the ITC_DRIFT bit is not * set by the BIOS on this hardware. */ sal_platform_features |= IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT; - /*Start cyclone clock*/ - cyclone_setup(0); + cyclone_setup(); } } @@ -340,9 +336,9 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size) /* Get base address of IPI Message Block */ if (acpi_madt->lapic_address) - ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0); + ipi_base_addr = ioremap(acpi_madt->lapic_address, 0); - printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr); + printk(KERN_INFO PREFIX "Local APIC address %p\n", ipi_base_addr); acpi_madt_oem_check(acpi_madt->header.oem_id, acpi_madt->header.oem_table_id); @@ -441,8 +437,9 @@ acpi_numa_arch_fixup (void) { int i, j, node_from, node_to; - /* If there's no SRAT, fix the phys_id */ + /* If there's no SRAT, fix the phys_id and mark node 0 online */ if (srat_num_cpus == 0) { + node_set_online(0); node_cpuid[0].phys_id = hard_smp_processor_id(); return; } @@ -508,9 +505,14 @@ acpi_numa_arch_fixup (void) #endif /* CONFIG_ACPI_NUMA */ unsigned int -acpi_register_gsi (u32 gsi, int polarity, int trigger) +acpi_register_gsi (u32 gsi, int edge_level, int active_high_low) { - return acpi_register_irq(gsi, polarity, trigger); + if (has_8259 && gsi < 16) + return isa_irq_to_vector(gsi); + + return iosapic_register_intr(gsi, + (active_high_low == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (edge_level == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); } EXPORT_SYMBOL(acpi_register_gsi); @@ -535,7 +537,7 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size) if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES) acpi_legacy_devices = 1; - acpi_register_gsi(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE); + acpi_register_gsi(fadt->sci_int, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); return 0; } @@ -632,16 +634,6 @@ acpi_boot_init (void) return 0; } -/* deprecated in favor of acpi_gsi_to_irq */ -int -acpi_irq_to_vector (u32 gsi) -{ - if (has_8259 && gsi < 16) - return isa_irq_to_vector(gsi); - - return gsi_to_vector(gsi); -} - int acpi_gsi_to_irq (u32 gsi, unsigned int *irq) { @@ -659,16 +651,71 @@ acpi_gsi_to_irq (u32 gsi, unsigned int *irq) return 0; } -int -acpi_register_irq (u32 gsi, u32 polarity, u32 trigger) +#ifdef CONFIG_NUMA +acpi_status __init +acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret) { - if (has_8259 && gsi < 16) - return isa_irq_to_vector(gsi); + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *obj; + struct acpi_table_iosapic *iosapic; + unsigned int gsi_base; + int node; - return iosapic_register_intr(gsi, - (polarity == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, - (trigger == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); -} -EXPORT_SYMBOL(acpi_register_irq); + /* Only care about objects w/ a method that returns the MADT */ + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) + return AE_OK; + + if (!buffer.length || !buffer.pointer) + return AE_OK; + + obj = buffer.pointer; + if (obj->type != ACPI_TYPE_BUFFER || + obj->buffer.length < sizeof(*iosapic)) { + acpi_os_free(buffer.pointer); + return AE_OK; + } + + iosapic = (struct acpi_table_iosapic *)obj->buffer.pointer; + + if (iosapic->header.type != ACPI_MADT_IOSAPIC) { + acpi_os_free(buffer.pointer); + return AE_OK; + } + + gsi_base = iosapic->global_irq_base; + + acpi_os_free(buffer.pointer); + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + + /* + * OK, it's an IOSAPIC MADT entry, look for a _PXM method to tell + * us which node to associate this with. + */ + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer))) + return AE_OK; + + if (!buffer.length || !buffer.pointer) + return AE_OK; + obj = buffer.pointer; + + if (obj->type != ACPI_TYPE_INTEGER || + obj->integer.value >= MAX_PXM_DOMAINS) { + acpi_os_free(buffer.pointer); + return AE_OK; + } + + node = pxm_to_nid_map[obj->integer.value]; + acpi_os_free(buffer.pointer); + + if (node >= MAX_NUMNODES || !node_online(node) || + cpus_empty(node_to_cpumask(node))) + return AE_OK; + + /* We know a gsi to node mapping! */ + map_iosapic_to_node(gsi_base, node); + return AE_OK; +} +#endif /* CONFIG_NUMA */ #endif /* CONFIG_ACPI_BOOT */