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;
#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? */
......
......@@ -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);
}
......
......@@ -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();
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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));
......
......@@ -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*/
......@@ -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
......
......@@ -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*/
......@@ -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*/
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