summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2004-07-14 07:39:55 -0400
committerLen Brown <lenb@dhcppc3.>2004-07-14 07:39:55 -0400
commit25bf3b3ea93d26d798595fe7b4e51c671d8fc0c6 (patch)
tree1c62a80fb3310109a500314fc94c5f87fd325a7e
parent52fb97fa0cca1e3e1881eb0620299070d17bd1b2 (diff)
[ACPI] add SMP suport to processor driver (Venkatesh Pallipadi)
http://bugzilla.kernel.org/show_bug.cgi?id=2615
-rw-r--r--arch/i386/kernel/acpi/boot.c7
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi.c30
-rw-r--r--arch/i386/kernel/smpboot.c6
-rw-r--r--arch/ia64/kernel/acpi.c6
-rw-r--r--arch/x86_64/kernel/smpboot.c1
-rw-r--r--drivers/acpi/processor.c65
-rw-r--r--include/asm-i386/acpi.h2
-rw-r--r--include/asm-i386/smp.h1
-rw-r--r--include/asm-ia64/acpi.h2
-rw-r--r--include/asm-x86_64/acpi.h2
10 files changed, 107 insertions, 15 deletions
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 99b1be964765..e179f4a906ae 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -83,6 +83,11 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
#warning ACPI uses CMPXCHG, i486 and later hardware
#endif
+#define MAX_MADT_ENTRIES 256
+u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] =
+ { [0 ... MAX_MADT_ENTRIES-1] = 0xff };
+EXPORT_SYMBOL(x86_acpiid_to_apicid);
+
/* --------------------------------------------------------------------------
Boot-time Configuration
-------------------------------------------------------------------------- */
@@ -224,6 +229,8 @@ acpi_parse_lapic (
if (processor->flags.enabled == 0)
return 0;
+ x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
+
mp_register_lapic (
processor->id, /* APIC ID */
processor->flags.enabled); /* Enabled? */
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c
index 8c056882df27..8c56687f071b 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi.c
@@ -108,13 +108,27 @@ acpi_processor_set_performance (
u32 value = 0;
int i = 0;
struct cpufreq_freqs cpufreq_freqs;
+ cpumask_t saved_mask;
+ int retval;
ACPI_FUNCTION_TRACE("acpi_processor_set_performance");
+ /*
+ * TBD: Use something other than set_cpus_allowed.
+ * As set_cpus_allowed is a bit racy,
+ * with any other set_cpus_allowed for this process.
+ */
+ saved_mask = current->cpus_allowed;
+ set_cpus_allowed(current, cpumask_of_cpu(cpu));
+ if (smp_processor_id() != cpu) {
+ return_VALUE(-EAGAIN);
+ }
+
if (state == data->acpi_data.state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Already at target state (P%d)\n", state));
- return_VALUE(0);
+ retval = 0;
+ goto migrate_end;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n",
@@ -144,7 +158,8 @@ acpi_processor_set_performance (
if (ret) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid port width 0x%04x\n", bit_width));
- return_VALUE(ret);
+ retval = ret;
+ goto migrate_end;
}
/*
@@ -166,7 +181,8 @@ acpi_processor_set_performance (
if (ret) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid port width 0x%04x\n", bit_width));
- return_VALUE(ret);
+ retval = ret;
+ goto migrate_end;
}
if (value == (u32) data->acpi_data.states[state].status)
break;
@@ -183,7 +199,8 @@ acpi_processor_set_performance (
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
- return_VALUE(-ENODEV);
+ retval = -ENODEV;
+ goto migrate_end;
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -192,7 +209,10 @@ acpi_processor_set_performance (
data->acpi_data.state = state;
- return_VALUE(0);
+ retval = 0;
+migrate_end:
+ set_cpus_allowed(current, saved_mask);
+ return_VALUE(retval);
}
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 45e8fbab361c..14406e35e79c 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -73,6 +73,10 @@ static cpumask_t smp_commenced_mask;
/* Per CPU bogomips and other parameters */
struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
+u8 x86_cpu_to_apicid[NR_CPUS] =
+ { [0 ... NR_CPUS-1] = 0xff };
+EXPORT_SYMBOL(x86_cpu_to_apicid);
+
/* Set when the idlers are all forked */
int smp_threads_ready;
@@ -871,6 +875,7 @@ static int __init do_boot_cpu(int apicid)
inquire_remote_apic(apicid);
}
}
+ x86_cpu_to_apicid[cpu] = apicid;
if (boot_error) {
/* Try to put things back the way they were before ... */
unmap_cpu_to_logical_apicid(cpu);
@@ -953,6 +958,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
boot_cpu_logical_apicid = logical_smp_processor_id();
+ x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
current_thread_info()->cpu = 0;
smp_tune_scheduling();
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 28264441b3fb..560e6945cd76 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -65,6 +65,11 @@ void (*pm_power_off) (void);
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)
{
@@ -205,6 +210,7 @@ acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end)
== (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;
}
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index ba2cba68da14..20193af1b013 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -62,6 +62,7 @@ cpumask_t cpu_online_map;
/* which logical CPU number maps to which CPU (physical APIC ID) */
volatile char x86_cpu_to_apicid[NR_CPUS];
+EXPORT_SYMBOL(x86_cpu_to_apicid);
static cpumask_t cpu_callin_map;
cpumask_t cpu_callout_map;
diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c
index 38e13a1a9098..627135287d71 100644
--- a/drivers/acpi/processor.c
+++ b/drivers/acpi/processor.c
@@ -44,6 +44,9 @@
#include <asm/system.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/smp.h>
+#include <asm/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -859,7 +862,6 @@ static void acpi_processor_ppc_exit(void) {
* _PCT and _PSS structures are read out and written into struct
* acpi_processor_performance.
*/
-
static int acpi_processor_set_pdc (struct acpi_processor *pr)
{
acpi_status status = AE_OK;
@@ -2146,6 +2148,37 @@ acpi_processor_remove_fs (
return_VALUE(0);
}
+/* Use the acpiid in MADT to map cpus in case of SMP */
+#ifndef CONFIG_SMP
+#define convert_acpiid_to_cpu(acpi_id) (0xff)
+#else
+
+#ifdef CONFIG_IA64
+#define arch_acpiid_to_apicid ia64_acpiid_to_sapicid
+#define arch_cpu_to_apicid ia64_cpu_to_sapicid
+#define ARCH_BAD_APICID (0xffff)
+#else
+#define arch_acpiid_to_apicid x86_acpiid_to_apicid
+#define arch_cpu_to_apicid x86_cpu_to_apicid
+#define ARCH_BAD_APICID (0xff)
+#endif
+
+static u8 convert_acpiid_to_cpu(u8 acpi_id)
+{
+ u16 apic_id;
+ int i;
+
+ apic_id = arch_acpiid_to_apicid[acpi_id];
+ if (apic_id == ARCH_BAD_APICID)
+ return -1;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (arch_cpu_to_apicid[i] == apic_id)
+ return i;
+ }
+ return -1;
+}
+#endif
/* --------------------------------------------------------------------------
Driver Interface
@@ -2158,7 +2191,8 @@ acpi_processor_get_info (
acpi_status status = 0;
union acpi_object object = {0};
struct acpi_buffer buffer = {sizeof(union acpi_object), &object};
- static int cpu_index = 0;
+ u8 cpu_index;
+ static int cpu0_initialized;
ACPI_FUNCTION_TRACE("acpi_processor_get_info");
@@ -2168,13 +2202,6 @@ acpi_processor_get_info (
if (num_online_cpus() > 1)
errata.smp = TRUE;
- /*
- * Extra Processor objects may be enumerated on MP systems with
- * less than the max # of CPUs. They should be ignored.
- */
- if ((cpu_index + 1) > num_online_cpus())
- return_VALUE(-ENODEV);
-
acpi_processor_errata(pr);
/*
@@ -2206,9 +2233,27 @@ acpi_processor_get_info (
* TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
* >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
*/
- pr->id = cpu_index++;
pr->acpi_id = object.processor.proc_id;
+ cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
+
+ if ( !cpu0_initialized && (cpu_index == 0xff)) {
+ /* Handle UP system running SMP kernel, with no LAPIC in MADT */
+ cpu_index = 0;
+ } else if (cpu_index > num_online_cpus()) {
+ /*
+ * Extra Processor objects may be enumerated on MP systems with
+ * less than the max # of CPUs. They should be ignored.
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error getting cpuindex for acpiid 0x%x\n",
+ pr->acpi_id));
+ return_VALUE(-ENODEV);
+ }
+ cpu0_initialized = 1;
+
+ pr->id = cpu_index;
+
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
pr->acpi_id));
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
index 42164a6d5fe0..ce1852636faa 100644
--- a/include/asm-i386/acpi.h
+++ b/include/asm-i386/acpi.h
@@ -178,6 +178,8 @@ extern void acpi_reserve_bootmem(void);
#endif /*CONFIG_ACPI_SLEEP*/
+extern u8 x86_acpiid_to_apicid[];
+
#endif /*__KERNEL__*/
#endif /*_ASM_ACPI_H*/
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 88c461e5e107..ba7eccc97f19 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -43,6 +43,7 @@ extern void (*mtrr_hook) (void);
extern void zap_low_mappings (void);
#define MAX_APICID 256
+extern u8 x86_cpu_to_apicid[];
/*
* This function is needed by all SMP systems. It must _always_ be valid
diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
index 3e13984cf871..1ebe9a591227 100644
--- a/include/asm-ia64/acpi.h
+++ b/include/asm-ia64/acpi.h
@@ -105,6 +105,8 @@ extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
#endif
+extern u16 ia64_acpiid_to_sapicid[];
+
#endif /*__KERNEL__*/
#endif /*_ASM_ACPI_H*/
diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h
index b768ed272d72..3ebe9be2aea9 100644
--- a/include/asm-x86_64/acpi.h
+++ b/include/asm-x86_64/acpi.h
@@ -163,6 +163,8 @@ extern int acpi_pci_disabled;
#define BROKEN_ACPI_Sx 0x0001
#define BROKEN_INIT_AFTER_S1 0x0002
+extern u8 x86_acpiid_to_apicid[];
+
#endif /*__KERNEL__*/
#endif /*_ASM_ACPI_H*/