vserver 1.9.5.x5
[linux-2.6.git] / arch / ia64 / kernel / acpi.c
index 10f2c7c..ca062b9 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/acpi.h>
 #include <linux/efi.h>
 #include <linux/mmzone.h>
+#include <linux/nodemask.h>
 #include <asm/io.h>
 #include <asm/iosapic.h>
 #include <asm/machvec.h>
 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)
 {
@@ -106,6 +113,8 @@ acpi_get_sysname (void)
        return "hpsim";
 # elif defined (CONFIG_IA64_HP_ZX1)
        return "hpzx1";
+# elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB)
+       return "hpzx1_swiotlb";
 # elif defined (CONFIG_IA64_SGI_SN2)
        return "sn2";
 # elif defined (CONFIG_IA64_DIG)
@@ -171,11 +180,9 @@ acpi_parse_lapic_addr_ovr (
        if (BAD_MADT_ENTRY(lapic, end))
                return -EINVAL;
 
-       acpi_table_print_madt_entry(header);
-
        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;
 }
@@ -191,25 +198,14 @@ acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end)
        if (BAD_MADT_ENTRY(lsapic, end))
                return -EINVAL;
 
-       acpi_table_print_madt_entry(header);
-
-       printk(KERN_INFO "CPU %d (0x%04x)", total_cpus, (lsapic->id << 8) | lsapic->eid);
-
-       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;
 }
@@ -225,8 +221,6 @@ acpi_parse_lapic_nmi (acpi_table_entry_header *header, const unsigned long end)
        if (BAD_MADT_ENTRY(lacpi_nmi, end))
                return -EINVAL;
 
-       acpi_table_print_madt_entry(header);
-
        /* TBD: Support lapic_nmi entries */
        return 0;
 }
@@ -242,8 +236,6 @@ acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end)
        if (BAD_MADT_ENTRY(iosapic, end))
                return -EINVAL;
 
-       acpi_table_print_madt_entry(header);
-
        iosapic_init(iosapic->address, iosapic->global_irq_base);
 
        return 0;
@@ -262,8 +254,6 @@ acpi_parse_plat_int_src (
        if (BAD_MADT_ENTRY(plintsrc, end))
                return -EINVAL;
 
-       acpi_table_print_madt_entry(header);
-
        /*
         * Get vector assignment for this interrupt, set attributes,
         * and program the IOSAPIC routing table.
@@ -292,8 +282,6 @@ acpi_parse_int_src_ovr (
        if (BAD_MADT_ENTRY(p, end))
                return -EINVAL;
 
-       acpi_table_print_madt_entry(header);
-
        iosapic_override_isa_irq(p->bus_irq, p->global_irq,
                                 (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
                                 (p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
@@ -311,26 +299,24 @@ acpi_parse_nmi_src (acpi_table_entry_header *header, const unsigned long end)
        if (BAD_MADT_ENTRY(nmi_src, end))
                return -EINVAL;
 
-       acpi_table_print_madt_entry(header);
-
        /* 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();
        }
 }
 
@@ -353,9 +339,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);
@@ -371,11 +357,11 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
 #define PXM_FLAG_LEN ((MAX_PXM_DOMAINS + 1)/32)
 
 static int __initdata srat_num_cpus;                   /* number of cpus */
-static u32 __initdata pxm_flag[PXM_FLAG_LEN];
+static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
 #define pxm_bit_set(bit)       (set_bit(bit,(void *)pxm_flag))
 #define pxm_bit_test(bit)      (test_bit(bit,(void *)pxm_flag))
 /* maps to convert between proximity domain and logical node ID */
-int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
+int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS];
 int __initdata nid_to_pxm_map[MAX_NUMNODES];
 static struct acpi_table_slit __initdata *slit_table;
 
@@ -454,22 +440,27 @@ 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;
        }
 
+       /*
+        * MCD - This can probably be dropped now.  No need for pxm ID to node ID
+        * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES.
+        */
        /* calculate total number of nodes in system from PXM bitmap */
-       numnodes = 0;           /* init total nodes in system */
-
        memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
        memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
+       nodes_clear(node_online_map);
        for (i = 0; i < MAX_PXM_DOMAINS; i++) {
                if (pxm_bit_test(i)) {
-                       pxm_to_nid_map[i] = numnodes;
-                       node_set_online(numnodes);
-                       nid_to_pxm_map[numnodes++] = i;
+                       int nid = num_online_nodes();
+                       pxm_to_nid_map[i] = nid;
+                       nid_to_pxm_map[nid] = i;
+                       node_set_online(nid);
                }
        }
 
@@ -478,7 +469,7 @@ acpi_numa_arch_fixup (void)
                node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid];
 
        /* assign memory bank numbers for each chunk on each node */
-       for (i = 0; i < numnodes; i++) {
+       for_each_online_node(i) {
                int bank;
 
                bank = 0;
@@ -491,7 +482,7 @@ acpi_numa_arch_fixup (void)
        for (i = 0; i < srat_num_cpus; i++)
                node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid];
 
-       printk(KERN_INFO "Number of logical nodes in system = %d\n", numnodes);
+       printk(KERN_INFO "Number of logical nodes in system = %d\n", num_online_nodes());
        printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks);
 
        if (!slit_table) return;
