提交 02c646ef 编写于 作者: L Linus Torvalds

Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6:
  ACPI / PM: Do not enable GPEs for system wakeup in advance
  ACPICA: Truncate I/O addresses to 16 bits for Windows compatibility
  ACPICA: Limit maximum time for Sleep() operator
  ACPICA: Fix namestring associated with AE_NO_HANDLER exception
  ACPI / ACPICA: Fix sysfs GPE interface
  ACPI / ACPICA: Fix GPE initialization
  ACPI / ACPICA: Avoid writing full enable masks to GPE registers
  ACPI / ACPICA: Fix low-level GPE manipulation code
  ACPI / ACPICA: Use helper function for computing GPE masks
  ACPI / ACPICA: Do not attempt to disable GPE when installing handler
  ACPI: Disable Vista compatibility for Sony VGN-NS50B_L
  ACPI: fan: fix unbalanced code block
  ACPI: Store NVS state even when entering suspend to RAM
  suspend: Move NVS save/restore code to generic suspend functionality
  ACPI: Do not try to set up acpi processor stuff on cores exceeding maxcpus=
  ACPI: acpi_pad: Don't needlessly mark LAPIC unstable
......@@ -729,7 +729,7 @@ static int __init e820_mark_nvs_memory(void)
struct e820entry *ei = &e820.map[i];
if (ei->type == E820_NVS)
hibernate_nvs_register(ei->addr, ei->size);
suspend_nvs_register(ei->addr, ei->size);
}
return 0;
......
......@@ -46,6 +46,8 @@ static unsigned long power_saving_mwait_eax;
static unsigned char tsc_detected_unstable;
static unsigned char tsc_marked_unstable;
static unsigned char lapic_detected_unstable;
static unsigned char lapic_marked_unstable;
static void power_saving_mwait_init(void)
{
......@@ -75,9 +77,6 @@ static void power_saving_mwait_init(void)
power_saving_mwait_eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) |
(highest_subcstate - 1);
for_each_online_cpu(i)
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &i);
#if defined(CONFIG_GENERIC_TIME) && defined(CONFIG_X86)
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
......@@ -86,13 +85,15 @@ static void power_saving_mwait_init(void)
* AMD Fam10h TSC will tick in all
* C/P/S0/S1 states when this bit is set.
*/
if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
return;
/*FALL THROUGH*/
if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
tsc_detected_unstable = 1;
if (!boot_cpu_has(X86_FEATURE_ARAT))
lapic_detected_unstable = 1;
break;
default:
/* TSC could halt in idle */
/* TSC & LAPIC could halt in idle */
tsc_detected_unstable = 1;
lapic_detected_unstable = 1;
}
#endif
}
......@@ -180,10 +181,20 @@ static int power_saving_thread(void *data)
mark_tsc_unstable("TSC halts in idle");
tsc_marked_unstable = 1;
}
if (lapic_detected_unstable && !lapic_marked_unstable) {
int i;
/* LAPIC could halt in idle, so notify users */
for_each_online_cpu(i)
clockevents_notify(
CLOCK_EVT_NOTIFY_BROADCAST_ON,
&i);
lapic_marked_unstable = 1;
}
local_irq_disable();
cpu = smp_processor_id();
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
&cpu);
if (lapic_marked_unstable)
clockevents_notify(
CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
stop_critical_timings();
__monitor((void *)&current_thread_info()->flags, 0, 0);
......@@ -192,8 +203,9 @@ static int power_saving_thread(void *data)
__mwait(power_saving_mwait_eax, 1);
start_critical_timings();
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
&cpu);
if (lapic_marked_unstable)
clockevents_notify(
CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
local_irq_enable();
if (jiffies > expire_time) {
......
......@@ -119,6 +119,10 @@
#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF
/* Maximum sleep allowed via Sleep() operator */
#define ACPI_MAX_SLEEP 20000 /* Two seconds */
/******************************************************************************
*
* ACPI Specification constants (Do not change unless the specification changes)
......
......@@ -80,10 +80,6 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
acpi_status
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
u32 gpe_number);
......
......@@ -125,6 +125,14 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
*/
u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE);
/*
* Optionally truncate I/O addresses to 16 bits. Provides compatibility
* with other ACPI implementations. NOTE: During ACPICA initialization,
* this value is set to TRUE if any Windows OSI strings have been
* requested by the BIOS.
*/
u8 ACPI_INIT_GLOBAL(acpi_gbl_truncate_io_addresses, FALSE);
/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
struct acpi_table_fadt acpi_gbl_FADT;
......
......@@ -90,7 +90,11 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);
/*
* hwgpe - GPE support
*/
acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info);
u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
struct acpi_gpe_register_info *gpe_register_info);
acpi_status
acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action);
acpi_status
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info);
......
......@@ -69,7 +69,7 @@ acpi_status
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
u8 register_bit;
u32 register_bit;
ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks);
......@@ -78,9 +78,8 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
return_ACPI_STATUS(AE_NOT_EXIST);
}
register_bit = (u8)
(1 <<
(gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
gpe_register_info);
/* Clear the wake/run bits up front */
......@@ -100,106 +99,6 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_enable_gpe
*
* PARAMETERS: gpe_event_info - GPE to enable
*
* RETURN: Status
*
* DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
* of type or number of references.
*
* Note: The GPE lock should be already acquired when this function is called.
*
******************************************************************************/
acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ev_enable_gpe);
/*
* We will only allow a GPE to be enabled if it has either an
* associated method (_Lxx/_Exx) or a handler. Otherwise, the
* GPE will be immediately disabled by acpi_ev_gpe_dispatch the
* first time it fires.
*/
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
return_ACPI_STATUS(AE_NO_HANDLER);
}
/* Ensure the HW enable masks are current */
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Clear the GPE (of stale events) */
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Enable the requested GPE */
status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_disable_gpe
*
* PARAMETERS: gpe_event_info - GPE to disable
*
* RETURN: Status
*
* DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
* regardless of the type or number of references.
*
* Note: The GPE lock should be already acquired when this function is called.
*
******************************************************************************/
acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ev_disable_gpe);
/*
* Note: Always disable the GPE, even if we think that that it is already
* disabled. It is possible that the AML or some other code has enabled
* the GPE behind our back.
*/
/* Ensure the HW enable masks are current */
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Always H/W disable this GPE, even if we don't know the GPE type.
* Simply clear the enable bit for this particular GPE, but do not
* write out the current GPE enable mask since this may inadvertently
* enable GPEs too early. An example is a rogue GPE that has arrived
* during ACPICA initialization - possibly because AML or other code
* has enabled the GPE.
*/
status = acpi_hw_low_disable_gpe(gpe_event_info);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
......@@ -451,10 +350,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
return_VOID;
}
/* Update the GPE register masks for return to enabled state */
(void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
/*
* Take a snapshot of the GPE info for this level - we copy the info to
* prevent a race condition with remove_handler/remove_block.
......@@ -607,7 +502,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
* Disable the GPE, so it doesn't keep firing before the method has a
* chance to run (it runs asynchronously with interrupts enabled).
*/
status = acpi_ev_disable_gpe(gpe_event_info);
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE[0x%2X]",
......@@ -644,7 +539,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
* Disable the GPE. The GPE will remain disabled a handler
* is installed or ACPICA is restarted.
*/
status = acpi_ev_disable_gpe(gpe_event_info);
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to disable GPE[0x%2X]",
......
......@@ -500,6 +500,19 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
gpe_event_info = &gpe_block->event_info[gpe_index];
gpe_number = gpe_index + gpe_block->block_base_number;
/*
* If the GPE has already been enabled for runtime
* signaling, make sure it remains enabled, but do not
* increment its reference counter.
*/
if (gpe_event_info->runtime_count) {
acpi_set_gpe(gpe_device, gpe_number,
ACPI_GPE_ENABLE);
gpe_enabled_count++;
continue;
}
if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
wake_gpe_count++;
......@@ -516,7 +529,6 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
/* Enable this GPE */
gpe_number = gpe_index + gpe_block->block_base_number;
status = acpi_enable_gpe(gpe_device, gpe_number,
ACPI_GPE_TYPE_RUNTIME);
if (ACPI_FAILURE(status)) {
......
......@@ -719,13 +719,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
handler->context = context;
handler->method_node = gpe_event_info->dispatch.method_node;
/* Disable the GPE before installing the handler */
status = acpi_ev_disable_gpe(gpe_event_info);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
/* Install the handler */
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
......
......@@ -208,6 +208,44 @@ acpi_status acpi_enable_event(u32 event, u32 flags)
ACPI_EXPORT_SYMBOL(acpi_enable_event)
/*******************************************************************************
*
* FUNCTION: acpi_clear_and_enable_gpe
*
* PARAMETERS: gpe_event_info - GPE to enable
*
* RETURN: Status
*
* DESCRIPTION: Clear the given GPE from stale events and enable it.
*
******************************************************************************/
static acpi_status
acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;
/*
* We will only allow a GPE to be enabled if it has either an
* associated method (_Lxx/_Exx) or a handler. Otherwise, the
* GPE will be immediately disabled by acpi_ev_gpe_dispatch the
* first time it fires.
*/
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
return_ACPI_STATUS(AE_NO_HANDLER);
}
/* Clear the GPE (of stale events) */
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Enable the requested GPE */
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_set_gpe
......@@ -249,11 +287,11 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
switch (action) {
case ACPI_GPE_ENABLE:
status = acpi_ev_enable_gpe(gpe_event_info);
status = acpi_clear_and_enable_gpe(gpe_event_info);
break;
case ACPI_GPE_DISABLE:
status = acpi_ev_disable_gpe(gpe_event_info);
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
break;
default:
......@@ -316,7 +354,11 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
gpe_event_info->runtime_count++;
if (gpe_event_info->runtime_count == 1) {
status = acpi_ev_enable_gpe(gpe_event_info);
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
if (ACPI_SUCCESS(status)) {
status = acpi_clear_and_enable_gpe(gpe_event_info);
}
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count--;
goto unlock_and_exit;
......@@ -343,7 +385,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
*/
gpe_event_info->wakeup_count++;
if (gpe_event_info->wakeup_count == 1) {
(void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
}
......@@ -403,7 +445,12 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
gpe_event_info->runtime_count--;
if (!gpe_event_info->runtime_count) {
status = acpi_ev_disable_gpe(gpe_event_info);
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
if (ACPI_SUCCESS(status)) {
status = acpi_hw_low_set_gpe(gpe_event_info,
ACPI_GPE_DISABLE);
}
if (ACPI_FAILURE(status)) {
gpe_event_info->runtime_count++;
goto unlock_and_exit;
......@@ -424,7 +471,7 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
gpe_event_info->wakeup_count--;
if (!gpe_event_info->wakeup_count) {
(void)acpi_ev_update_gpe_enable_masks(gpe_event_info);
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
}
}
......
......@@ -201,6 +201,14 @@ acpi_status acpi_ex_system_do_sleep(u64 how_long)
acpi_ex_relinquish_interpreter();
/*
* For compatibility with other ACPI implementations and to prevent
* accidental deep sleeps, limit the sleep time to something reasonable.
*/
if (how_long > ACPI_MAX_SLEEP) {
how_long = ACPI_MAX_SLEEP;
}
acpi_os_sleep(how_long);
/* And now we must get the interpreter again */
......
......@@ -57,21 +57,47 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/******************************************************************************
*
* FUNCTION: acpi_hw_low_disable_gpe
* FUNCTION: acpi_hw_gpe_register_bit
*
* PARAMETERS: gpe_event_info - Info block for the GPE
* gpe_register_info - Info block for the GPE register
*
* RETURN: Status
*
* DESCRIPTION: Compute GPE enable mask with one bit corresponding to the given
* GPE set.
*
******************************************************************************/
u32 acpi_hw_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
struct acpi_gpe_register_info *gpe_register_info)
{
return (u32)1 << (gpe_event_info->gpe_number -
gpe_register_info->base_gpe_number);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_low_set_gpe
*
* PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
* action - Enable or disable
*
* RETURN: Status
*
* DESCRIPTION: Disable a single GPE in the enable register.
* DESCRIPTION: Enable or disable a single GPE in its enable register.
*
******************************************************************************/
acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
acpi_status
acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u8 action)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
u32 enable_mask;
u32 register_bit;
ACPI_FUNCTION_ENTRY();
/* Get the info block for the entire GPE register */
......@@ -87,11 +113,27 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
return (status);
}
/* Clear just the bit that corresponds to this GPE */
/* Set ot clear just the bit that corresponds to this GPE */
ACPI_CLEAR_BIT(enable_mask, ((u32)1 <<
(gpe_event_info->gpe_number -
gpe_register_info->base_gpe_number)));
register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
gpe_register_info);
switch (action) {
case ACPI_GPE_COND_ENABLE:
if (!(register_bit & gpe_register_info->enable_for_run))
return (AE_BAD_PARAMETER);
case ACPI_GPE_ENABLE:
ACPI_SET_BIT(enable_mask, register_bit);
break;
case ACPI_GPE_DISABLE:
ACPI_CLEAR_BIT(enable_mask, register_bit);
break;
default:
ACPI_ERROR((AE_INFO, "Invalid action\n"));
return (AE_BAD_PARAMETER);
}
/* Write the updated enable mask */
......@@ -116,23 +158,11 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
acpi_status
acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
ACPI_FUNCTION_ENTRY();
/* Get the info block for the entire GPE register */
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
return (AE_NOT_EXIST);
}
/* Write the entire GPE (runtime) enable register */
status = acpi_hw_write(gpe_register_info->enable_for_run,
&gpe_register_info->enable_address);
status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_COND_ENABLE);
return (status);
}
......@@ -150,21 +180,28 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
u8 register_bit;
u32 register_bit;
ACPI_FUNCTION_ENTRY();
register_bit = (u8)(1 <<
(gpe_event_info->gpe_number -
gpe_event_info->register_info->base_gpe_number));
/* Get the info block for the entire GPE register */
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
return (AE_NOT_EXIST);
}
register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
gpe_register_info);
/*
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
status = acpi_hw_write(register_bit,
&gpe_event_info->register_info->status_address);
&gpe_register_info->status_address);
return (status);
}
......@@ -187,7 +224,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
acpi_event_status * event_status)
{
u32 in_byte;
u8 register_bit;
u32 register_bit;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
acpi_event_status local_event_status = 0;
......@@ -204,9 +241,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
/* Get the register bitmask for this GPE */
register_bit = (u8)(1 <<
(gpe_event_info->gpe_number -
gpe_event_info->register_info->base_gpe_number));
register_bit = acpi_hw_gpe_register_bit(gpe_event_info,
gpe_register_info);
/* GPE currently enabled? (enabled for runtime?) */
......
......@@ -222,6 +222,12 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
u32 one_byte;
u32 i;
/* Truncate address to 16 bits if requested */
if (acpi_gbl_truncate_io_addresses) {
address &= ACPI_UINT16_MAX;
}
/* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
......@@ -279,6 +285,12 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
acpi_status status;
u32 i;
/* Truncate address to 16 bits if requested */
if (acpi_gbl_truncate_io_addresses) {
address &= ACPI_UINT16_MAX;
}
/* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
......
......@@ -193,6 +193,15 @@ acpi_status acpi_ns_initialize_devices(void)
acpi_ns_init_one_device, NULL, &info,
NULL);
/*
* Any _OSI requests should be completed by now. If the BIOS has
* requested any Windows OSI strings, we will always truncate
* I/O addresses to 16 bits -- for Windows compatibility.
*/
if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
acpi_gbl_truncate_io_addresses = TRUE;
}
ACPI_FREE(info.evaluate_info);
if (ACPI_FAILURE(status)) {
goto error_exit;
......
......@@ -218,6 +218,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
},
},
{
.callback = dmi_disable_osi_vista,
.ident = "VGN-NS50B_L",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
},
},
{
.callback = dmi_disable_osi_win7,
.ident = "ASUS K50IJ",
.matches = {
......
......@@ -425,7 +425,7 @@ static int acpi_button_add(struct acpi_device *device)
/* Button's GPE is run-wake GPE */
acpi_enable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number,
ACPI_GPE_TYPE_WAKE_RUN);
ACPI_GPE_TYPE_RUNTIME);
device->wakeup.run_wake_count++;
device->wakeup.state.enabled = 1;
}
......@@ -449,7 +449,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
if (device->wakeup.flags.valid) {
acpi_disable_gpe(device->wakeup.gpe_device,
device->wakeup.gpe_number,
ACPI_GPE_TYPE_WAKE_RUN);
ACPI_GPE_TYPE_RUNTIME);
device->wakeup.run_wake_count--;
device->wakeup.state.enabled = 0;
}
......
......@@ -347,7 +347,6 @@ static int __init acpi_fan_init(void)
{
int result = 0;
#ifdef CONFIG_ACPI_PROCFS
acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
if (!acpi_fan_dir)
......@@ -356,7 +355,9 @@ static int __init acpi_fan_init(void)
result = acpi_bus_register_driver(&acpi_fan_driver);
if (result < 0) {
#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
#endif
return -ENODEV;
}
......
......@@ -581,6 +581,11 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
return 0;
}
#ifdef CONFIG_SMP
if (pr->id >= setup_max_cpus && pr->id != 0)
return 0;
#endif
BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));
/*
......
......@@ -114,6 +114,8 @@ static int __acpi_pm_prepare(void)
{
int error = acpi_sleep_prepare(acpi_target_sleep_state);
suspend_nvs_save();
if (error)
acpi_target_sleep_state = ACPI_STATE_S0;
return error;
......@@ -143,6 +145,9 @@ static void acpi_pm_finish(void)
{
u32 acpi_state = acpi_target_sleep_state;
suspend_nvs_free();
acpi_ec_unblock_transactions();
if (acpi_state == ACPI_STATE_S0)
return;
......@@ -192,6 +197,11 @@ static int acpi_suspend_begin(suspend_state_t pm_state)
u32 acpi_state = acpi_suspend_states[pm_state];
int error = 0;
error = suspend_nvs_alloc();
if (error)
return error;
if (sleep_states[acpi_state]) {
acpi_target_sleep_state = acpi_state;
acpi_sleep_tts_switch(acpi_target_sleep_state);
......@@ -269,12 +279,13 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
if (acpi_state == ACPI_STATE_S3)
acpi_restore_state_mem();
suspend_nvs_restore();
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
static void acpi_suspend_finish(void)
{
acpi_ec_unblock_transactions();
acpi_pm_finish();
}
......@@ -404,7 +415,7 @@ static int acpi_hibernation_begin(void)
{
int error;
error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
error = s4_no_nvs ? 0 : suspend_nvs_alloc();
if (!error) {
acpi_target_sleep_state = ACPI_STATE_S4;
acpi_sleep_tts_switch(acpi_target_sleep_state);
......@@ -418,7 +429,7 @@ static int acpi_hibernation_pre_snapshot(void)
int error = acpi_pm_prepare();
if (!error)
hibernate_nvs_save();
suspend_nvs_save();
return error;
}
......@@ -441,13 +452,6 @@ static int acpi_hibernation_enter(void)
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
static void acpi_hibernation_finish(void)
{
hibernate_nvs_free();
acpi_ec_unblock_transactions();
acpi_pm_finish();
}
static void acpi_hibernation_leave(void)
{
/*
......@@ -464,7 +468,7 @@ static void acpi_hibernation_leave(void)
panic("ACPI S4 hardware signature mismatch");
}
/* Restore the NVS memory area */
hibernate_nvs_restore();
suspend_nvs_restore();
/* Allow EC transactions to happen. */
acpi_ec_unblock_transactions_early();
}
......@@ -479,7 +483,7 @@ static struct platform_hibernation_ops acpi_hibernation_ops = {
.begin = acpi_hibernation_begin,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot,
.finish = acpi_hibernation_finish,
.finish = acpi_pm_finish,
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
......@@ -507,7 +511,7 @@ static int acpi_hibernation_begin_old(void)
if (!error) {
if (!s4_no_nvs)
error = hibernate_nvs_alloc();
error = suspend_nvs_alloc();
if (!error)
acpi_target_sleep_state = ACPI_STATE_S4;
}
......@@ -517,7 +521,7 @@ static int acpi_hibernation_begin_old(void)
static int acpi_hibernation_pre_snapshot_old(void)
{
acpi_pm_freeze();
hibernate_nvs_save();
suspend_nvs_save();
return 0;
}
......@@ -529,8 +533,8 @@ static struct platform_hibernation_ops acpi_hibernation_ops_old = {
.begin = acpi_hibernation_begin_old,
.end = acpi_pm_end,
.pre_snapshot = acpi_hibernation_pre_snapshot_old,
.finish = acpi_hibernation_finish,
.prepare = acpi_pm_freeze,
.finish = acpi_pm_finish,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
.pre_restore = acpi_pm_freeze,
......
......@@ -388,10 +388,12 @@ static ssize_t counter_set(struct kobject *kobj,
if (index < num_gpes) {
if (!strcmp(buf, "disable\n") &&
(status & ACPI_EVENT_FLAG_ENABLED))
result = acpi_set_gpe(handle, index, ACPI_GPE_DISABLE);
result = acpi_disable_gpe(handle, index,
ACPI_GPE_TYPE_RUNTIME);
else if (!strcmp(buf, "enable\n") &&
!(status & ACPI_EVENT_FLAG_ENABLED))
result = acpi_set_gpe(handle, index, ACPI_GPE_ENABLE);
result = acpi_enable_gpe(handle, index,
ACPI_GPE_TYPE_RUNTIME);
else if (!strcmp(buf, "clear\n") &&
(status & ACPI_EVENT_FLAG_SET))
result = acpi_clear_gpe(handle, index);
......
......@@ -64,16 +64,13 @@ void acpi_enable_wakeup_device(u8 sleep_state)
struct acpi_device *dev =
container_of(node, struct acpi_device, wakeup_list);
if (!dev->wakeup.flags.valid)
continue;
if ((!dev->wakeup.state.enabled && !dev->wakeup.prepare_count)
if (!dev->wakeup.flags.valid || !dev->wakeup.state.enabled
|| sleep_state > (u32) dev->wakeup.sleep_state)
continue;
/* The wake-up power should have been enabled already. */
acpi_set_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
ACPI_GPE_ENABLE);
acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
ACPI_GPE_TYPE_WAKE);
}
}
......@@ -96,6 +93,8 @@ void acpi_disable_wakeup_device(u8 sleep_state)
|| (sleep_state > (u32) dev->wakeup.sleep_state))
continue;
acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
ACPI_GPE_TYPE_WAKE);
acpi_disable_wakeup_device_power(dev);
}
}
......@@ -109,13 +108,8 @@ int __init acpi_wakeup_device_init(void)
struct acpi_device *dev = container_of(node,
struct acpi_device,
wakeup_list);
/* In case user doesn't load button driver */
if (!dev->wakeup.flags.always_enabled ||
dev->wakeup.state.enabled)
continue;
acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number,
ACPI_GPE_TYPE_WAKE);
dev->wakeup.state.enabled = 1;
if (dev->wakeup.flags.always_enabled)
dev->wakeup.state.enabled = 1;
}
mutex_unlock(&acpi_device_lock);
return 0;
......
......@@ -212,7 +212,7 @@ char const *acpi_gbl_exception_names_env[] = {
"AE_NO_GLOBAL_LOCK",
"AE_ABORT_METHOD",
"AE_SAME_HANDLER",
"AE_WAKE_ONLY_GPE",
"AE_NO_HANDLER",
"AE_OWNER_ID_LIMIT"
};
......
......@@ -69,6 +69,7 @@ extern acpi_name acpi_gbl_trace_method_name;
extern u32 acpi_gbl_trace_flags;
extern u8 acpi_gbl_enable_aml_debug_object;
extern u8 acpi_gbl_copy_dsdt_locally;
extern u8 acpi_gbl_truncate_io_addresses;
extern u32 acpi_current_gpe_count;
extern struct acpi_table_fadt acpi_gbl_FADT;
......
......@@ -663,10 +663,11 @@ typedef u32 acpi_event_status;
#define ACPI_GPE_MAX 0xFF
#define ACPI_NUM_GPE 256
/* Actions for acpi_set_gpe */
/* Actions for acpi_set_gpe and acpi_hw_low_set_gpe */
#define ACPI_GPE_ENABLE 0
#define ACPI_GPE_DISABLE 1
#define ACPI_GPE_COND_ENABLE 2
/* gpe_types for acpi_enable_gpe and acpi_disable_gpe */
......
......@@ -256,22 +256,22 @@ static inline int hibernate(void) { return -ENOSYS; }
static inline bool system_entering_hibernation(void) { return false; }
#endif /* CONFIG_HIBERNATION */
#ifdef CONFIG_HIBERNATION_NVS
extern int hibernate_nvs_register(unsigned long start, unsigned long size);
extern int hibernate_nvs_alloc(void);
extern void hibernate_nvs_free(void);
extern void hibernate_nvs_save(void);
extern void hibernate_nvs_restore(void);
#else /* CONFIG_HIBERNATION_NVS */
static inline int hibernate_nvs_register(unsigned long a, unsigned long b)
#ifdef CONFIG_SUSPEND_NVS
extern int suspend_nvs_register(unsigned long start, unsigned long size);
extern int suspend_nvs_alloc(void);
extern void suspend_nvs_free(void);
extern void suspend_nvs_save(void);
extern void suspend_nvs_restore(void);
#else /* CONFIG_SUSPEND_NVS */
static inline int suspend_nvs_register(unsigned long a, unsigned long b)
{
return 0;
}
static inline int hibernate_nvs_alloc(void) { return 0; }
static inline void hibernate_nvs_free(void) {}
static inline void hibernate_nvs_save(void) {}
static inline void hibernate_nvs_restore(void) {}
#endif /* CONFIG_HIBERNATION_NVS */
static inline int suspend_nvs_alloc(void) { return 0; }
static inline void suspend_nvs_free(void) {}
static inline void suspend_nvs_save(void) {}
static inline void suspend_nvs_restore(void) {}
#endif /* CONFIG_SUSPEND_NVS */
#ifdef CONFIG_PM_SLEEP
void save_processor_state(void);
......
......@@ -125,7 +125,9 @@ static char *ramdisk_execute_command;
#ifdef CONFIG_SMP
/* Setup configured maximum number of CPUs to activate */
unsigned int __initdata setup_max_cpus = NR_CPUS;
unsigned int setup_max_cpus = NR_CPUS;
EXPORT_SYMBOL(setup_max_cpus);
/*
* Setup routine for controlling SMP activation
......
......@@ -99,9 +99,13 @@ config PM_SLEEP_ADVANCED_DEBUG
depends on PM_ADVANCED_DEBUG
default n
config SUSPEND_NVS
bool
config SUSPEND
bool "Suspend to RAM and standby"
depends on PM && ARCH_SUSPEND_POSSIBLE
select SUSPEND_NVS if HAS_IOMEM
default y
---help---
Allow the system to enter sleep states in which main memory is
......@@ -130,13 +134,10 @@ config SUSPEND_FREEZER
Turning OFF this setting is NOT recommended! If in doubt, say Y.
config HIBERNATION_NVS
bool
config HIBERNATION
bool "Hibernation (aka 'suspend to disk')"
depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
select HIBERNATION_NVS if HAS_IOMEM
select SUSPEND_NVS if HAS_IOMEM
---help---
Enable the suspend to disk (STD) functionality, which is usually
called "hibernation" in user interfaces. STD checkpoints the
......
......@@ -10,6 +10,6 @@ obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o
obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o user.o \
block_io.o
obj-$(CONFIG_HIBERNATION_NVS) += hibernate_nvs.o
obj-$(CONFIG_SUSPEND_NVS) += nvs.o
obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
......@@ -15,7 +15,7 @@
/*
* Platforms, like ACPI, may want us to save some memory used by them during
* hibernation and to restore the contents of this memory during the subsequent
* suspend and to restore the contents of this memory during the subsequent
* resume. The code below implements a mechanism allowing us to do that.
*/
......@@ -30,7 +30,7 @@ struct nvs_page {
static LIST_HEAD(nvs_list);
/**
* hibernate_nvs_register - register platform NVS memory region to save
* suspend_nvs_register - register platform NVS memory region to save
* @start - physical address of the region
* @size - size of the region
*
......@@ -38,7 +38,7 @@ static LIST_HEAD(nvs_list);
* things so that the data from page-aligned addresses in this region will
* be copied into separate RAM pages.
*/
int hibernate_nvs_register(unsigned long start, unsigned long size)
int suspend_nvs_register(unsigned long start, unsigned long size)
{
struct nvs_page *entry, *next;
......@@ -68,9 +68,9 @@ int hibernate_nvs_register(unsigned long start, unsigned long size)
}
/**
* hibernate_nvs_free - free data pages allocated for saving NVS regions
* suspend_nvs_free - free data pages allocated for saving NVS regions
*/
void hibernate_nvs_free(void)
void suspend_nvs_free(void)
{
struct nvs_page *entry;
......@@ -86,16 +86,16 @@ void hibernate_nvs_free(void)
}
/**
* hibernate_nvs_alloc - allocate memory necessary for saving NVS regions
* suspend_nvs_alloc - allocate memory necessary for saving NVS regions
*/
int hibernate_nvs_alloc(void)
int suspend_nvs_alloc(void)
{
struct nvs_page *entry;
list_for_each_entry(entry, &nvs_list, node) {
entry->data = (void *)__get_free_page(GFP_KERNEL);
if (!entry->data) {
hibernate_nvs_free();
suspend_nvs_free();
return -ENOMEM;
}
}
......@@ -103,9 +103,9 @@ int hibernate_nvs_alloc(void)
}
/**
* hibernate_nvs_save - save NVS memory regions
* suspend_nvs_save - save NVS memory regions
*/
void hibernate_nvs_save(void)
void suspend_nvs_save(void)
{
struct nvs_page *entry;
......@@ -119,12 +119,12 @@ void hibernate_nvs_save(void)
}
/**
* hibernate_nvs_restore - restore NVS memory regions
* suspend_nvs_restore - restore NVS memory regions
*
* This function is going to be called with interrupts disabled, so it
* cannot iounmap the virtual addresses used to access the NVS region.
*/
void hibernate_nvs_restore(void)
void suspend_nvs_restore(void)
{
struct nvs_page *entry;
......
......@@ -16,6 +16,12 @@
#include <linux/cpu.h>
#include <linux/syscalls.h>
#include <linux/gfp.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/suspend.h>
#include "power.h"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册