Commit 25bf3b3e authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] add SMP suport to processor driver (Venkatesh Pallipadi)

http://bugzilla.kernel.org/show_bug.cgi?id=2615
parent 52fb97fa
...@@ -83,6 +83,11 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; ...@@ -83,6 +83,11 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
#warning ACPI uses CMPXCHG, i486 and later hardware #warning ACPI uses CMPXCHG, i486 and later hardware
#endif #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 Boot-time Configuration
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
...@@ -224,6 +229,8 @@ acpi_parse_lapic ( ...@@ -224,6 +229,8 @@ acpi_parse_lapic (
if (processor->flags.enabled == 0) if (processor->flags.enabled == 0)
return 0; return 0;
x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
mp_register_lapic ( mp_register_lapic (
processor->id, /* APIC ID */ processor->id, /* APIC ID */
processor->flags.enabled); /* Enabled? */ processor->flags.enabled); /* Enabled? */
......
...@@ -108,13 +108,27 @@ acpi_processor_set_performance ( ...@@ -108,13 +108,27 @@ acpi_processor_set_performance (
u32 value = 0; u32 value = 0;
int i = 0; int i = 0;
struct cpufreq_freqs cpufreq_freqs; struct cpufreq_freqs cpufreq_freqs;
cpumask_t saved_mask;
int retval;
ACPI_FUNCTION_TRACE("acpi_processor_set_performance"); 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) { if (state == data->acpi_data.state) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Already at target state (P%d)\n", state)); "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", ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n",
...@@ -144,7 +158,8 @@ acpi_processor_set_performance ( ...@@ -144,7 +158,8 @@ acpi_processor_set_performance (
if (ret) { if (ret) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid port width 0x%04x\n", bit_width)); "Invalid port width 0x%04x\n", bit_width));
return_VALUE(ret); retval = ret;
goto migrate_end;
} }
/* /*
...@@ -166,7 +181,8 @@ acpi_processor_set_performance ( ...@@ -166,7 +181,8 @@ acpi_processor_set_performance (
if (ret) { if (ret) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, ACPI_DEBUG_PRINT((ACPI_DB_WARN,
"Invalid port width 0x%04x\n", bit_width)); "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) if (value == (u32) data->acpi_data.states[state].status)
break; break;
...@@ -183,7 +199,8 @@ acpi_processor_set_performance ( ...@@ -183,7 +199,8 @@ acpi_processor_set_performance (
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n")); ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
return_VALUE(-ENODEV); retval = -ENODEV;
goto migrate_end;
} }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
...@@ -192,7 +209,10 @@ acpi_processor_set_performance ( ...@@ -192,7 +209,10 @@ acpi_processor_set_performance (
data->acpi_data.state = state; data->acpi_data.state = state;
return_VALUE(0); retval = 0;
migrate_end:
set_cpus_allowed(current, saved_mask);
return_VALUE(retval);
} }
......
...@@ -73,6 +73,10 @@ static cpumask_t smp_commenced_mask; ...@@ -73,6 +73,10 @@ static cpumask_t smp_commenced_mask;
/* Per CPU bogomips and other parameters */ /* Per CPU bogomips and other parameters */
struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; 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 */ /* Set when the idlers are all forked */
int smp_threads_ready; int smp_threads_ready;
...@@ -871,6 +875,7 @@ static int __init do_boot_cpu(int apicid) ...@@ -871,6 +875,7 @@ static int __init do_boot_cpu(int apicid)
inquire_remote_apic(apicid); inquire_remote_apic(apicid);
} }
} }
x86_cpu_to_apicid[cpu] = apicid;
if (boot_error) { if (boot_error) {
/* Try to put things back the way they were before ... */ /* Try to put things back the way they were before ... */
unmap_cpu_to_logical_apicid(cpu); unmap_cpu_to_logical_apicid(cpu);
...@@ -953,6 +958,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) ...@@ -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_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
boot_cpu_logical_apicid = logical_smp_processor_id(); boot_cpu_logical_apicid = logical_smp_processor_id();
x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
current_thread_info()->cpu = 0; current_thread_info()->cpu = 0;
smp_tune_scheduling(); smp_tune_scheduling();
......
...@@ -65,6 +65,11 @@ void (*pm_power_off) (void); ...@@ -65,6 +65,11 @@ void (*pm_power_off) (void);
unsigned char acpi_kbd_controller_present = 1; unsigned char acpi_kbd_controller_present = 1;
unsigned char acpi_legacy_devices; 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 * const char *
acpi_get_sysname (void) acpi_get_sysname (void)
{ {
...@@ -205,6 +210,7 @@ acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end) ...@@ -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]) == (unsigned int) smp_boot_data.cpu_phys_id[available_cpus])
printk(" (BSP)"); printk(" (BSP)");
#endif #endif
ia64_acpiid_to_sapicid[lsapic->acpi_id] = (lsapic->id << 8) | lsapic->eid;
++available_cpus; ++available_cpus;
} }
......
...@@ -62,6 +62,7 @@ cpumask_t cpu_online_map; ...@@ -62,6 +62,7 @@ cpumask_t cpu_online_map;
/* which logical CPU number maps to which CPU (physical APIC ID) */ /* which logical CPU number maps to which CPU (physical APIC ID) */
volatile char x86_cpu_to_apicid[NR_CPUS]; volatile char x86_cpu_to_apicid[NR_CPUS];
EXPORT_SYMBOL(x86_cpu_to_apicid);
static cpumask_t cpu_callin_map; static cpumask_t cpu_callin_map;
cpumask_t cpu_callout_map; cpumask_t cpu_callout_map;
......
...@@ -44,6 +44,9 @@ ...@@ -44,6 +44,9 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/uaccess.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_bus.h>
#include <acpi/acpi_drivers.h> #include <acpi/acpi_drivers.h>
...@@ -859,7 +862,6 @@ static void acpi_processor_ppc_exit(void) { ...@@ -859,7 +862,6 @@ static void acpi_processor_ppc_exit(void) {
* _PCT and _PSS structures are read out and written into struct * _PCT and _PSS structures are read out and written into struct
* acpi_processor_performance. * acpi_processor_performance.
*/ */
static int acpi_processor_set_pdc (struct acpi_processor *pr) static int acpi_processor_set_pdc (struct acpi_processor *pr)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
...@@ -2146,6 +2148,37 @@ acpi_processor_remove_fs ( ...@@ -2146,6 +2148,37 @@ acpi_processor_remove_fs (
return_VALUE(0); 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 Driver Interface
...@@ -2158,7 +2191,8 @@ acpi_processor_get_info ( ...@@ -2158,7 +2191,8 @@ acpi_processor_get_info (
acpi_status status = 0; acpi_status status = 0;
union acpi_object object = {0}; union acpi_object object = {0};
struct acpi_buffer buffer = {sizeof(union acpi_object), &object}; 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"); ACPI_FUNCTION_TRACE("acpi_processor_get_info");
...@@ -2168,13 +2202,6 @@ acpi_processor_get_info ( ...@@ -2168,13 +2202,6 @@ acpi_processor_get_info (
if (num_online_cpus() > 1) if (num_online_cpus() > 1)
errata.smp = TRUE; 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); acpi_processor_errata(pr);
/* /*
...@@ -2206,9 +2233,27 @@ acpi_processor_get_info ( ...@@ -2206,9 +2233,27 @@ acpi_processor_get_info (
* TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
* >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
*/ */
pr->id = cpu_index++;
pr->acpi_id = object.processor.proc_id; 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, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id,
pr->acpi_id)); pr->acpi_id));
......
...@@ -178,6 +178,8 @@ extern void acpi_reserve_bootmem(void); ...@@ -178,6 +178,8 @@ extern void acpi_reserve_bootmem(void);
#endif /*CONFIG_ACPI_SLEEP*/ #endif /*CONFIG_ACPI_SLEEP*/
extern u8 x86_acpiid_to_apicid[];
#endif /*__KERNEL__*/ #endif /*__KERNEL__*/
#endif /*_ASM_ACPI_H*/ #endif /*_ASM_ACPI_H*/
...@@ -43,6 +43,7 @@ extern void (*mtrr_hook) (void); ...@@ -43,6 +43,7 @@ extern void (*mtrr_hook) (void);
extern void zap_low_mappings (void); extern void zap_low_mappings (void);
#define MAX_APICID 256 #define MAX_APICID 256
extern u8 x86_cpu_to_apicid[];
/* /*
* This function is needed by all SMP systems. It must _always_ be valid * This function is needed by all SMP systems. It must _always_ be valid
......
...@@ -105,6 +105,8 @@ extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS]; ...@@ -105,6 +105,8 @@ extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
#endif #endif
extern u16 ia64_acpiid_to_sapicid[];
#endif /*__KERNEL__*/ #endif /*__KERNEL__*/
#endif /*_ASM_ACPI_H*/ #endif /*_ASM_ACPI_H*/
...@@ -163,6 +163,8 @@ extern int acpi_pci_disabled; ...@@ -163,6 +163,8 @@ extern int acpi_pci_disabled;
#define BROKEN_ACPI_Sx 0x0001 #define BROKEN_ACPI_Sx 0x0001
#define BROKEN_INIT_AFTER_S1 0x0002 #define BROKEN_INIT_AFTER_S1 0x0002
extern u8 x86_acpiid_to_apicid[];
#endif /*__KERNEL__*/ #endif /*__KERNEL__*/
#endif /*_ASM_ACPI_H*/ #endif /*_ASM_ACPI_H*/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment