Following linux files needs para-virtualized to match pm interface with Xen. Signed-off-by Ke Yu Signed-off-by Kevin Tian diff -r d82790771926 linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/arch/i386/power/cpu-xen.c Tue Feb 13 16:34:07 2007 +0800 @@ -0,0 +1,132 @@ +/* + * Suspend support specific for i386. + * + * Distribute under GPLv2 + * + * Copyright (c) 2002 Pavel Machek + * Copyright (c) 2001 Patrick Mochel + */ + +#include +#include +#include +#include + +static struct saved_context saved_context; + +unsigned long saved_context_ebx; +unsigned long saved_context_esp, saved_context_ebp; +unsigned long saved_context_esi, saved_context_edi; +unsigned long saved_context_eflags; + +void __save_processor_state(struct saved_context *ctxt) +{ + kernel_fpu_begin(); + + /* + * descriptor tables + */ + store_gdt(&ctxt->gdt_limit); + store_idt(&ctxt->idt_limit); + store_tr(ctxt->tr); + + /* + * segment registers + */ + savesegment(es, ctxt->es); + savesegment(fs, ctxt->fs); + savesegment(gs, ctxt->gs); + savesegment(ss, ctxt->ss); + + /* + * control registers + */ + ctxt->cr0 = read_cr0(); + ctxt->cr2 = read_cr2(); + ctxt->cr3 = read_cr3(); + ctxt->cr4 = read_cr4(); +} + +void save_processor_state(void) +{ + __save_processor_state(&saved_context); +} + +static void do_fpu_end(void) +{ + /* + * Restore FPU regs if necessary. + */ + kernel_fpu_end(); +} + +static void fix_processor_context(void) +{ + int cpu = smp_processor_id(); + struct tss_struct * t = &per_cpu(init_tss, cpu); + + set_tss_desc(cpu,t); /* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */ + + load_TR_desc(); /* This does ltr */ + load_LDT(¤t->active_mm->context); /* This does lldt */ + + /* + * Now maybe reload the debug registers + */ + if (current->thread.debugreg[7]){ + set_debugreg(current->thread.debugreg[0], 0); + set_debugreg(current->thread.debugreg[1], 1); + set_debugreg(current->thread.debugreg[2], 2); + set_debugreg(current->thread.debugreg[3], 3); + /* no 4 and 5 */ + set_debugreg(current->thread.debugreg[6], 6); + set_debugreg(current->thread.debugreg[7], 7); + } + +} + +void __restore_processor_state(struct saved_context *ctxt) +{ + /* + * control registers + */ + write_cr4(ctxt->cr4); + write_cr3(ctxt->cr3); + write_cr2(ctxt->cr2); + write_cr0(ctxt->cr0); + + /* + * now restore the descriptor tables to their proper values + * ltr is done i fix_processor_context(). + */ + load_gdt(&ctxt->gdt_limit); + load_idt(&ctxt->idt_limit); + + /* + * segment registers + */ + loadsegment(es, ctxt->es); + loadsegment(fs, ctxt->fs); + loadsegment(gs, ctxt->gs); + loadsegment(ss, ctxt->ss); + + /* + * sysenter MSRs + */ + if (boot_cpu_has(X86_FEATURE_SEP)) + enable_sep_cpu(); + + fix_processor_context(); + do_fpu_end(); + mtrr_ap_init(); + mcheck_init(&boot_cpu_data); +} + +void restore_processor_state(void) +{ + __restore_processor_state(&saved_context); +} + +/* Needed by apm.c */ +EXPORT_SYMBOL(save_processor_state); +EXPORT_SYMBOL(restore_processor_state); diff -r d82790771926 linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/hwsleep-xen.c Tue Feb 13 16:34:07 2007 +0800 @@ -0,0 +1,588 @@ + +/****************************************************************************** + * + * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2006, R. Byron Moore + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwsleep") + +/******************************************************************************* + * + * FUNCTION: acpi_set_firmware_waking_vector + * + * PARAMETERS: physical_address - Physical address of ACPI real mode + * entry point. + * + * RETURN: Status + * + * DESCRIPTION: Access function for the firmware_waking_vector field in FACS + * + ******************************************************************************/ +acpi_status +acpi_set_firmware_waking_vector(acpi_physical_address physical_address) +{ + + ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector); + + /* Set the vector */ + + if (acpi_gbl_common_fACS.vector_width == 32) { + *(ACPI_CAST_PTR + (u32, acpi_gbl_common_fACS.firmware_waking_vector)) + = (u32) physical_address; + } else { + *acpi_gbl_common_fACS.firmware_waking_vector = physical_address; + } + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) + +/******************************************************************************* + * + * FUNCTION: acpi_get_firmware_waking_vector + * + * PARAMETERS: *physical_address - Where the contents of + * the firmware_waking_vector field of + * the FACS will be returned. + * + * RETURN: Status, vector + * + * DESCRIPTION: Access function for the firmware_waking_vector field in FACS + * + ******************************************************************************/ +#ifdef ACPI_FUTURE_USAGE +acpi_status +acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) +{ + + ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector); + + if (!physical_address) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* Get the vector */ + + if (acpi_gbl_common_fACS.vector_width == 32) { + *physical_address = (acpi_physical_address) + * + (ACPI_CAST_PTR + (u32, acpi_gbl_common_fACS.firmware_waking_vector)); + } else { + *physical_address = + *acpi_gbl_common_fACS.firmware_waking_vector; + } + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector) +#endif + +/******************************************************************************* + * + * FUNCTION: acpi_enter_sleep_state_prep + * + * PARAMETERS: sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231) + * This function must execute with interrupts enabled. + * We break sleeping into 2 stages so that OSPM can handle + * various OS-specific tasks between the two steps. + * + ******************************************************************************/ +acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) +{ + acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); + + /* + * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. + */ + status = acpi_get_sleep_type_data(sleep_state, + &acpi_gbl_sleep_type_a, + &acpi_gbl_sleep_type_b); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Setup parameter object */ + + arg_list.count = 1; + arg_list.pointer = &arg; + + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = sleep_state; + + /* Run the _PTS and _GTS methods */ + + status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + return_ACPI_STATUS(status); + } + + status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + return_ACPI_STATUS(status); + } + + /* Setup the argument to _SST */ + + switch (sleep_state) { + case ACPI_STATE_S0: + arg.integer.value = ACPI_SST_WORKING; + break; + + case ACPI_STATE_S1: + case ACPI_STATE_S2: + case ACPI_STATE_S3: + arg.integer.value = ACPI_SST_SLEEPING; + break; + + case ACPI_STATE_S4: + arg.integer.value = ACPI_SST_SLEEP_CONTEXT; + break; + + default: + arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is off */ + break; + } + + /* Set the system indicators to show the desired sleep state. */ + + status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, + "While executing method _SST")); + } + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) + +/******************************************************************************* + * + * FUNCTION: acpi_enter_sleep_state + * + * PARAMETERS: sleep_state - Which sleep state to enter + * + * RETURN: Status + * + * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231) + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ +acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) +{ + u32 PM1Acontrol; + u32 PM1Bcontrol; + struct acpi_bit_register_info *sleep_type_reg_info; + struct acpi_bit_register_info *sleep_enable_reg_info; + u32 in_value; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state); + + if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) || + (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) { + ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X", + acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b)); + return_ACPI_STATUS(AE_AML_OPERAND_VALUE); + } + + sleep_type_reg_info = + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); + sleep_enable_reg_info = + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); + + /* Clear wake status */ + + status = + acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Clear all fixed and general purpose status bits */ + + status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * 1) Disable/Clear all GPEs + * 2) Enable all wakeup GPEs + */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + acpi_gbl_system_awake_and_running = FALSE; + + status = acpi_hw_enable_all_wakeup_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get current value of PM1A control */ + + status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + ACPI_DEBUG_PRINT((ACPI_DB_INIT, + "Entering sleep state [S%d]\n", sleep_state)); + + /* Clear SLP_EN and SLP_TYP fields */ + + PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | + sleep_enable_reg_info->access_bit_mask); + PM1Bcontrol = PM1Acontrol; + + /* Insert SLP_TYP bits */ + + PM1Acontrol |= + (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); + PM1Bcontrol |= + (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); + + /* + * We split the writes of SLP_TYP and SLP_EN to workaround + * poorly implemented hardware. + */ + + /* Write #1: fill in SLP_TYP data */ + + status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1A_CONTROL, + PM1Acontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1B_CONTROL, + PM1Bcontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Insert SLP_ENABLE bit */ + + PM1Acontrol |= sleep_enable_reg_info->access_bit_mask; + PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; + + /* Write #2: SLP_TYP + SLP_EN */ + + ACPI_FLUSH_CPU_CACHE(); + + status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1A_CONTROL, + PM1Acontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1B_CONTROL, + PM1Bcontrol); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (sleep_state > ACPI_STATE_S3) { + /* + * We wanted to sleep > S3, but it didn't happen (by virtue of the + * fact that we are still executing!) + * + * Wait ten seconds, then try again. This is to get S4/S5 to work on + * all machines. + * + * We wait so long to allow chipsets that poll this reg very slowly to + * still read the right value. Ideally, this block would go + * away entirely. + */ + acpi_os_stall(10000000); + + status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_CONTROL, + sleep_enable_reg_info-> + access_bit_mask); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } + + /* Wait until we enter sleep state */ + + do { + status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value, + ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Spin until we wake */ + + } while (!in_value); + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state) + +/******************************************************************************* + * + * FUNCTION: acpi_enter_sleep_state_s4bios + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Perform a S4 bios request. + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED + * + ******************************************************************************/ +acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) +{ + u32 in_value; + acpi_status status; + + ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); + + status = + acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + status = acpi_hw_clear_acpi_status(ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * 1) Disable/Clear all GPEs + * 2) Enable all wakeup GPEs + */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + acpi_gbl_system_awake_and_running = FALSE; + + status = acpi_hw_enable_all_wakeup_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + ACPI_FLUSH_CPU_CACHE(); + + status = acpi_os_write_port(acpi_gbl_FADT->smi_cmd, + (u32) acpi_gbl_FADT->S4bios_req, 8); + + do { + acpi_os_stall(1000); + status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value, + ACPI_MTX_DO_NOT_LOCK); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + } while (!in_value); + + return_ACPI_STATUS(AE_OK); +} + +ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios) + +/******************************************************************************* + * + * FUNCTION: acpi_leave_sleep_state + * + * PARAMETERS: sleep_state - Which sleep state we just exited + * + * RETURN: Status + * + * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep + * Called with interrupts ENABLED. + * + ******************************************************************************/ +acpi_status acpi_leave_sleep_state(u8 sleep_state) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + struct acpi_bit_register_info *sleep_type_reg_info; + struct acpi_bit_register_info *sleep_enable_reg_info; + u32 PM1Acontrol; + u32 PM1Bcontrol; + + ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); + + /* + * Set SLP_TYPE and SLP_EN to state S0. + * This is unclear from the ACPI Spec, but it is required + * by some machines. + */ + status = acpi_get_sleep_type_data(ACPI_STATE_S0, + &acpi_gbl_sleep_type_a, + &acpi_gbl_sleep_type_b); + if (ACPI_SUCCESS(status)) { + sleep_type_reg_info = + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); + sleep_enable_reg_info = + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); + + /* Get current value of PM1A control */ + + status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_CONTROL, + &PM1Acontrol); + if (ACPI_SUCCESS(status)) { + + /* Clear SLP_EN and SLP_TYP fields */ + + PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | + sleep_enable_reg_info-> + access_bit_mask); + PM1Bcontrol = PM1Acontrol; + + /* Insert SLP_TYP bits */ + + PM1Acontrol |= + (acpi_gbl_sleep_type_a << sleep_type_reg_info-> + bit_position); + PM1Bcontrol |= + (acpi_gbl_sleep_type_b << sleep_type_reg_info-> + bit_position); + + /* Just ignore any errors */ + + (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1A_CONTROL, + PM1Acontrol); + (void)acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1B_CONTROL, + PM1Bcontrol); + } + } + + /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */ + + acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID; + + /* Setup parameter object */ + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + + /* Ignore any errors from these methods */ + + arg.integer.value = ACPI_SST_WAKING; + status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); + } + + arg.integer.value = sleep_state; + status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS")); + } + + status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); + } + /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ + + /* + * Restore the GPEs: + * 1) Disable/Clear all GPEs + * 2) Enable all runtime GPEs + */ + status = acpi_hw_disable_all_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + acpi_gbl_system_awake_and_running = TRUE; + + status = acpi_hw_enable_all_runtime_gpes(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Enable power button */ + + (void) + acpi_set_register(acpi_gbl_fixed_event_info + [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1, + ACPI_MTX_DO_NOT_LOCK); + + (void) + acpi_set_register(acpi_gbl_fixed_event_info + [ACPI_EVENT_POWER_BUTTON].status_register_id, 1, + ACPI_MTX_DO_NOT_LOCK); + + arg.integer.value = ACPI_SST_WORKING; + status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + ACPI_EXCEPTION((AE_INFO, status, "During Method _SST")); + } + + return_ACPI_STATUS(status); +} + +ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state) diff -r d82790771926 linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/Makefile Tue Feb 13 16:33:52 2007 +0800 @@ -0,0 +1,5 @@ +obj-y := poweroff.o wakeup.o +obj-$(CONFIG_ACPI_SLEEP) += main.o +obj-$(CONFIG_ACPI_SLEEP_PROC_FS) += proc.o + +EXTRA_CFLAGS += $(ACPI_CFLAGS) diff -r d82790771926 linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/main-xen.c Tue Feb 13 16:34:07 2007 +0800 @@ -0,0 +1,232 @@ +/* + * sleep.c - ACPI sleep support. + * + * Copyright (c) 2005 Alexey Starikovskiy + * Copyright (c) 2004 David Shaohua Li + * Copyright (c) 2000-2003 Patrick Mochel + * Copyright (c) 2003 Open Source Development Lab + * + * This file is released under the GPLv2. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "sleep.h" + +u8 sleep_states[ACPI_S_STATE_COUNT]; + +static struct pm_ops acpi_pm_ops; + +extern void do_suspend_lowlevel(void); + +static u32 acpi_suspend_states[] = { + [PM_SUSPEND_ON] = ACPI_STATE_S0, + [PM_SUSPEND_STANDBY] = ACPI_STATE_S1, + [PM_SUSPEND_MEM] = ACPI_STATE_S3, + [PM_SUSPEND_DISK] = ACPI_STATE_S4, + [PM_SUSPEND_MAX] = ACPI_STATE_S5 +}; + +static int init_8259A_after_S1; + +/** + * acpi_pm_prepare - Do preliminary suspend work. + * @pm_state: suspend state we're entering. + * + * Make sure we support the state. If we do, and we need it, set the + * firmware waking vector and do arch-specific nastiness to get the + * wakeup code to the waking vector. + */ + +extern int acpi_sleep_prepare(u32 acpi_state); +extern void acpi_power_off(void); + +static int acpi_pm_prepare(suspend_state_t pm_state) +{ + u32 acpi_state = acpi_suspend_states[pm_state]; + + if (!sleep_states[acpi_state]) { + printk("acpi_pm_prepare does not support %d \n", pm_state); + return -EPERM; + } + return acpi_sleep_prepare(acpi_state); +} + +/** + * acpi_pm_enter - Actually enter a sleep state. + * @pm_state: State we're entering. + * + * Flush caches and go to sleep. For STR or STD, we have to call + * arch-specific assembly, which in turn call acpi_enter_sleep_state(). + * It's unfortunate, but it works. Please fix if you're feeling frisky. + */ + +static int acpi_pm_enter(suspend_state_t pm_state) +{ + acpi_status status = AE_OK; + unsigned long flags = 0; + u32 acpi_state = acpi_suspend_states[pm_state]; + + ACPI_FLUSH_CPU_CACHE(); + + /* Do arch specific saving of state. */ + if (pm_state > PM_SUSPEND_STANDBY) { + int error = acpi_save_state_mem(); + if (error) + return error; + } + + local_irq_save(flags); + acpi_enable_wakeup_device(acpi_state); + switch (pm_state) { + case PM_SUSPEND_STANDBY: + barrier(); + status = acpi_enter_sleep_state(acpi_state); + break; + + case PM_SUSPEND_MEM: + do_suspend_lowlevel(); + break; + + case PM_SUSPEND_DISK: + if (acpi_pm_ops.pm_disk_mode == PM_DISK_PLATFORM) + status = acpi_enter_sleep_state(acpi_state); + break; + case PM_SUSPEND_MAX: + acpi_power_off(); + break; + + default: + return -EINVAL; + } + + /* ACPI 3.0 specs (P62) says that it's the responsabilty + * of the OSPM to clear the status bit [ implying that the + * POWER_BUTTON event should not reach userspace ] + */ + if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) + acpi_clear_event(ACPI_EVENT_POWER_BUTTON); + + local_irq_restore(flags); + printk(KERN_DEBUG "Back to C!\n"); + + /* restore processor state + * We should only be here if we're coming back from STR or STD. + * And, in the case of the latter, the memory image should have already + * been loaded from disk. + */ + if (pm_state > PM_SUSPEND_STANDBY) + acpi_restore_state_mem(); + + return ACPI_SUCCESS(status) ? 0 : -EFAULT; +} + +/** + * acpi_pm_finish - Finish up suspend sequence. + * @pm_state: State we're coming out of. + * + * This is called after we wake back up (or if entering the sleep state + * failed). + */ + +static int acpi_pm_finish(suspend_state_t pm_state) +{ + u32 acpi_state = acpi_suspend_states[pm_state]; + + acpi_leave_sleep_state(acpi_state); + acpi_disable_wakeup_device(acpi_state); + + /* reset firmware waking vector */ + acpi_set_firmware_waking_vector((acpi_physical_address) 0); + + if (init_8259A_after_S1) { + printk("Broken toshiba laptop -> kicking interrupts\n"); + init_8259A(0); + } + return 0; +} + +int acpi_suspend(u32 acpi_state) +{ + suspend_state_t states[] = { + [1] = PM_SUSPEND_STANDBY, + [3] = PM_SUSPEND_MEM, + [4] = PM_SUSPEND_DISK, + [5] = PM_SUSPEND_MAX + }; + + if (acpi_state < 6 && states[acpi_state]) + return pm_suspend(states[acpi_state]); + return -EINVAL; +} + +static int acpi_pm_state_valid(suspend_state_t pm_state) +{ + u32 acpi_state = acpi_suspend_states[pm_state]; + + return sleep_states[acpi_state]; +} + +static struct pm_ops acpi_pm_ops = { + .valid = acpi_pm_state_valid, + .prepare = acpi_pm_prepare, + .enter = acpi_pm_enter, + .finish = acpi_pm_finish, +}; + +/* + * Toshiba fails to preserve interrupts over S1, reinitialization + * of 8259 is needed after S1 resume. + */ +static int __init init_ints_after_s1(struct dmi_system_id *d) +{ + printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident); + init_8259A_after_S1 = 1; + return 0; +} + +static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + { + .callback = init_ints_after_s1, + .ident = "Toshiba Satellite 4030cdt", + .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),}, + }, + {}, +}; + +static int __init acpi_sleep_init(void) +{ + int i = 0; + + dmi_check_system(acpisleep_dmi_table); + + if (acpi_disabled) + return 0; + + printk(KERN_INFO PREFIX "(supports"); + for (i = 0; i < ACPI_S_STATE_COUNT; i++) { + acpi_status status; + u8 type_a, type_b; + status = acpi_get_sleep_type_data(i, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { + sleep_states[i] = 1; + printk(" S%d", i); + } + if (i == ACPI_STATE_S4) { + if (sleep_states[i]) + acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM; + } + } + printk(")\n"); + + pm_set_ops(&acpi_pm_ops); + return 0; +} + +late_initcall(acpi_sleep_init); diff -r d82790771926 linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/acpi/sleep/poweroff-xen.c Tue Feb 13 16:34:07 2007 +0800 @@ -0,0 +1,99 @@ +/* + * poweroff.c - ACPI handler for powering off the system. + * + * AKA S5, but it is independent of whether or not the kernel supports + * any other sleep support in the system. + * + * Copyright (c) 2005 Alexey Starikovskiy + * + * This file is released under the GPLv2. + */ + +#include +#include +#include +#include +#include +#include +#include "sleep.h" + +int acpi_sleep_prepare(u32 acpi_state) +{ +#ifdef CONFIG_ACPI_SLEEP + /* do we have a wakeup address for S2 and S3? */ + if (acpi_state == ACPI_STATE_S3) { + if (!acpi_wakeup_address) { + return -EFAULT; + } + acpi_set_firmware_waking_vector((acpi_physical_address) + virt_to_phys((void *) + acpi_wakeup_address)); + + } + ACPI_FLUSH_CPU_CACHE(); + acpi_enable_wakeup_device_prep(acpi_state); +#endif + acpi_gpe_sleep_prepare(acpi_state); + acpi_enter_sleep_state_prep(acpi_state); + return 0; +} + +#ifdef CONFIG_PM + +void acpi_power_off(void) +{ + /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ + printk("%s called\n", __FUNCTION__); + local_irq_disable(); + /* Some SMP machines only can poweroff in boot CPU */ + acpi_enter_sleep_state(ACPI_STATE_S5); +} + +static int acpi_shutdown(struct sys_device *x) +{ + switch (system_state) { + case SYSTEM_POWER_OFF: + /* Prepare to power off the system */ + return acpi_sleep_prepare(ACPI_STATE_S5); + case SYSTEM_SUSPEND_DISK: + /* Prepare to suspend the system to disk */ + return acpi_sleep_prepare(ACPI_STATE_S4); + default: + return 0; + } +} + +static struct sysdev_class acpi_sysclass = { + set_kset_name("acpi"), + .shutdown = acpi_shutdown +}; + +static struct sys_device device_acpi = { + .id = 0, + .cls = &acpi_sysclass, +}; + +static int acpi_poweroff_init(void) +{ + if (!acpi_disabled) { + u8 type_a, type_b; + acpi_status status; + + status = + acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); + if (ACPI_SUCCESS(status)) { + int error; + error = sysdev_class_register(&acpi_sysclass); + if (!error) + error = sysdev_register(&device_acpi); + if (!error) + pm_power_off = acpi_power_off; + return error; + } + } + return 0; +} + +late_initcall(acpi_poweroff_init); + +#endif /* CONFIG_PM */ diff -r d82790771926 linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/acpi/hardware/Makefile Tue Feb 13 16:34:43 2007 +0800 @@ -0,0 +1,9 @@ +# +# Makefile for all Linux ACPI interpreter subdirectories +# + +obj-y := hwacpi.o hwgpe.o hwregs.o hwsleep.o + +obj-$(ACPI_FUTURE_USAGE) += hwtimer.o + +EXTRA_CFLAGS += $(ACPI_CFLAGS)