@@ -511,8 +502,8 @@ acpi_numa_arch_fixup (void)
 
 #ifdef SLIT_DEBUG
        printk("ACPI 2.0 SLIT locality table:\n");
-       for (i = 0; i < numnodes; i++) {
-               for (j = 0; j < numnodes; j++)
+       for_each_online_node(i) {
+               for_each_online_node(j)
                        printk("%03d ", node_distance(i,j));
                printk("\n");
        }
@@ -521,12 +512,26 @@ 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);
 
+#ifdef CONFIG_ACPI_DEALLOCATE_IRQ
+void
+acpi_unregister_gsi (u32 gsi)
+{
+       iosapic_unregister_intr(gsi);
+}
+EXPORT_SYMBOL(acpi_unregister_gsi);
+#endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
+
 static int __init
 acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
 {
@@ -548,7 +553,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;
 }
 
@@ -662,16 +667,175 @@ acpi_gsi_to_irq (u32 gsi, unsigned int *irq)
        return 0;
 }
 
+/*
+ *  ACPI based hotplug CPU support
+ */
+#ifdef CONFIG_ACPI_HOTPLUG_CPU
+static
 int
-acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
+acpi_map_cpu2node(acpi_handle handle, int cpu, long physid)
 {
-       if (has_8259 && gsi < 16)
-               return isa_irq_to_vector(gsi);
+#ifdef CONFIG_ACPI_NUMA
+       int                     pxm_id;
 
-       return iosapic_register_intr(gsi,
-                       (polarity == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
-                       (trigger == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
+       pxm_id = acpi_get_pxm(handle);
+
+       /*
+        * Assuming that the container driver would have set the proximity
+        * domain and would have initialized pxm_to_nid_map[pxm_id] && pxm_flag
+        */
+       node_cpuid[cpu].nid = (pxm_id < 0) ? 0:
+                       pxm_to_nid_map[pxm_id];
+
+       node_cpuid[cpu].phys_id =  physid;
+#endif
+       return(0);
+}
+
+
+int
+acpi_map_lsapic(acpi_handle handle, int *pcpu)
+{
+       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+       union acpi_object *obj;
+       struct acpi_table_lsapic *lsapic;
+       cpumask_t tmp_map;
+       long physid;
+       int cpu;
+       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+               return -EINVAL;
+
+       if (!buffer.length ||  !buffer.pointer)
+               return -EINVAL;
+       obj = buffer.pointer;
+       if (obj->type != ACPI_TYPE_BUFFER ||
+           obj->buffer.length < sizeof(*lsapic)) {
+               acpi_os_free(buffer.pointer);
+               return -EINVAL;
+       }
+
+       lsapic = (struct acpi_table_lsapic *)obj->buffer.pointer;
+
+       if ((lsapic->header.type != ACPI_MADT_LSAPIC) ||
+           (!lsapic->flags.enabled)) {
+               acpi_os_free(buffer.pointer);
+               return -EINVAL;
+       }
+
+       physid = ((lsapic->id <<8) | (lsapic->eid));
+
+       acpi_os_free(buffer.pointer);
+       buffer.length = ACPI_ALLOCATE_BUFFER;
+       buffer.pointer = NULL;
+
+       cpus_complement(tmp_map, cpu_present_map);
+       cpu = first_cpu(tmp_map);
+       if(cpu >= NR_CPUS)
+               return -EINVAL;
+
+       acpi_map_cpu2node(handle, cpu, physid);
+
+       cpu_set(cpu, cpu_present_map);
+       ia64_cpu_to_sapicid[cpu] = physid;
+       ia64_acpiid_to_sapicid[lsapic->acpi_id] = ia64_cpu_to_sapicid[cpu];
+
+       *pcpu = cpu;
+       return(0);
 }
-EXPORT_SYMBOL(acpi_register_irq);
+EXPORT_SYMBOL(acpi_map_lsapic);
 
+
+int
+acpi_unmap_lsapic(int cpu)
+{
+       int i;
+
+       for (i=0; i<MAX_SAPICS; i++) {
+               if (ia64_acpiid_to_sapicid[i] == ia64_cpu_to_sapicid[cpu]) {
+                       ia64_acpiid_to_sapicid[i] = -1;
+                       break;
+               }
+       }
+       ia64_cpu_to_sapicid[cpu] = -1;
+       cpu_clear(cpu,cpu_present_map);
+
+#ifdef CONFIG_ACPI_NUMA
+       /* NUMA specific cleanup's */
+#endif
+
+       return(0);
+}
+EXPORT_SYMBOL(acpi_unmap_lsapic);
+#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+
+#ifdef CONFIG_NUMA
+acpi_status __init
+acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
+{
+       struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+       union acpi_object *obj;
+       struct acpi_table_iosapic *iosapic;
+       unsigned int gsi_base;
+       int node;
+
+       /* 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 */