Commit f642d8b5 authored by Len Brown's avatar Len Brown

Merge

parents 2bba62b2 a10214ef
......@@ -84,6 +84,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
-------------------------------------------------------------------------- */
......@@ -225,6 +230,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);
}
......@@ -266,6 +286,69 @@ acpi_cpufreq_guess_freq (
}
/*
* acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities
* of this driver
* @perf: processor-specific acpi_io_data struct
* @cpu: CPU being initialized
*
* To avoid issues with legacy OSes, some BIOSes require to be informed of
* the SMP capabilities of OS P-state driver. Here we set the bits in _PDC
* accordingly, for Enhanced Speedstep. Actual call to _PDC is done in
* driver/acpi/processor.c
*/
static void
acpi_processor_cpu_init_pdc_est(
struct acpi_processor_performance *perf,
unsigned int cpu,
struct acpi_object_list *obj_list
)
{
union acpi_object *obj;
u32 *buf;
struct cpuinfo_x86 *c = cpu_data + cpu;
ACPI_FUNCTION_TRACE("acpi_processor_cpu_init_pdc_est");
if (!cpu_has(c, X86_FEATURE_EST))
return_VOID;
/* Initialize pdc. It will be used later. */
if (!obj_list)
return_VOID;
if (!(obj_list->count && obj_list->pointer))
return_VOID;
obj = obj_list->pointer;
if ((obj->buffer.length == 12) && obj->buffer.pointer) {
buf = (u32 *)obj->buffer.pointer;
buf[0] = ACPI_PDC_REVISION_ID;
buf[1] = 1;
buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
perf->pdc = obj_list;
}
return_VOID;
}
/* CPU specific PDC initialization */
static void
acpi_processor_cpu_init_pdc(
struct acpi_processor_performance *perf,
unsigned int cpu,
struct acpi_object_list *obj_list
)
{
struct cpuinfo_x86 *c = cpu_data + cpu;
ACPI_FUNCTION_TRACE("acpi_processor_cpu_init_pdc");
perf->pdc = NULL;
if (cpu_has(c, X86_FEATURE_EST))
acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list);
return_VOID;
}
static int
acpi_cpufreq_cpu_init (
struct cpufreq_policy *policy)
......@@ -275,7 +358,14 @@ acpi_cpufreq_cpu_init (
struct cpufreq_acpi_io *data;
unsigned int result = 0;
union acpi_object arg0 = {ACPI_TYPE_BUFFER};
u32 arg0_buf[3];
struct acpi_object_list arg_list = {1, &arg0};
ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init");
/* setup arg_list for _PDC settings */
arg0.buffer.length = 12;
arg0.buffer.pointer = (u8 *) arg0_buf;
data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
if (!data)
......@@ -284,7 +374,10 @@ acpi_cpufreq_cpu_init (
acpi_io_data[cpu] = data;
acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list);
result = acpi_processor_register_performance(&data->acpi_data, cpu);
data->acpi_data.pdc = NULL;
if (result)
goto err_free;
......
......@@ -238,14 +238,39 @@ void mask_and_ack_8259A(unsigned int irq)
}
}
static char irq_trigger[2];
/**
* ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
*/
static void restore_ELCR(char *trigger)
{
outb(trigger[0], 0x4d0);
outb(trigger[1], 0x4d1);
}
static void save_ELCR(char *trigger)
{
/* IRQ 0,1,2,8,13 are marked as reserved */
trigger[0] = inb(0x4d0) & 0xF8;
trigger[1] = inb(0x4d1) & 0xDE;
}
static int i8259A_resume(struct sys_device *dev)
{
init_8259A(0);
restore_ELCR(irq_trigger);
return 0;
}
static int i8259A_suspend(struct sys_device *dev, u32 state)
{
save_ELCR(irq_trigger);
return 0;
}
static struct sysdev_class i8259_sysdev_class = {
set_kset_name("i8259"),
.suspend = i8259A_suspend,
.resume = i8259A_resume,
};
......
......@@ -72,6 +72,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;
......@@ -875,6 +879,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);
......@@ -957,6 +962,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;
}
......
......@@ -342,7 +342,7 @@ void mask_and_ack_8259A(unsigned int irq)
}
}
void __init init_8259A(int auto_eoi)
void init_8259A(int auto_eoi)
{
unsigned long flags;
......@@ -385,6 +385,57 @@ void __init init_8259A(int auto_eoi)
spin_unlock_irqrestore(&i8259A_lock, flags);
}
static char irq_trigger[2];
/**
* ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
*/
static void restore_ELCR(char *trigger)
{
outb(trigger[0], 0x4d0);
outb(trigger[1], 0x4d1);
}
static void save_ELCR(char *trigger)
{
/* IRQ 0,1,2,8,13 are marked as reserved */
trigger[0] = inb(0x4d0) & 0xF8;
trigger[1] = inb(0x4d1) & 0xDE;
}
static int i8259A_resume(struct sys_device *dev)
{
init_8259A(0);
restore_ELCR(irq_trigger);
return 0;
}
static int i8259A_suspend(struct sys_device *dev, u32 state)
{
save_ELCR(irq_trigger);
return 0;
}
static struct sysdev_class i8259_sysdev_class = {
set_kset_name("i8259"),
.suspend = i8259A_suspend,
.resume = i8259A_resume,
};
static struct sys_device device_i8259A = {
.id = 0,
.cls = &i8259_sysdev_class,
};
static int __init i8259A_init_sysfs(void)
{
int error = sysdev_class_register(&i8259_sysdev_class);
if (!error)
error = sysdev_register(&device_i8259A);
return error;
}
device_initcall(i8259A_init_sysfs);
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
......
......@@ -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;
......@@ -1047,6 +1049,8 @@ acpi_processor_get_performance_info (
if (!pr || !pr->performance || !pr->handle)
return_VALUE(-EINVAL);
acpi_processor_set_pdc(pr);
status = acpi_get_handle(pr->handle, "_PCT", &handle);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
......@@ -1054,8 +1058,6 @@ acpi_processor_get_performance_info (
return_VALUE(-ENODEV);
}
acpi_processor_set_pdc(pr);
result = acpi_processor_get_performance_control(pr);
if (result)
return_VALUE(result);
......@@ -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));
......
......@@ -60,6 +60,7 @@
#define ACPI_THERMAL_NOTIFY_HOT 0xF1
#define ACPI_THERMAL_MODE_ACTIVE 0x00
#define ACPI_THERMAL_MODE_PASSIVE 0x01
#define ACPI_THERMAL_MODE_CRT 0xff
#define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff"
#define ACPI_THERMAL_MAX_ACTIVE 10
......@@ -289,13 +290,6 @@ acpi_thermal_set_cooling_mode (
status = acpi_get_handle(tz->handle, "_SCP", &handle);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
status = acpi_get_handle(tz->handle, "_PSV", &handle);
if(!ACPI_FAILURE(status)) {
tz->cooling_mode = 1;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n",
mode?"passive":"active"));
return_VALUE(0);
}
return_VALUE(-ENODEV);
}
......@@ -950,12 +944,14 @@ static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
goto end;
if (!tz->flags.cooling_mode) {
seq_puts(seq, "<not supported>\n");
goto end;
seq_puts(seq, "<setting not supported>\n");
}
seq_printf(seq, "cooling mode: %s\n",
tz->cooling_mode?"passive":"active");
if ( tz->cooling_mode == ACPI_THERMAL_MODE_CRT )
seq_printf(seq, "cooling mode: critical\n");
else
seq_printf(seq, "cooling mode: %s\n",
tz->cooling_mode?"passive":"active");
end:
return 0;
......@@ -997,6 +993,8 @@ acpi_thermal_write_cooling_mode (
if (result)
return_VALUE(result);
acpi_thermal_check(tz);
return_VALUE(count);
}
......@@ -1234,16 +1232,34 @@ acpi_thermal_get_info (
if (result)
return_VALUE(result);
/* Set the cooling mode [_SCP] to active cooling (default) */
result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
if (!result)
tz->flags.cooling_mode = 1;
/* Get trip points [_CRT, _PSV, etc.] (required) */
result = acpi_thermal_get_trip_points(tz);
if (result)
return_VALUE(result);
/* Set the cooling mode [_SCP] to active cooling (default) */
result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
if (!result)
tz->flags.cooling_mode = 1;
else {
/* Oh,we have not _SCP method.
Generally show cooling_mode by _ACx, _PSV,spec 12.2*/
tz->flags.cooling_mode = 0;
if ( tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
if ( tz->trips.passive.temperature > tz->trips.active[0].temperature )
tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
else
tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
} else if ( !tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
} else if ( tz->trips.active[0].flags.valid && !tz->trips.passive.flags.valid ) {
tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
} else {
/* _ACx and _PSV are optional, but _CRT is required */
tz->cooling_mode = ACPI_THERMAL_MODE_CRT;
}
}
/* Get default polling frequency [_TZP] (optional) */
if (tzp)
tz->polling_frequency = tzp;
......
......@@ -102,6 +102,12 @@ __acpi_release_global_lock (unsigned int *lock)
:"0"(n_hi), "1"(n_lo))
/*
* Refer Intel ACPI _PDC support document for bit definitions
*/
#define ACPI_PDC_EST_CAPABILITY_SMP 0xa
#define ACPI_PDC_EST_CAPABILITY_MSR 0x1
#ifdef CONFIG_ACPI_BOOT
extern int acpi_lapic;
extern int acpi_ioapic;
......@@ -178,6 +184,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*/
......@@ -159,6 +159,8 @@ extern void acpi_reserve_bootmem(void);
extern int acpi_disabled;
extern int acpi_pci_disabled;
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