Merge branches 'idle-fix' and 'misc' into release

This commit is contained in:
Len Brown 2012-04-06 21:48:59 -04:00
commit eeaab2d8af
10325 changed files with 498938 additions and 290093 deletions

View file

@ -384,6 +384,15 @@ config ACPI_CUSTOM_METHOD
load additional kernel modules after boot, this feature may be used
to override that restriction).
config ACPI_BGRT
tristate "Boottime Graphics Resource Table support"
default n
help
This driver adds support for exposing the ACPI Boottime Graphics
Resource Table, which allows the operating system to obtain
data from the firmware boot splash. It will appear under
/sys/firmware/acpi/bgrt/ .
source "drivers/acpi/apei/Kconfig"
endif # ACPI

View file

@ -62,6 +62,7 @@ obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_HED) += hed.o
obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
obj-$(CONFIG_ACPI_BGRT) += bgrt.o
# processor has its own "processor." module_param namespace
processor-y := processor_driver.o processor_throttling.o

View file

@ -68,12 +68,14 @@ acpi-y += \
acpi-y += \
hwacpi.o \
hwesleep.o \
hwgpe.o \
hwpci.o \
hwregs.o \
hwsleep.o \
hwvalid.o \
hwxface.o
hwxface.o \
hwxfsleep.o
acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o

View file

@ -51,7 +51,6 @@
*
* Note: The order of these include files is important.
*/
#include "acconfig.h" /* Global configuration constants */
#include "acmacros.h" /* C macros */
#include "aclocal.h" /* Internal data types */
#include "acobject.h" /* ACPI internal object */

View file

@ -1,231 +0,0 @@
/******************************************************************************
*
* Name: acconfig.h - Global configuration constants
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2012, Intel Corp.
* 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.
*/
#ifndef _ACCONFIG_H
#define _ACCONFIG_H
/******************************************************************************
*
* Configuration options
*
*****************************************************************************/
/*
* ACPI_DEBUG_OUTPUT - This switch enables all the debug facilities of the
* ACPI subsystem. This includes the DEBUG_PRINT output
* statements. When disabled, all DEBUG_PRINT
* statements are compiled out.
*
* ACPI_APPLICATION - Use this switch if the subsystem is going to be run
* at the application level.
*
*/
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
* but there is a large base of ASL/AML code in existing machines that check
* for the string below. The use of this string usually guarantees that
* the ASL will execute down the most tested code path. Also, there is some
* code that will not execute the _OSI method unless _OS matches the string
* below. Therefore, change this string at your own risk.
*/
#define ACPI_OS_NAME "Microsoft Windows NT"
/* Maximum objects in the various object caches */
#define ACPI_MAX_STATE_CACHE_DEPTH 96 /* State objects */
#define ACPI_MAX_PARSE_CACHE_DEPTH 96 /* Parse tree objects */
#define ACPI_MAX_EXTPARSE_CACHE_DEPTH 96 /* Parse tree objects */
#define ACPI_MAX_OBJECT_CACHE_DEPTH 96 /* Interpreter operand objects */
#define ACPI_MAX_NAMESPACE_CACHE_DEPTH 96 /* Namespace objects */
/*
* Should the subsystem abort the loading of an ACPI table if the
* table checksum is incorrect?
*/
#define ACPI_CHECKSUM_ABORT FALSE
/******************************************************************************
*
* Subsystem Constants
*
*****************************************************************************/
/* Version of ACPI supported */
#define ACPI_CA_SUPPORT_LEVEL 3
/* Maximum count for a semaphore object */
#define ACPI_MAX_SEMAPHORE_COUNT 256
/* Maximum object reference count (detects object deletion issues) */
#define ACPI_MAX_REFERENCE_COUNT 0x1000
/* Default page size for use in mapping memory for operation regions */
#define ACPI_DEFAULT_PAGE_SIZE 4096 /* Must be power of 2 */
/* owner_id tracking. 8 entries allows for 255 owner_ids */
#define ACPI_NUM_OWNERID_MASKS 8
/* Size of the root table array is increased by this increment */
#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4
/* Maximum number of While() loop iterations before forced abort */
#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF
/* Maximum sleep allowed via Sleep() operator */
#define ACPI_MAX_SLEEP 2000 /* Two seconds */
/* Address Range lists are per-space_id (Memory and I/O only) */
#define ACPI_ADDRESS_RANGE_MAX 2
/******************************************************************************
*
* ACPI Specification constants (Do not change unless the specification changes)
*
*****************************************************************************/
/* Number of distinct GPE register blocks and register width */
#define ACPI_MAX_GPE_BLOCKS 2
#define ACPI_GPE_REGISTER_WIDTH 8
/* Method info (in WALK_STATE), containing local variables and argumetns */
#define ACPI_METHOD_NUM_LOCALS 8
#define ACPI_METHOD_MAX_LOCAL 7
#define ACPI_METHOD_NUM_ARGS 7
#define ACPI_METHOD_MAX_ARG 6
/* Length of _HID, _UID, _CID, and UUID values */
#define ACPI_DEVICE_ID_LENGTH 0x09
#define ACPI_MAX_CID_LENGTH 48
#define ACPI_UUID_LENGTH 16
/*
* Operand Stack (in WALK_STATE), Must be large enough to contain METHOD_MAX_ARG
*/
#define ACPI_OBJ_NUM_OPERANDS 8
#define ACPI_OBJ_MAX_OPERAND 7
/* Number of elements in the Result Stack frame, can be an arbitrary value */
#define ACPI_RESULTS_FRAME_OBJ_NUM 8
/*
* Maximal number of elements the Result Stack can contain,
* it may be an arbitray value not exceeding the types of
* result_size and result_count (now u8).
*/
#define ACPI_RESULTS_OBJ_NUM_MAX 255
/* Names within the namespace are 4 bytes long */
#define ACPI_NAME_SIZE 4
#define ACPI_PATH_SEGMENT_LENGTH 5 /* 4 chars for name + 1 char for separator */
#define ACPI_PATH_SEPARATOR '.'
/* Sizes for ACPI table headers */
#define ACPI_OEM_ID_SIZE 6
#define ACPI_OEM_TABLE_ID_SIZE 8
/* Constants used in searching for the RSDP in low memory */
#define ACPI_EBDA_PTR_LOCATION 0x0000040E /* Physical Address */
#define ACPI_EBDA_PTR_LENGTH 2
#define ACPI_EBDA_WINDOW_SIZE 1024
#define ACPI_HI_RSDP_WINDOW_BASE 0x000E0000 /* Physical Address */
#define ACPI_HI_RSDP_WINDOW_SIZE 0x00020000
#define ACPI_RSDP_SCAN_STEP 16
/* Operation regions */
#define ACPI_USER_REGION_BEGIN 0x80
/* Maximum space_ids for Operation Regions */
#define ACPI_MAX_ADDRESS_SPACE 255
/* Array sizes. Used for range checking also */
#define ACPI_MAX_MATCH_OPCODE 5
/* RSDP checksums */
#define ACPI_RSDP_CHECKSUM_LENGTH 20
#define ACPI_RSDP_XCHECKSUM_LENGTH 36
/* SMBus, GSBus and IPMI bidirectional buffer size */
#define ACPI_SMBUS_BUFFER_SIZE 34
#define ACPI_GSBUS_BUFFER_SIZE 34
#define ACPI_IPMI_BUFFER_SIZE 66
/* _sx_d and _sx_w control methods */
#define ACPI_NUM_sx_d_METHODS 4
#define ACPI_NUM_sx_w_METHODS 5
/******************************************************************************
*
* ACPI AML Debugger
*
*****************************************************************************/
#define ACPI_DEBUGGER_MAX_ARGS 8 /* Must be max method args + 1 */
#define ACPI_DEBUGGER_COMMAND_PROMPT '-'
#define ACPI_DEBUGGER_EXECUTE_PROMPT '%'
#endif /* _ACCONFIG_H */

View file

@ -111,7 +111,7 @@ acpi_status acpi_db_find_name_in_namespace(char *name_arg);
void acpi_db_set_scope(char *name);
acpi_status acpi_db_sleep(char *object_arg);
ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_db_sleep(char *object_arg))
void acpi_db_find_references(char *object_arg);
@ -119,11 +119,13 @@ void acpi_db_display_locks(void);
void acpi_db_display_resources(char *object_arg);
void acpi_db_display_gpes(void);
ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void))
void acpi_db_check_integrity(void);
void acpi_db_generate_gpe(char *gpe_arg, char *block_arg);
ACPI_HW_DEPENDENT_RETURN_VOID(void
acpi_db_generate_gpe(char *gpe_arg,
char *block_arg))
void acpi_db_check_predefined_names(void);

View file

@ -69,11 +69,10 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node *node,
*/
acpi_status acpi_ev_init_global_lock_handler(void);
acpi_status acpi_ev_acquire_global_lock(u16 timeout);
acpi_status acpi_ev_release_global_lock(void);
acpi_status acpi_ev_remove_global_lock_handler(void);
ACPI_HW_DEPENDENT_RETURN_OK(acpi_status
acpi_ev_acquire_global_lock(u16 timeout))
ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void))
acpi_status acpi_ev_remove_global_lock_handler(void);
/*
* evgpe - Low-level GPE support
@ -114,7 +113,9 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *context);
acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block);
ACPI_HW_DEPENDENT_RETURN_OK(acpi_status
acpi_ev_delete_gpe_block(struct acpi_gpe_block_info
*gpe_block))
u32
acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
@ -126,9 +127,10 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
*/
acpi_status acpi_ev_gpe_initialize(void);
void acpi_ev_update_gpes(acpi_owner_id table_owner_id);
ACPI_HW_DEPENDENT_RETURN_VOID(void
acpi_ev_update_gpes(acpi_owner_id table_owner_id))
acpi_status
acpi_status
acpi_ev_match_gpe_method(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
@ -237,6 +239,5 @@ acpi_status acpi_ev_remove_sci_handler(void);
u32 acpi_ev_initialize_sCI(u32 program_sCI);
void acpi_ev_terminate(void);
ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void))
#endif /* __ACEVENTS_H__ */

View file

@ -147,7 +147,7 @@ u8 acpi_gbl_system_awake_and_running;
*/
u8 acpi_gbl_reduced_hardware;
#endif
#endif /* DEFINE_ACPI_GLOBALS */
/* Do not disassemble buffers to resource descriptors */
@ -184,8 +184,12 @@ ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
* found in the RSDT/XSDT.
*/
ACPI_EXTERN struct acpi_table_list acpi_gbl_root_table_list;
#if (!ACPI_REDUCED_HARDWARE)
ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS;
#endif /* !ACPI_REDUCED_HARDWARE */
/* These addresses are calculated from the FADT Event Block addresses */
ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_status;
@ -397,10 +401,15 @@ ACPI_EXTERN struct acpi_fixed_event_handler
ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
ACPI_EXTERN struct acpi_gpe_block_info
*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
#if (!ACPI_REDUCED_HARDWARE)
ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized;
ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler;
ACPI_EXTERN void *acpi_gbl_global_event_handler_context;
#endif /* !ACPI_REDUCED_HARDWARE */
/*****************************************************************************
*
* Debugger globals

View file

@ -80,6 +80,26 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value);
acpi_status acpi_hw_clear_acpi_status(void);
/*
* hwsleep - sleep/wake support (Legacy sleep registers)
*/
acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags);
acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags);
acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags);
/*
* hwesleep - sleep/wake support (Extended FADT-V5 sleep registers)
*/
void acpi_hw_execute_sleep_method(char *method_name, u32 integer_argument);
acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags);
acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags);
acpi_status acpi_hw_extended_wake(u8 sleep_state, u8 flags);
/*
* hwvalid - Port I/O with validation
*/
@ -128,16 +148,4 @@ acpi_status
acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
acpi_handle root_pci_device, acpi_handle pci_region);
#ifdef ACPI_FUTURE_USAGE
/*
* hwtimer - ACPI Timer prototypes
*/
acpi_status acpi_get_timer_resolution(u32 * resolution);
acpi_status acpi_get_timer(u32 * ticks);
acpi_status
acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed);
#endif /* ACPI_FUTURE_USAGE */
#endif /* __ACHWARE_H__ */

View file

@ -370,6 +370,7 @@ struct acpi_predefined_data {
/* Defines for Flags field above */
#define ACPI_OBJECT_REPAIRED 1
#define ACPI_OBJECT_WRAPPED 2
/*
* Bitmapped return value types

View file

@ -516,6 +516,12 @@
#endif /* ACPI_DEBUG_OUTPUT */
#if (!ACPI_REDUCED_HARDWARE)
#define ACPI_HW_OPTIONAL_FUNCTION(addr) addr
#else
#define ACPI_HW_OPTIONAL_FUNCTION(addr) NULL
#endif
/*
* Some code only gets executed when the debugger is built in.
* Note that this is entirely independent of whether the

View file

@ -283,8 +283,9 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
union acpi_operand_object **return_object_ptr);
acpi_status
acpi_ns_repair_package_list(struct acpi_predefined_data *data,
union acpi_operand_object **obj_desc_ptr);
acpi_ns_wrap_with_package(struct acpi_predefined_data *data,
union acpi_operand_object *original_object,
union acpi_operand_object **obj_desc_ptr);
acpi_status
acpi_ns_repair_null_element(struct acpi_predefined_data *data,

View file

@ -67,6 +67,11 @@ acpi_status acpi_tb_resize_root_table_list(void);
acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc);
struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
*table_header,
struct acpi_table_desc
*table_desc);
acpi_status
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index);

View file

@ -47,7 +47,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evevent")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static acpi_status acpi_ev_fixed_event_initialize(void);
@ -291,3 +291,5 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
return ((acpi_gbl_fixed_event_handlers[event].
handler) (acpi_gbl_fixed_event_handlers[event].context));
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -48,7 +48,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evglock")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static u32 acpi_ev_global_lock_handler(void *context);
@ -339,3 +339,5 @@ acpi_status acpi_ev_release_global_lock(void)
acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex);
return_ACPI_STATUS(status);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -48,7 +48,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpe")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
@ -766,3 +766,5 @@ acpi_ev_gpe_dispatch(struct acpi_namespace_node *gpe_device,
return_UINT32(ACPI_INTERRUPT_HANDLED);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -48,7 +48,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpeblk")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static acpi_status
acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
@ -504,3 +504,5 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
return_ACPI_STATUS(AE_OK);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -48,7 +48,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpeinit")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*
* Note: History of _PRW support in ACPICA
*
@ -440,3 +440,5 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
name, gpe_number));
return_ACPI_STATUS(AE_OK);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -48,6 +48,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpeutil")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*******************************************************************************
*
* FUNCTION: acpi_ev_walk_gpe_list
@ -374,3 +375,5 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
return_ACPI_STATUS(AE_OK);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -108,27 +108,30 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
ACPI_FUNCTION_NAME(ev_queue_notify_request);
/*
* For value 3 (Ejection Request), some device method may need to be run.
* For value 2 (Device Wake) if _PRW exists, the _PS0 method may need
* to be run.
* For value 0x03 (Ejection Request), may need to run a device method.
* For value 0x02 (Device Wake), if _PRW exists, may need to run
* the _PS0 method.
* For value 0x80 (Status Change) on the power button or sleep button,
* initiate soft-off or sleep operation?
* initiate soft-off or sleep operation.
*
* For all cases, simply dispatch the notify to the handler.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n",
acpi_ut_get_node_name(node), node, notify_value,
acpi_ut_get_notify_name(notify_value)));
"Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
acpi_ut_get_node_name(node),
acpi_ut_get_type_name(node->type), notify_value,
acpi_ut_get_notify_name(notify_value), node));
/* Get the notify object attached to the NS Node */
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/* We have the notify object, Get the right handler */
/* We have the notify object, Get the correct handler */
switch (node->type) {
/* Notify allowed only on these types */
/* Notify is allowed only on these types */
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_THERMAL:
@ -152,7 +155,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
}
/*
* If there is any handler to run, schedule the dispatcher.
* If there is a handler to run, schedule the dispatcher.
* Check for:
* 1) Global system notify handler
* 2) Global device notify handler
@ -270,6 +273,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
acpi_ut_delete_generic_state(notify_info);
}
#if (!ACPI_REDUCED_HARDWARE)
/******************************************************************************
*
* FUNCTION: acpi_ev_terminate
@ -338,3 +342,5 @@ void acpi_ev_terminate(void)
}
return_VOID;
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -48,7 +48,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evsci")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
@ -181,3 +181,5 @@ acpi_status acpi_ev_remove_sci_handler(void)
return_ACPI_STATUS(status);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -51,222 +51,6 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evxface")
/*******************************************************************************
*
* FUNCTION: acpi_install_exception_handler
*
* PARAMETERS: Handler - Pointer to the handler function for the
* event
*
* RETURN: Status
*
* DESCRIPTION: Saves the pointer to the handler function
*
******************************************************************************/
#ifdef ACPI_FUTURE_USAGE
acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
if (acpi_gbl_exception_handler) {
status = AE_ALREADY_EXISTS;
goto cleanup;
}
/* Install the handler */
acpi_gbl_exception_handler = handler;
cleanup:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
#endif /* ACPI_FUTURE_USAGE */
/*******************************************************************************
*
* FUNCTION: acpi_install_global_event_handler
*
* PARAMETERS: Handler - Pointer to the global event handler function
* Context - Value passed to the handler on each event
*
* RETURN: Status
*
* DESCRIPTION: Saves the pointer to the handler function. The global handler
* is invoked upon each incoming GPE and Fixed Event. It is
* invoked at interrupt level at the time of the event dispatch.
* Can be used to update event counters, etc.
*
******************************************************************************/
acpi_status
acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);
/* Parameter validation */
if (!handler) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
if (acpi_gbl_global_event_handler) {
status = AE_ALREADY_EXISTS;
goto cleanup;
}
acpi_gbl_global_event_handler = handler;
acpi_gbl_global_event_handler_context = context;
cleanup:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)
/*******************************************************************************
*
* FUNCTION: acpi_install_fixed_event_handler
*
* PARAMETERS: Event - Event type to enable.
* Handler - Pointer to the handler function for the
* event
* Context - Value passed to the handler on each GPE
*
* RETURN: Status
*
* DESCRIPTION: Saves the pointer to the handler function and then enables the
* event.
*
******************************************************************************/
acpi_status
acpi_install_fixed_event_handler(u32 event,
acpi_event_handler handler, void *context)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
/* Parameter validation */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
status = AE_ALREADY_EXISTS;
goto cleanup;
}
/* Install the handler before enabling the event */
acpi_gbl_fixed_event_handlers[event].handler = handler;
acpi_gbl_fixed_event_handlers[event].context = context;
status = acpi_clear_event(event);
if (ACPI_SUCCESS(status))
status = acpi_enable_event(event, 0);
if (ACPI_FAILURE(status)) {
ACPI_WARNING((AE_INFO, "Could not enable fixed event 0x%X",
event));
/* Remove the handler */
acpi_gbl_fixed_event_handlers[event].handler = NULL;
acpi_gbl_fixed_event_handlers[event].context = NULL;
} else {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Enabled fixed event %X, Handler=%p\n", event,
handler));
}
cleanup:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
/*******************************************************************************
*
* FUNCTION: acpi_remove_fixed_event_handler
*
* PARAMETERS: Event - Event type to disable.
* Handler - Address of the handler
*
* RETURN: Status
*
* DESCRIPTION: Disables the event and unregisters the event handler.
*
******************************************************************************/
acpi_status
acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
/* Parameter validation */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Disable the event before removing the handler */
status = acpi_disable_event(event, 0);
/* Always Remove the handler */
acpi_gbl_fixed_event_handlers[event].handler = NULL;
acpi_gbl_fixed_event_handlers[event].context = NULL;
if (ACPI_FAILURE(status)) {
ACPI_WARNING((AE_INFO,
"Could not write to fixed event enable register 0x%X",
event));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
event));
}
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
/*******************************************************************************
*
@ -334,6 +118,7 @@ acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj,
return AE_OK;
}
/*******************************************************************************
*
* FUNCTION: acpi_install_notify_handler
@ -703,6 +488,224 @@ acpi_remove_notify_handler(acpi_handle device,
ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)
/*******************************************************************************
*
* FUNCTION: acpi_install_exception_handler
*
* PARAMETERS: Handler - Pointer to the handler function for the
* event
*
* RETURN: Status
*
* DESCRIPTION: Saves the pointer to the handler function
*
******************************************************************************/
#ifdef ACPI_FUTURE_USAGE
acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
if (acpi_gbl_exception_handler) {
status = AE_ALREADY_EXISTS;
goto cleanup;
}
/* Install the handler */
acpi_gbl_exception_handler = handler;
cleanup:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
#endif /* ACPI_FUTURE_USAGE */
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
* FUNCTION: acpi_install_global_event_handler
*
* PARAMETERS: Handler - Pointer to the global event handler function
* Context - Value passed to the handler on each event
*
* RETURN: Status
*
* DESCRIPTION: Saves the pointer to the handler function. The global handler
* is invoked upon each incoming GPE and Fixed Event. It is
* invoked at interrupt level at the time of the event dispatch.
* Can be used to update event counters, etc.
*
******************************************************************************/
acpi_status
acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);
/* Parameter validation */
if (!handler) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
if (acpi_gbl_global_event_handler) {
status = AE_ALREADY_EXISTS;
goto cleanup;
}
acpi_gbl_global_event_handler = handler;
acpi_gbl_global_event_handler_context = context;
cleanup:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)
/*******************************************************************************
*
* FUNCTION: acpi_install_fixed_event_handler
*
* PARAMETERS: Event - Event type to enable.
* Handler - Pointer to the handler function for the
* event
* Context - Value passed to the handler on each GPE
*
* RETURN: Status
*
* DESCRIPTION: Saves the pointer to the handler function and then enables the
* event.
*
******************************************************************************/
acpi_status
acpi_install_fixed_event_handler(u32 event,
acpi_event_handler handler, void *context)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
/* Parameter validation */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Don't allow two handlers. */
if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
status = AE_ALREADY_EXISTS;
goto cleanup;
}
/* Install the handler before enabling the event */
acpi_gbl_fixed_event_handlers[event].handler = handler;
acpi_gbl_fixed_event_handlers[event].context = context;
status = acpi_clear_event(event);
if (ACPI_SUCCESS(status))
status = acpi_enable_event(event, 0);
if (ACPI_FAILURE(status)) {
ACPI_WARNING((AE_INFO, "Could not enable fixed event 0x%X",
event));
/* Remove the handler */
acpi_gbl_fixed_event_handlers[event].handler = NULL;
acpi_gbl_fixed_event_handlers[event].context = NULL;
} else {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Enabled fixed event %X, Handler=%p\n", event,
handler));
}
cleanup:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
/*******************************************************************************
*
* FUNCTION: acpi_remove_fixed_event_handler
*
* PARAMETERS: Event - Event type to disable.
* Handler - Address of the handler
*
* RETURN: Status
*
* DESCRIPTION: Disables the event and unregisters the event handler.
*
******************************************************************************/
acpi_status
acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
{
acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
/* Parameter validation */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Disable the event before removing the handler */
status = acpi_disable_event(event, 0);
/* Always Remove the handler */
acpi_gbl_fixed_event_handlers[event].handler = NULL;
acpi_gbl_fixed_event_handlers[event].context = NULL;
if (ACPI_FAILURE(status)) {
ACPI_WARNING((AE_INFO,
"Could not write to fixed event enable register 0x%X",
event));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
event));
}
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
/*******************************************************************************
*
* FUNCTION: acpi_install_gpe_handler
@ -984,3 +987,4 @@ acpi_status acpi_release_global_lock(u32 handle)
}
ACPI_EXPORT_SYMBOL(acpi_release_global_lock)
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -49,6 +49,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evxfevnt")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*******************************************************************************
*
* FUNCTION: acpi_enable
@ -352,3 +353,4 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
}
ACPI_EXPORT_SYMBOL(acpi_get_event_status)
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -50,6 +50,7 @@
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evxfgpe")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/******************************************************************************
*
* FUNCTION: acpi_update_all_gpes
@ -695,3 +696,4 @@ acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
}
ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -48,6 +48,7 @@
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwacpi")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/******************************************************************************
*
* FUNCTION: acpi_hw_set_mode
@ -166,3 +167,5 @@ u32 acpi_hw_get_mode(void)
return_UINT32(ACPI_SYS_MODE_LEGACY);
}
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -0,0 +1,247 @@
/******************************************************************************
*
* Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the
* extended FADT-V5 sleep registers.
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2012, Intel Corp.
* 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 <acpi/acpi.h>
#include "accommon.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwesleep")
/*******************************************************************************
*
* FUNCTION: acpi_hw_execute_sleep_method
*
* PARAMETERS: method_pathname - Pathname of method to execute
* integer_argument - Argument to pass to the method
*
* RETURN: None
*
* DESCRIPTION: Execute a sleep/wake related method with one integer argument
* and no return value.
*
******************************************************************************/
void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument)
{
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status;
ACPI_FUNCTION_TRACE(hw_execute_sleep_method);
/* One argument, integer_argument; No return value expected */
arg_list.count = 1;
arg_list.pointer = &arg;
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = (u64)integer_argument;
status = acpi_evaluate_object(NULL, method_pathname, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
ACPI_EXCEPTION((AE_INFO, status, "While executing method %s",
method_pathname));
}
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_extended_sleep
*
* PARAMETERS: sleep_state - Which sleep state to enter
* Flags - ACPI_EXECUTE_GTS to run optional method
*
* RETURN: Status
*
* DESCRIPTION: Enter a system sleep state via the extended FADT sleep
* registers (V5 FADT).
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
******************************************************************************/
acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags)
{
acpi_status status;
u8 sleep_type_value;
u64 sleep_status;
ACPI_FUNCTION_TRACE(hw_extended_sleep);
/* Extended sleep registers must be valid */
if (!acpi_gbl_FADT.sleep_control.address ||
!acpi_gbl_FADT.sleep_status.address) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Clear wake status (WAK_STS) */
status = acpi_write(ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
acpi_gbl_system_awake_and_running = FALSE;
/* Optionally execute _GTS (Going To Sleep) */
if (flags & ACPI_EXECUTE_GTS) {
acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state);
}
/* Flush caches, as per ACPI specification */
ACPI_FLUSH_CPU_CACHE();
/*
* Set the SLP_TYP and SLP_EN bits.
*
* Note: We only use the first value returned by the \_Sx method
* (acpi_gbl_sleep_type_a) - As per ACPI specification.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
"Entering sleep state [S%u]\n", sleep_state));
sleep_type_value =
((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
ACPI_X_SLEEP_TYPE_MASK);
status = acpi_write((sleep_type_value | ACPI_X_SLEEP_ENABLE),
&acpi_gbl_FADT.sleep_control);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Wait for transition back to Working State */
do {
status = acpi_read(&sleep_status, &acpi_gbl_FADT.sleep_status);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} while (!(((u8)sleep_status) & ACPI_X_WAKE_STATUS));
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_extended_wake_prep
*
* PARAMETERS: sleep_state - Which sleep state we just exited
* Flags - ACPI_EXECUTE_BFS to run optional method
*
* RETURN: Status
*
* DESCRIPTION: Perform first part of OS-independent ACPI cleanup after
* a sleep. Called with interrupts ENABLED.
*
******************************************************************************/
acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags)
{
acpi_status status;
u8 sleep_type_value;
ACPI_FUNCTION_TRACE(hw_extended_wake_prep);
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_value =
((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
ACPI_X_SLEEP_TYPE_MASK);
(void)acpi_write((sleep_type_value | ACPI_X_SLEEP_ENABLE),
&acpi_gbl_FADT.sleep_control);
}
/* Optionally execute _BFS (Back From Sleep) */
if (flags & ACPI_EXECUTE_BFS) {
acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state);
}
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_extended_wake
*
* PARAMETERS: sleep_state - Which sleep state we just exited
* Flags - Reserved, set to zero
*
* RETURN: Status
*
* DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
* Called with interrupts ENABLED.
*
******************************************************************************/
acpi_status acpi_hw_extended_wake(u8 sleep_state, u8 flags)
{
ACPI_FUNCTION_TRACE(hw_extended_wake);
/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
/* Execute the wake methods */
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);
acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);
/*
* Some BIOS code assumes that WAK_STS will be cleared on resume
* and use it to determine whether the system is rebooting or
* resuming. Clear WAK_STS for compatibility.
*/
(void)acpi_write(ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
acpi_gbl_system_awake_and_running = TRUE;
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
return_ACPI_STATUS(AE_OK);
}

View file

@ -48,7 +48,7 @@
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwgpe")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/* Local prototypes */
static acpi_status
acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
@ -479,3 +479,5 @@ acpi_status acpi_hw_enable_all_wakeup_gpes(void)
status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
return_ACPI_STATUS(status);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -51,6 +51,7 @@
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwregs")
#if (!ACPI_REDUCED_HARDWARE)
/* Local Prototypes */
static acpi_status
acpi_hw_read_multiple(u32 *value,
@ -62,6 +63,8 @@ acpi_hw_write_multiple(u32 value,
struct acpi_generic_address *register_a,
struct acpi_generic_address *register_b);
#endif /* !ACPI_REDUCED_HARDWARE */
/******************************************************************************
*
* FUNCTION: acpi_hw_validate_register
@ -154,6 +157,7 @@ acpi_hw_validate_register(struct acpi_generic_address *reg,
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
{
u64 address;
u64 value64;
acpi_status status;
ACPI_FUNCTION_NAME(hw_read);
@ -175,7 +179,9 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_read_memory((acpi_physical_address)
address, value, reg->bit_width);
address, &value64, reg->bit_width);
*value = (u32)value64;
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_read_port((acpi_io_address)
@ -225,7 +231,8 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_write_memory((acpi_physical_address)
address, value, reg->bit_width);
address, (u64)value,
reg->bit_width);
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_write_port((acpi_io_address)
@ -240,6 +247,7 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
return (status);
}
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
* FUNCTION: acpi_hw_clear_acpi_status
@ -285,7 +293,7 @@ exit:
/*******************************************************************************
*
* FUNCTION: acpi_hw_get_register_bit_mask
* FUNCTION: acpi_hw_get_bit_register_info
*
* PARAMETERS: register_id - Index of ACPI Register to access
*
@ -658,3 +666,5 @@ acpi_hw_write_multiple(u32 value,
return (status);
}
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -1,7 +1,7 @@
/******************************************************************************
*
* Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
* Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the
* original/legacy sleep/PM registers.
*
*****************************************************************************/
@ -43,213 +43,37 @@
*/
#include <acpi/acpi.h>
#include <linux/acpi.h>
#include "accommon.h"
#include "actables.h"
#include <linux/tboot.h>
#include <linux/module.h>
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwsleep")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/*******************************************************************************
*
* FUNCTION: acpi_set_firmware_waking_vector
*
* PARAMETERS: physical_address - 32-bit physical address of ACPI real mode
* entry point.
*
* RETURN: Status
*
* DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS
*
******************************************************************************/
acpi_status
acpi_set_firmware_waking_vector(u32 physical_address)
{
ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
/*
* According to the ACPI specification 2.0c and later, the 64-bit
* waking vector should be cleared and the 32-bit waking vector should
* be used, unless we want the wake-up code to be called by the BIOS in
* Protected Mode. Some systems (for example HP dv5-1004nr) are known
* to fail to resume if the 64-bit vector is used.
*/
/* Set the 32-bit vector */
acpi_gbl_FACS->firmware_waking_vector = physical_address;
/* Clear the 64-bit vector if it exists */
if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) {
acpi_gbl_FACS->xfirmware_waking_vector = 0;
}
return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
#if ACPI_MACHINE_WIDTH == 64
/*******************************************************************************
*
* FUNCTION: acpi_set_firmware_waking_vector64
*
* PARAMETERS: physical_address - 64-bit physical address of ACPI protected
* mode entry point.
*
* RETURN: Status
*
* DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if
* it exists in the table. This function is intended for use with
* 64-bit host operating systems.
*
******************************************************************************/
acpi_status
acpi_set_firmware_waking_vector64(u64 physical_address)
{
ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64);
/* Determine if the 64-bit vector actually exists */
if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Clear 32-bit vector, set the 64-bit X_ vector */
acpi_gbl_FACS->firmware_waking_vector = 0;
acpi_gbl_FACS->xfirmware_waking_vector = physical_address;
return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64)
#endif
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state_prep
* FUNCTION: acpi_hw_legacy_sleep
*
* PARAMETERS: sleep_state - Which sleep state to enter
* Flags - ACPI_EXECUTE_GTS to run optional method
*
* 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 method */
status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &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.
* _SST is an optional method (return no error if not found)
*/
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)
static unsigned int gts, bfs;
module_param(gts, uint, 0644);
module_param(bfs, uint, 0644);
MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend.");
MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".);
/*******************************************************************************
*
* 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)
* DESCRIPTION: Enter a system sleep state via the legacy FADT PM registers
* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
*
******************************************************************************/
acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags)
{
u32 pm1a_control;
u32 pm1b_control;
struct acpi_bit_register_info *sleep_type_reg_info;
struct acpi_bit_register_info *sleep_enable_reg_info;
u32 pm1a_control;
u32 pm1b_control;
u32 in_value;
struct acpi_object_list arg_list;
union acpi_object arg;
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=0x%X B=0x%X",
acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
ACPI_FUNCTION_TRACE(hw_legacy_sleep);
sleep_type_reg_info =
acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
@ -271,6 +95,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
return_ACPI_STATUS(status);
}
if (sleep_state != ACPI_STATE_S5) {
/*
* Disable BM arbitration. This feature is contained within an
* optional register (PM2 Control), so ignore a BAD_ADDRESS
* exception.
*/
status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
return_ACPI_STATUS(status);
}
}
/*
* 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
@ -286,18 +122,10 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
return_ACPI_STATUS(status);
}
if (gts) {
/* Execute the _GTS method */
/* Optionally execute _GTS (Going To Sleep) */
arg_list.count = 1;
arg_list.pointer = &arg;
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = sleep_state;
status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
return_ACPI_STATUS(status);
}
if (flags & ACPI_EXECUTE_GTS) {
acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state);
}
/* Get current value of PM1A control */
@ -344,8 +172,12 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
ACPI_FLUSH_CPU_CACHE();
tboot_sleep(sleep_state, pm1a_control, pm1b_control);
status = acpi_os_prepare_sleep(sleep_state, pm1a_control,
pm1b_control);
if (ACPI_SKIP(status))
return_ACPI_STATUS(AE_OK);
if (ACPI_FAILURE(status))
return_ACPI_STATUS(status);
/* Write #2: Write both SLP_TYP + SLP_EN */
status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control);
@ -375,114 +207,44 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
}
}
/* Wait until we enter sleep state */
/* Wait for transition back to Working State */
do {
status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS,
&in_value);
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);
/* Clear the wake status bit (PM1) */
status =
acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_hw_clear_acpi_status();
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_hw_write_port(acpi_gbl_FADT.smi_command,
(u32) acpi_gbl_FADT.S4bios_request, 8);
do {
acpi_os_stall(1000);
status =
acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
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_prep
* FUNCTION: acpi_hw_legacy_wake_prep
*
* PARAMETERS: sleep_state - Which sleep state we are exiting
* PARAMETERS: sleep_state - Which sleep state we just exited
* Flags - ACPI_EXECUTE_BFS to run optional method
*
* RETURN: Status
*
* DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
* sleep.
* Called with interrupts DISABLED.
* Called with interrupts ENABLED.
*
******************************************************************************/
acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags)
{
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 pm1a_control;
u32 pm1b_control;
ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
ACPI_FUNCTION_TRACE(hw_legacy_wake_prep);
/*
* Set SLP_TYPE and SLP_EN to state S0.
@ -525,27 +287,20 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
}
}
if (bfs) {
/* Execute the _BFS method */
/* Optionally execute _BFS (Back From Sleep) */
arg_list.count = 1;
arg_list.pointer = &arg;
arg.type = ACPI_TYPE_INTEGER;
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"));
}
if (flags & ACPI_EXECUTE_BFS) {
acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state);
}
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_leave_sleep_state
* FUNCTION: acpi_hw_legacy_wake
*
* PARAMETERS: sleep_state - Which sleep state we just exited
* Flags - Reserved, set to zero
*
* RETURN: Status
*
@ -553,31 +308,17 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
* Called with interrupts ENABLED.
*
******************************************************************************/
acpi_status acpi_leave_sleep_state(u8 sleep_state)
acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags)
{
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
ACPI_FUNCTION_TRACE(hw_legacy_wake);
/* 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"));
}
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WAKING);
/*
* GPEs must be enabled before _WAK is called as GPEs
@ -591,46 +332,50 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_hw_enable_all_runtime_gpes();
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
arg.integer.value = sleep_state;
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? */
/*
* Now we can execute _WAK, etc. Some machines require that the GPEs
* are enabled before the wake methods are executed.
*/
acpi_hw_execute_sleep_method(METHOD_PATHNAME__WAK, sleep_state);
/*
* Some BIOSes assume that WAK_STS will be cleared on resume and use
* it to determine whether the system is rebooting or resuming. Clear
* it for compatibility.
* Some BIOS code assumes that WAK_STS will be cleared on resume
* and use it to determine whether the system is rebooting or
* resuming. Clear WAK_STS for compatibility.
*/
acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1);
acpi_gbl_system_awake_and_running = TRUE;
/* Enable power button */
(void)
acpi_write_bit_register(acpi_gbl_fixed_event_info
[ACPI_EVENT_POWER_BUTTON].
enable_register_id, ACPI_ENABLE_EVENT);
[ACPI_EVENT_POWER_BUTTON].
enable_register_id, ACPI_ENABLE_EVENT);
(void)
acpi_write_bit_register(acpi_gbl_fixed_event_info
[ACPI_EVENT_POWER_BUTTON].
status_register_id, ACPI_CLEAR_STATUS);
[ACPI_EVENT_POWER_BUTTON].
status_register_id, ACPI_CLEAR_STATUS);
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"));
/*
* Enable BM arbitration. This feature is contained within an
* optional register (PM2 Control), so ignore a BAD_ADDRESS
* exception.
*/
status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
return_ACPI_STATUS(status);
}
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -49,6 +49,7 @@
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwtimer")
#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
/******************************************************************************
*
* FUNCTION: acpi_get_timer_resolution
@ -187,3 +188,4 @@ acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
}
ACPI_EXPORT_SYMBOL(acpi_get_timer_duration)
#endif /* !ACPI_REDUCED_HARDWARE */

View file

@ -74,8 +74,7 @@ acpi_status acpi_reset(void)
/* Check if the reset register is supported */
if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
!reset_reg->address) {
if (!reset_reg->address) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
@ -138,11 +137,6 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
return (status);
}
width = reg->bit_width;
if (width == 64) {
width = 32; /* Break into two 32-bit transfers */
}
/* Initialize entire 64-bit return value to zero */
*return_value = 0;
@ -154,25 +148,18 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_read_memory((acpi_physical_address)
address, &value, width);
address, return_value,
reg->bit_width);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value = value;
if (reg->bit_width == 64) {
/* Read the top 32 bits */
status = acpi_os_read_memory((acpi_physical_address)
(address + 4), &value, 32);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value |= ((u64)value << 32);
}
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
width = reg->bit_width;
if (width == 64) {
width = 32; /* Break into two 32-bit transfers */
}
status = acpi_hw_read_port((acpi_io_address)
address, &value, width);
if (ACPI_FAILURE(status)) {
@ -231,33 +218,23 @@ acpi_status acpi_write(u64 value, struct acpi_generic_address *reg)
return (status);
}
width = reg->bit_width;
if (width == 64) {
width = 32; /* Break into two 32-bit transfers */
}
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_write_memory((acpi_physical_address)
address, ACPI_LODWORD(value),
width);
address, value, reg->bit_width);
if (ACPI_FAILURE(status)) {
return (status);
}
if (reg->bit_width == 64) {
status = acpi_os_write_memory((acpi_physical_address)
(address + 4),
ACPI_HIDWORD(value), 32);
if (ACPI_FAILURE(status)) {
return (status);
}
}
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
width = reg->bit_width;
if (width == 64) {
width = 32; /* Break into two 32-bit transfers */
}
status = acpi_hw_write_port((acpi_io_address)
address, ACPI_LODWORD(value),
width);
@ -286,6 +263,7 @@ acpi_status acpi_write(u64 value, struct acpi_generic_address *reg)
ACPI_EXPORT_SYMBOL(acpi_write)
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
* FUNCTION: acpi_read_bit_register
@ -453,7 +431,7 @@ unlock_and_exit:
}
ACPI_EXPORT_SYMBOL(acpi_write_bit_register)
#endif /* !ACPI_REDUCED_HARDWARE */
/*******************************************************************************
*
* FUNCTION: acpi_get_sleep_type_data

View file

@ -0,0 +1,431 @@
/******************************************************************************
*
* Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2012, Intel Corp.
* 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 <acpi/acpi.h>
#include "accommon.h"
#include <linux/module.h>
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwxfsleep")
/* Local prototypes */
static acpi_status
acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id);
/*
* Dispatch table used to efficiently branch to the various sleep
* functions.
*/
#define ACPI_SLEEP_FUNCTION_ID 0
#define ACPI_WAKE_PREP_FUNCTION_ID 1
#define ACPI_WAKE_FUNCTION_ID 2
/* Legacy functions are optional, based upon ACPI_REDUCED_HARDWARE */
static struct acpi_sleep_functions acpi_sleep_dispatch[] = {
{ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_sleep),
acpi_hw_extended_sleep},
{ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake_prep),
acpi_hw_extended_wake_prep},
{ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake), acpi_hw_extended_wake}
};
/*
* These functions are removed for the ACPI_REDUCED_HARDWARE case:
* acpi_set_firmware_waking_vector
* acpi_set_firmware_waking_vector64
* acpi_enter_sleep_state_s4bios
*/
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
* FUNCTION: acpi_set_firmware_waking_vector
*
* PARAMETERS: physical_address - 32-bit physical address of ACPI real mode
* entry point.
*
* RETURN: Status
*
* DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS
*
******************************************************************************/
acpi_status acpi_set_firmware_waking_vector(u32 physical_address)
{
ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
/*
* According to the ACPI specification 2.0c and later, the 64-bit
* waking vector should be cleared and the 32-bit waking vector should
* be used, unless we want the wake-up code to be called by the BIOS in
* Protected Mode. Some systems (for example HP dv5-1004nr) are known
* to fail to resume if the 64-bit vector is used.
*/
/* Set the 32-bit vector */
acpi_gbl_FACS->firmware_waking_vector = physical_address;
/* Clear the 64-bit vector if it exists */
if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) {
acpi_gbl_FACS->xfirmware_waking_vector = 0;
}
return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
#if ACPI_MACHINE_WIDTH == 64
/*******************************************************************************
*
* FUNCTION: acpi_set_firmware_waking_vector64
*
* PARAMETERS: physical_address - 64-bit physical address of ACPI protected
* mode entry point.
*
* RETURN: Status
*
* DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if
* it exists in the table. This function is intended for use with
* 64-bit host operating systems.
*
******************************************************************************/
acpi_status acpi_set_firmware_waking_vector64(u64 physical_address)
{
ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64);
/* Determine if the 64-bit vector actually exists */
if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Clear 32-bit vector, set the 64-bit X_ vector */
acpi_gbl_FACS->firmware_waking_vector = 0;
acpi_gbl_FACS->xfirmware_waking_vector = physical_address;
return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64)
#endif
/*******************************************************************************
*
* 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);
/* Clear the wake status bit (PM1) */
status =
acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
status = acpi_hw_clear_acpi_status();
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_hw_write_port(acpi_gbl_FADT.smi_command,
(u32)acpi_gbl_FADT.S4bios_request, 8);
do {
acpi_os_stall(1000);
status =
acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} while (!in_value);
return_ACPI_STATUS(AE_OK);
}
ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
#endif /* !ACPI_REDUCED_HARDWARE */
/*******************************************************************************
*
* FUNCTION: acpi_hw_sleep_dispatch
*
* PARAMETERS: sleep_state - Which sleep state to enter/exit
* function_id - Sleep, wake_prep, or Wake
*
* RETURN: Status from the invoked sleep handling function.
*
* DESCRIPTION: Dispatch a sleep/wake request to the appropriate handling
* function.
*
******************************************************************************/
static acpi_status
acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id)
{
acpi_status status;
struct acpi_sleep_functions *sleep_functions =
&acpi_sleep_dispatch[function_id];
#if (!ACPI_REDUCED_HARDWARE)
/*
* If the Hardware Reduced flag is set (from the FADT), we must
* use the extended sleep registers
*/
if (acpi_gbl_reduced_hardware || acpi_gbl_FADT.sleep_control.address) {
status = sleep_functions->extended_function(sleep_state, flags);
} else {
/* Legacy sleep */
status = sleep_functions->legacy_function(sleep_state, flags);
}
return (status);
#else
/*
* For the case where reduced-hardware-only code is being generated,
* we know that only the extended sleep registers are available
*/
status = sleep_functions->extended_function(sleep_state, flags);
return (status);
#endif /* !ACPI_REDUCED_HARDWARE */
}
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state_prep
*
* PARAMETERS: sleep_state - Which sleep state to enter
*
* RETURN: Status
*
* DESCRIPTION: Prepare to enter a system sleep state.
* 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;
u32 sst_value;
ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);
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);
}
/* Execute the _PTS method (Prepare To Sleep) */
arg_list.count = 1;
arg_list.pointer = &arg;
arg.type = ACPI_TYPE_INTEGER;
arg.integer.value = sleep_state;
status =
acpi_evaluate_object(NULL, METHOD_PATHNAME__PTS, &arg_list, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
return_ACPI_STATUS(status);
}
/* Setup the argument to the _SST method (System STatus) */
switch (sleep_state) {
case ACPI_STATE_S0:
sst_value = ACPI_SST_WORKING;
break;
case ACPI_STATE_S1:
case ACPI_STATE_S2:
case ACPI_STATE_S3:
sst_value = ACPI_SST_SLEEPING;
break;
case ACPI_STATE_S4:
sst_value = ACPI_SST_SLEEP_CONTEXT;
break;
default:
sst_value = ACPI_SST_INDICATOR_OFF; /* Default is off */
break;
}
/*
* Set the system indicators to show the desired sleep state.
* _SST is an optional method (return no error if not found)
*/
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, sst_value);
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
* Flags - ACPI_EXECUTE_GTS to run optional method
*
* 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, u8 flags)
{
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=0x%X B=0x%X",
acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
status =
acpi_hw_sleep_dispatch(sleep_state, flags, ACPI_SLEEP_FUNCTION_ID);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
/*******************************************************************************
*
* FUNCTION: acpi_leave_sleep_state_prep
*
* PARAMETERS: sleep_state - Which sleep state we are exiting
* Flags - ACPI_EXECUTE_BFS to run optional method
*
* RETURN: Status
*
* DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
* sleep.
* Called with interrupts DISABLED.
*
******************************************************************************/
acpi_status acpi_leave_sleep_state_prep(u8 sleep_state, u8 flags)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
status =
acpi_hw_sleep_dispatch(sleep_state, flags,
ACPI_WAKE_PREP_FUNCTION_ID);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state_prep)
/*******************************************************************************
*
* FUNCTION: acpi_leave_sleep_state
*
* PARAMETERS: sleep_state - Which sleep state we are exiting
*
* RETURN: Status
*
* DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
* Called with interrupts ENABLED.
*
******************************************************************************/
acpi_status acpi_leave_sleep_state(u8 sleep_state)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
status = acpi_hw_sleep_dispatch(sleep_state, 0, ACPI_WAKE_FUNCTION_ID);
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)

View file

@ -242,7 +242,20 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
if (!obj_desc) {
/* No attached object, we are done */
/* No attached object. Some types should always have an object */
switch (type) {
case ACPI_TYPE_INTEGER:
case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_STRING:
case ACPI_TYPE_METHOD:
acpi_os_printf("<No attached object>");
break;
default:
break;
}
acpi_os_printf("\n");
return (AE_OK);

View file

@ -121,7 +121,7 @@ void acpi_ns_dump_root_devices(void)
return;
}
status = acpi_get_handle(NULL, ACPI_NS_SYSTEM_BUS, &sys_bus_handle);
status = acpi_get_handle(NULL, METHOD_NAME__SB_, &sys_bus_handle);
if (ACPI_FAILURE(status)) {
return;
}

View file

@ -638,8 +638,8 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
/* Create the new outer package and populate it */
status =
acpi_ns_repair_package_list(data,
return_object_ptr);
acpi_ns_wrap_with_package(data, *elements,
return_object_ptr);
if (ACPI_FAILURE(status)) {
return (status);
}

View file

@ -71,11 +71,10 @@ ACPI_MODULE_NAME("nsrepair")
* Buffer -> String
* Buffer -> Package of Integers
* Package -> Package of one Package
* An incorrect standalone object is wrapped with required outer package
*
* Additional possible repairs:
*
* Required package elements that are NULL replaced by Integer/String/Buffer
* Incorrect standalone package wrapped with required outer package
*
******************************************************************************/
/* Local prototypes */
@ -91,10 +90,6 @@ static acpi_status
acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
union acpi_operand_object **return_object);
static acpi_status
acpi_ns_convert_to_package(union acpi_operand_object *original_object,
union acpi_operand_object **return_object);
/*******************************************************************************
*
* FUNCTION: acpi_ns_repair_object
@ -151,9 +146,24 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
}
}
if (expected_btypes & ACPI_RTYPE_PACKAGE) {
status = acpi_ns_convert_to_package(return_object, &new_object);
/*
* A package is expected. We will wrap the existing object with a
* new package object. It is often the case that if a variable-length
* package is required, but there is only a single object needed, the
* BIOS will return that object instead of wrapping it with a Package
* object. Note: after the wrapping, the package will be validated
* for correct contents (expected object type or types).
*/
status =
acpi_ns_wrap_with_package(data, return_object, &new_object);
if (ACPI_SUCCESS(status)) {
goto object_repaired;
/*
* The original object just had its reference count
* incremented for being inserted into the new package.
*/
*return_object_ptr = new_object; /* New Package object */
data->flags |= ACPI_OBJECT_REPAIRED;
return (AE_OK);
}
}
@ -165,22 +175,27 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
/* Object was successfully repaired */
/*
* If the original object is a package element, we need to:
* 1. Set the reference count of the new object to match the
* reference count of the old object.
* 2. Decrement the reference count of the original object.
*/
if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
new_object->common.reference_count =
return_object->common.reference_count;
/*
* The original object is a package element. We need to
* decrement the reference count of the original object,
* for removing it from the package.
*
* However, if the original object was just wrapped with a
* package object as part of the repair, we don't need to
* change the reference count.
*/
if (!(data->flags & ACPI_OBJECT_WRAPPED)) {
new_object->common.reference_count =
return_object->common.reference_count;
if (return_object->common.reference_count > 1) {
return_object->common.reference_count--;
if (return_object->common.reference_count > 1) {
return_object->common.reference_count--;
}
}
ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
"%s: Converted %s to expected %s at index %u\n",
"%s: Converted %s to expected %s at Package index %u\n",
data->pathname,
acpi_ut_get_object_type_name(return_object),
acpi_ut_get_object_type_name(new_object),
@ -451,65 +466,6 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_convert_to_package
*
* PARAMETERS: original_object - Object to be converted
* return_object - Where the new converted object is returned
*
* RETURN: Status. AE_OK if conversion was successful.
*
* DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
* the buffer is converted to a single integer package element.
*
******************************************************************************/
static acpi_status
acpi_ns_convert_to_package(union acpi_operand_object *original_object,
union acpi_operand_object **return_object)
{
union acpi_operand_object *new_object;
union acpi_operand_object **elements;
u32 length;
u8 *buffer;
switch (original_object->common.type) {
case ACPI_TYPE_BUFFER:
/* Buffer-to-Package conversion */
length = original_object->buffer.length;
new_object = acpi_ut_create_package_object(length);
if (!new_object) {
return (AE_NO_MEMORY);
}
/* Convert each buffer byte to an integer package element */
elements = new_object->package.elements;
buffer = original_object->buffer.pointer;
while (length--) {
*elements =
acpi_ut_create_integer_object((u64) *buffer);
if (!*elements) {
acpi_ut_remove_reference(new_object);
return (AE_NO_MEMORY);
}
elements++;
buffer++;
}
break;
default:
return (AE_AML_OPERAND_TYPE);
}
*return_object = new_object;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_repair_null_element
@ -677,55 +633,56 @@ acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
/*******************************************************************************
*
* FUNCTION: acpi_ns_repair_package_list
* FUNCTION: acpi_ns_wrap_with_package
*
* PARAMETERS: Data - Pointer to validation data structure
* obj_desc_ptr - Pointer to the object to repair. The new
* package object is returned here,
* overwriting the old object.
* original_object - Pointer to the object to repair.
* obj_desc_ptr - The new package object is returned here
*
* RETURN: Status, new object in *obj_desc_ptr
*
* DESCRIPTION: Repair a common problem with objects that are defined to return
* a variable-length Package of Packages. If the variable-length
* is one, some BIOS code mistakenly simply declares a single
* Package instead of a Package with one sub-Package. This
* function attempts to repair this error by wrapping a Package
* object around the original Package, creating the correct
* Package with one sub-Package.
* DESCRIPTION: Repair a common problem with objects that are defined to
* return a variable-length Package of sub-objects. If there is
* only one sub-object, some BIOS code mistakenly simply declares
* the single object instead of a Package with one sub-object.
* This function attempts to repair this error by wrapping a
* Package object around the original object, creating the
* correct and expected Package with one sub-object.
*
* Names that can be repaired in this manner include:
* _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
* _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS,
* _BCL, _DOD, _FIX, _Sx
*
******************************************************************************/
acpi_status
acpi_ns_repair_package_list(struct acpi_predefined_data *data,
union acpi_operand_object **obj_desc_ptr)
acpi_ns_wrap_with_package(struct acpi_predefined_data *data,
union acpi_operand_object *original_object,
union acpi_operand_object **obj_desc_ptr)
{
union acpi_operand_object *pkg_obj_desc;
ACPI_FUNCTION_NAME(ns_repair_package_list);
ACPI_FUNCTION_NAME(ns_wrap_with_package);
/*
* Create the new outer package and populate it. The new package will
* have a single element, the lone subpackage.
* have a single element, the lone sub-object.
*/
pkg_obj_desc = acpi_ut_create_package_object(1);
if (!pkg_obj_desc) {
return (AE_NO_MEMORY);
}
pkg_obj_desc->package.elements[0] = *obj_desc_ptr;
pkg_obj_desc->package.elements[0] = original_object;
ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
"%s: Wrapped %s with expected Package object\n",
data->pathname,
acpi_ut_get_object_type_name(original_object)));
/* Return the new object in the object pointer */
*obj_desc_ptr = pkg_obj_desc;
data->flags |= ACPI_OBJECT_REPAIRED;
ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
"%s: Repaired incorrectly formed Package\n",
data->pathname));
data->flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED;
return (AE_OK);
}

View file

@ -341,7 +341,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
if (!acpi_ns_valid_path_separator(*external_name) &&
(*external_name != 0)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
return_ACPI_STATUS(AE_BAD_PATHNAME);
}
/* Move on the next segment */

View file

@ -363,10 +363,6 @@ static void acpi_tb_convert_fadt(void)
u32 address32;
u32 i;
/* Update the local FADT table header length */
acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
/*
* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
* Later code will always use the X 64-bit field. Also, check for an
@ -408,6 +404,10 @@ static void acpi_tb_convert_fadt(void)
acpi_gbl_FADT.boot_flags = 0;
}
/* Update the local FADT table header length */
acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
/*
* Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
* generic address structures as necessary. Later code will always use

View file

@ -114,7 +114,6 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
{
u32 i;
acpi_status status = AE_OK;
struct acpi_table_header *override_table = NULL;
ACPI_FUNCTION_TRACE(tb_add_table);
@ -224,25 +223,10 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
/*
* ACPI Table Override:
* Allow the host to override dynamically loaded tables.
* NOTE: the table is fully mapped at this point, and the mapping will
* be deleted by tb_table_override if the table is actually overridden.
*/
status = acpi_os_table_override(table_desc->pointer, &override_table);
if (ACPI_SUCCESS(status) && override_table) {
ACPI_INFO((AE_INFO,
"%4.4s @ 0x%p Table override, replaced with:",
table_desc->pointer->signature,
ACPI_CAST_PTR(void, table_desc->address)));
/* We can delete the table that was passed as a parameter */
acpi_tb_delete_table(table_desc);
/* Setup descriptor for the new table */
table_desc->address = ACPI_PTR_TO_PHYSADDR(override_table);
table_desc->pointer = override_table;
table_desc->length = override_table->length;
table_desc->flags = ACPI_TABLE_ORIGIN_OVERRIDE;
}
(void)acpi_tb_table_override(table_desc->pointer, table_desc);
/* Add the table to the global root table list */
@ -261,6 +245,95 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_table_override
*
* PARAMETERS: table_header - Header for the original table
* table_desc - Table descriptor initialized for the
* original table. May or may not be mapped.
*
* RETURN: Pointer to the entire new table. NULL if table not overridden.
* If overridden, installs the new table within the input table
* descriptor.
*
* DESCRIPTION: Attempt table override by calling the OSL override functions.
* Note: If the table is overridden, then the entire new table
* is mapped and returned by this function.
*
******************************************************************************/
struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
*table_header,
struct acpi_table_desc
*table_desc)
{
acpi_status status;
struct acpi_table_header *new_table = NULL;
acpi_physical_address new_address = 0;
u32 new_table_length = 0;
u8 new_flags;
char *override_type;
/* (1) Attempt logical override (returns a logical address) */
status = acpi_os_table_override(table_header, &new_table);
if (ACPI_SUCCESS(status) && new_table) {
new_address = ACPI_PTR_TO_PHYSADDR(new_table);
new_table_length = new_table->length;
new_flags = ACPI_TABLE_ORIGIN_OVERRIDE;
override_type = "Logical";
goto finish_override;
}
/* (2) Attempt physical override (returns a physical address) */
status = acpi_os_physical_table_override(table_header,
&new_address,
&new_table_length);
if (ACPI_SUCCESS(status) && new_address && new_table_length) {
/* Map the entire new table */
new_table = acpi_os_map_memory(new_address, new_table_length);
if (!new_table) {
ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
"%4.4s %p Attempted physical table override failed",
table_header->signature,
ACPI_CAST_PTR(void,
table_desc->address)));
return (NULL);
}
override_type = "Physical";
new_flags = ACPI_TABLE_ORIGIN_MAPPED;
goto finish_override;
}
return (NULL); /* There was no override */
finish_override:
ACPI_INFO((AE_INFO,
"%4.4s %p %s table override, new table: %p",
table_header->signature,
ACPI_CAST_PTR(void, table_desc->address),
override_type, new_table));
/* We can now unmap/delete the original table (if fully mapped) */
acpi_tb_delete_table(table_desc);
/* Setup descriptor for the new table */
table_desc->address = new_address;
table_desc->pointer = new_table;
table_desc->length = new_table_length;
table_desc->flags = new_flags;
return (new_table);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_resize_root_table_list
@ -396,7 +469,11 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
case ACPI_TABLE_ORIGIN_ALLOCATED:
ACPI_FREE(table_desc->pointer);
break;
default:;
/* Not mapped or allocated, there is nothing we can do */
default:
return;
}
table_desc->pointer = NULL;

View file

@ -118,6 +118,7 @@ acpi_tb_check_xsdt(acpi_physical_address address)
return AE_OK;
}
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
* FUNCTION: acpi_tb_initialize_facs
@ -148,6 +149,7 @@ acpi_status acpi_tb_initialize_facs(void)
&acpi_gbl_FACS));
return status;
}
#endif /* !ACPI_REDUCED_HARDWARE */
/*******************************************************************************
*
@ -444,7 +446,7 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
* RETURN: None
*
* DESCRIPTION: Install an ACPI table into the global data structure. The
* table override mechanism is implemented here to allow the host
* table override mechanism is called to allow the host
* OS to replace any table before it is installed in the root
* table array.
*
@ -454,11 +456,9 @@ void
acpi_tb_install_table(acpi_physical_address address,
char *signature, u32 table_index)
{
u8 flags;
acpi_status status;
struct acpi_table_header *table_to_install;
struct acpi_table_header *mapped_table;
struct acpi_table_header *override_table = NULL;
struct acpi_table_header *table;
struct acpi_table_header *final_table;
struct acpi_table_desc *table_desc;
if (!address) {
ACPI_ERROR((AE_INFO,
@ -469,69 +469,78 @@ acpi_tb_install_table(acpi_physical_address address,
/* Map just the table header */
mapped_table =
acpi_os_map_memory(address, sizeof(struct acpi_table_header));
if (!mapped_table) {
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
if (!table) {
ACPI_ERROR((AE_INFO,
"Could not map memory for table [%s] at %p",
signature, ACPI_CAST_PTR(void, address)));
return;
}
/* If a particular signature is expected (DSDT/FACS), it must match */
if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) {
if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) {
ACPI_ERROR((AE_INFO,
"Invalid signature 0x%X for ACPI table, expected [%s]",
*ACPI_CAST_PTR(u32, mapped_table->signature),
signature));
*ACPI_CAST_PTR(u32, table->signature), signature));
goto unmap_and_exit;
}
/*
* Initialize the table entry. Set the pointer to NULL, since the
* table is not fully mapped at this time.
*/
table_desc = &acpi_gbl_root_table_list.tables[table_index];
table_desc->address = address;
table_desc->pointer = NULL;
table_desc->length = table->length;
table_desc->flags = ACPI_TABLE_ORIGIN_MAPPED;
ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);
/*
* ACPI Table Override:
*
* Before we install the table, let the host OS override it with a new
* one if desired. Any table within the RSDT/XSDT can be replaced,
* including the DSDT which is pointed to by the FADT.
*
* NOTE: If the table is overridden, then final_table will contain a
* mapped pointer to the full new table. If the table is not overridden,
* or if there has been a physical override, then the table will be
* fully mapped later (in verify table). In any case, we must
* unmap the header that was mapped above.
*/
status = acpi_os_table_override(mapped_table, &override_table);
if (ACPI_SUCCESS(status) && override_table) {
ACPI_INFO((AE_INFO,
"%4.4s @ 0x%p Table override, replaced with:",
mapped_table->signature, ACPI_CAST_PTR(void,
address)));
acpi_gbl_root_table_list.tables[table_index].pointer =
override_table;
address = ACPI_PTR_TO_PHYSADDR(override_table);
table_to_install = override_table;
flags = ACPI_TABLE_ORIGIN_OVERRIDE;
} else {
table_to_install = mapped_table;
flags = ACPI_TABLE_ORIGIN_MAPPED;
final_table = acpi_tb_table_override(table, table_desc);
if (!final_table) {
final_table = table; /* There was no override */
}
/* Initialize the table entry */
acpi_tb_print_table_header(table_desc->address, final_table);
acpi_gbl_root_table_list.tables[table_index].address = address;
acpi_gbl_root_table_list.tables[table_index].length =
table_to_install->length;
acpi_gbl_root_table_list.tables[table_index].flags = flags;
ACPI_MOVE_32_TO_32(&
(acpi_gbl_root_table_list.tables[table_index].
signature), table_to_install->signature);
acpi_tb_print_table_header(address, table_to_install);
/* Set the global integer width (based upon revision of the DSDT) */
if (table_index == ACPI_TABLE_INDEX_DSDT) {
acpi_ut_set_integer_width(final_table->revision);
}
/* Global integer width is based upon revision of the DSDT */
acpi_ut_set_integer_width(table_to_install->revision);
/*
* If we have a physical override during this early loading of the ACPI
* tables, unmap the table for now. It will be mapped again later when
* it is actually used. This supports very early loading of ACPI tables,
* before virtual memory is fully initialized and running within the
* host OS. Note: A logical override has the ACPI_TABLE_ORIGIN_OVERRIDE
* flag set and will not be deleted below.
*/
if (final_table != table) {
acpi_tb_delete_table(table_desc);
}
unmap_and_exit:
acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header));
/* Always unmap the table header that we mapped above */
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
}
/*******************************************************************************

View file

@ -497,19 +497,20 @@ char *acpi_ut_get_mutex_name(u32 mutex_id)
/* Names for Notify() values, used for debug output */
static const char *acpi_gbl_notify_value_names[] = {
"Bus Check",
"Device Check",
"Device Wake",
"Eject Request",
"Device Check Light",
"Frequency Mismatch",
"Bus Mode Mismatch",
"Power Fault",
"Capabilities Check",
"Device PLD Check",
"Reserved",
"System Locality Update"
static const char *acpi_gbl_notify_value_names[ACPI_NOTIFY_MAX + 1] = {
/* 00 */ "Bus Check",
/* 01 */ "Device Check",
/* 02 */ "Device Wake",
/* 03 */ "Eject Request",
/* 04 */ "Device Check Light",
/* 05 */ "Frequency Mismatch",
/* 06 */ "Bus Mode Mismatch",
/* 07 */ "Power Fault",
/* 08 */ "Capabilities Check",
/* 09 */ "Device PLD Check",
/* 10 */ "Reserved",
/* 11 */ "System Locality Update",
/* 12 */ "Shutdown Request"
};
const char *acpi_ut_get_notify_name(u32 notify_value)
@ -519,9 +520,10 @@ const char *acpi_ut_get_notify_name(u32 notify_value)
return (acpi_gbl_notify_value_names[notify_value]);
} else if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
return ("Reserved");
} else { /* Greater or equal to 0x80 */
return ("**Device Specific**");
} else if (notify_value <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) {
return ("Device Specific");
} else {
return ("Hardware Specific");
}
}
#endif

View file

@ -140,6 +140,7 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = {
{NULL, ACPI_TYPE_ANY, NULL}
};
#if (!ACPI_REDUCED_HARDWARE)
/******************************************************************************
*
* Event and Hardware globals
@ -236,6 +237,7 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
ACPI_BITMASK_RT_CLOCK_STATUS,
ACPI_BITMASK_RT_CLOCK_ENABLE},
};
#endif /* !ACPI_REDUCED_HARDWARE */
/*******************************************************************************
*
@ -286,6 +288,8 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000;
#if (!ACPI_REDUCED_HARDWARE)
/* GPE support */
acpi_gbl_gpe_xrupt_list_head = NULL;
@ -294,6 +298,10 @@ acpi_status acpi_ut_init_globals(void)
acpi_current_gpe_count = 0;
acpi_gbl_all_gpes_initialized = FALSE;
acpi_gbl_global_event_handler = NULL;
#endif /* !ACPI_REDUCED_HARDWARE */
/* Global handlers */
acpi_gbl_system_notify.handler = NULL;
@ -302,7 +310,6 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_init_handler = NULL;
acpi_gbl_table_handler = NULL;
acpi_gbl_interface_handler = NULL;
acpi_gbl_global_event_handler = NULL;
/* Global Lock support */

View file

@ -53,27 +53,35 @@ ACPI_MODULE_NAME("utinit")
/* Local prototypes */
static void acpi_ut_terminate(void);
#if (!ACPI_REDUCED_HARDWARE)
static void acpi_ut_free_gpe_lists(void);
#else
#define acpi_ut_free_gpe_lists()
#endif /* !ACPI_REDUCED_HARDWARE */
#if (!ACPI_REDUCED_HARDWARE)
/******************************************************************************
*
* FUNCTION: acpi_ut_terminate
* FUNCTION: acpi_ut_free_gpe_lists
*
* PARAMETERS: none
*
* RETURN: none
*
* DESCRIPTION: Free global memory
* DESCRIPTION: Free global GPE lists
*
******************************************************************************/
static void acpi_ut_terminate(void)
static void acpi_ut_free_gpe_lists(void)
{
struct acpi_gpe_block_info *gpe_block;
struct acpi_gpe_block_info *next_gpe_block;
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
ACPI_FUNCTION_TRACE(ut_terminate);
/* Free global GPE blocks and related info structures */
gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
@ -91,7 +99,26 @@ static void acpi_ut_terminate(void)
ACPI_FREE(gpe_xrupt_info);
gpe_xrupt_info = next_gpe_xrupt_info;
}
}
#endif /* !ACPI_REDUCED_HARDWARE */
/******************************************************************************
*
* FUNCTION: acpi_ut_terminate
*
* PARAMETERS: none
*
* RETURN: none
*
* DESCRIPTION: Free global memory
*
******************************************************************************/
static void acpi_ut_terminate(void)
{
ACPI_FUNCTION_TRACE(ut_terminate);
acpi_ut_free_gpe_lists();
acpi_ut_delete_address_lists();
return_VOID;
}

View file

@ -145,6 +145,8 @@ acpi_status acpi_enable_subsystem(u32 flags)
ACPI_FUNCTION_TRACE(acpi_enable_subsystem);
#if (!ACPI_REDUCED_HARDWARE)
/* Enable ACPI mode */
if (!(flags & ACPI_NO_ACPI_ENABLE)) {
@ -169,6 +171,7 @@ acpi_status acpi_enable_subsystem(u32 flags)
ACPI_WARNING((AE_INFO, "Could not map the FACS table"));
return_ACPI_STATUS(status);
}
#endif /* !ACPI_REDUCED_HARDWARE */
/*
* Install the default op_region handlers. These are installed unless
@ -184,7 +187,7 @@ acpi_status acpi_enable_subsystem(u32 flags)
return_ACPI_STATUS(status);
}
}
#if (!ACPI_REDUCED_HARDWARE)
/*
* Initialize ACPI Event handling (Fixed and General Purpose)
*
@ -220,6 +223,7 @@ acpi_status acpi_enable_subsystem(u32 flags)
return_ACPI_STATUS(status);
}
}
#endif /* !ACPI_REDUCED_HARDWARE */
return_ACPI_STATUS(status);
}

View file

@ -558,33 +558,48 @@ void apei_resources_release(struct apei_resources *resources)
}
EXPORT_SYMBOL_GPL(apei_resources_release);
static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
u32 *access_bit_width)
{
u32 width, space_id;
u32 bit_width, bit_offset, access_size_code, space_id;
width = reg->bit_width;
bit_width = reg->bit_width;
bit_offset = reg->bit_offset;
access_size_code = reg->access_width;
space_id = reg->space_id;
/* Handle possible alignment issues */
memcpy(paddr, &reg->address, sizeof(*paddr));
if (!*paddr) {
pr_warning(FW_BUG APEI_PFX
"Invalid physical address in GAR [0x%llx/%u/%u]\n",
*paddr, width, space_id);
"Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n",
*paddr, bit_width, bit_offset, access_size_code,
space_id);
return -EINVAL;
}
if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) {
if (access_size_code < 1 || access_size_code > 4) {
pr_warning(FW_BUG APEI_PFX
"Invalid bit width in GAR [0x%llx/%u/%u]\n",
*paddr, width, space_id);
"Invalid access size code in GAR [0x%llx/%u/%u/%u/%u]\n",
*paddr, bit_width, bit_offset, access_size_code,
space_id);
return -EINVAL;
}
*access_bit_width = 1UL << (access_size_code + 2);
if ((bit_width + bit_offset) > *access_bit_width) {
pr_warning(FW_BUG APEI_PFX
"Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n",
*paddr, bit_width, bit_offset, access_size_code,
space_id);
return -EINVAL;
}
if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
pr_warning(FW_BUG APEI_PFX
"Invalid address space type in GAR [0x%llx/%u/%u]\n",
*paddr, width, space_id);
"Invalid address space type in GAR [0x%llx/%u/%u/%u/%u]\n",
*paddr, bit_width, bit_offset, access_size_code,
space_id);
return -EINVAL;
}
@ -595,23 +610,25 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
int apei_read(u64 *val, struct acpi_generic_address *reg)
{
int rc;
u32 access_bit_width;
u64 address;
acpi_status status;
rc = apei_check_gar(reg, &address);
rc = apei_check_gar(reg, &address, &access_bit_width);
if (rc)
return rc;
*val = 0;
switch(reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
status = acpi_os_read_memory64((acpi_physical_address)
address, val, reg->bit_width);
status = acpi_os_read_memory((acpi_physical_address) address,
val, access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
status = acpi_os_read_port(address, (u32 *)val,
access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
@ -627,22 +644,23 @@ EXPORT_SYMBOL_GPL(apei_read);
int apei_write(u64 val, struct acpi_generic_address *reg)
{
int rc;
u32 access_bit_width;
u64 address;
acpi_status status;
rc = apei_check_gar(reg, &address);
rc = apei_check_gar(reg, &address, &access_bit_width);
if (rc)
return rc;
switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
status = acpi_os_write_memory64((acpi_physical_address)
address, val, reg->bit_width);
status = acpi_os_write_memory((acpi_physical_address) address,
val, access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
status = acpi_os_write_port(address, val, reg->bit_width);
status = acpi_os_write_port(address, val, access_bit_width);
if (ACPI_FAILURE(status))
return -EIO;
break;
@ -661,23 +679,24 @@ static int collect_res_callback(struct apei_exec_context *ctx,
struct apei_resources *resources = data;
struct acpi_generic_address *reg = &entry->register_region;
u8 ins = entry->instruction;
u32 access_bit_width;
u64 paddr;
int rc;
if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER))
return 0;
rc = apei_check_gar(reg, &paddr);
rc = apei_check_gar(reg, &paddr, &access_bit_width);
if (rc)
return rc;
switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
return apei_res_add(&resources->iomem, paddr,
reg->bit_width / 8);
access_bit_width / 8);
case ACPI_ADR_SPACE_SYSTEM_IO:
return apei_res_add(&resources->ioport, paddr,
reg->bit_width / 8);
access_bit_width / 8);
default:
return -EINVAL;
}

View file

@ -362,6 +362,7 @@ void apei_estatus_print(const char *pfx,
gedata_len = gdata->error_data_length;
apei_estatus_print_section(pfx, gdata, sec_no);
data_len -= gedata_len + sizeof(*gdata);
gdata = (void *)(gdata + 1) + gedata_len;
sec_no++;
}
}
@ -396,6 +397,7 @@ int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
if (gedata_len > data_len - sizeof(*gdata))
return -EINVAL;
data_len -= gedata_len + sizeof(*gdata);
gdata = (void *)(gdata + 1) + gedata_len;
}
if (data_len)
return -EINVAL;

View file

@ -74,6 +74,8 @@ struct vendor_error_type_extension {
u8 reserved[3];
};
static u32 notrigger;
static u32 vendor_flags;
static struct debugfs_blob_wrapper vendor_blob;
static char vendor_dev[64];
@ -238,7 +240,7 @@ static void *einj_get_parameter_address(void)
return v5param;
}
}
if (paddrv4) {
if (param_extension && paddrv4) {
struct einj_parameter *v4param;
v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param));
@ -496,9 +498,11 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
if (rc)
return rc;
trigger_paddr = apei_exec_ctx_get_output(&ctx);
rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
if (rc)
return rc;
if (notrigger == 0) {
rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
if (rc)
return rc;
}
rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);
return rc;
@ -700,6 +704,11 @@ static int __init einj_init(void)
einj_debug_dir, &error_param2);
if (!fentry)
goto err_unmap;
fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
einj_debug_dir, &notrigger);
if (!fentry)
goto err_unmap;
}
if (vendor_dev[0]) {

View file

@ -917,7 +917,7 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
{
if ((erst_tab->header_length !=
(sizeof(struct acpi_table_erst) - sizeof(erst_tab->header)))
&& (erst_tab->header_length != sizeof(struct acpi_table_einj)))
&& (erst_tab->header_length != sizeof(struct acpi_table_erst)))
return -EINVAL;
if (erst_tab->header.length < sizeof(struct acpi_table_erst))
return -EINVAL;

175
drivers/acpi/bgrt.c Normal file
View file

@ -0,0 +1,175 @@
/*
* Copyright 2012 Red Hat, Inc <mjg@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/sysfs.h>
#include <acpi/acpi.h>
#include <acpi/acpi_bus.h>
static struct acpi_table_bgrt *bgrt_tab;
static struct kobject *bgrt_kobj;
struct bmp_header {
u16 id;
u32 size;
} __attribute ((packed));
static struct bmp_header bmp_header;
static ssize_t show_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->version);
}
static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
static ssize_t show_status(struct device *dev,
struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->status);
}
static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
static ssize_t show_type(struct device *dev,
struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_type);
}
static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
static ssize_t show_xoffset(struct device *dev,
struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_x);
}
static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL);
static ssize_t show_yoffset(struct device *dev,
struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_y);
}
static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL);
static ssize_t show_image(struct file *file, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t off, size_t count)
{
int size = attr->size;
void __iomem *image = attr->private;
if (off >= size) {
count = 0;
} else {
if (off + count > size)
count = size - off;
memcpy_fromio(buf, image+off, count);
}
return count;
}
static struct bin_attribute image_attr = {
.attr = {
.name = "image",
.mode = S_IRUGO,
},
.read = show_image,
};
static struct attribute *bgrt_attributes[] = {
&dev_attr_version.attr,
&dev_attr_status.attr,
&dev_attr_type.attr,
&dev_attr_xoffset.attr,
&dev_attr_yoffset.attr,
NULL,
};
static struct attribute_group bgrt_attribute_group = {
.attrs = bgrt_attributes,
};
static int __init bgrt_init(void)
{
acpi_status status;
int ret;
void __iomem *bgrt;
if (acpi_disabled)
return -ENODEV;
status = acpi_get_table("BGRT", 0,
(struct acpi_table_header **)&bgrt_tab);
if (ACPI_FAILURE(status))
return -ENODEV;
sysfs_bin_attr_init(&image_attr);
bgrt = ioremap(bgrt_tab->image_address, sizeof(struct bmp_header));
if (!bgrt) {
ret = -EINVAL;
goto out_err;
}
memcpy_fromio(&bmp_header, bgrt, sizeof(bmp_header));
image_attr.size = bmp_header.size;
iounmap(bgrt);
image_attr.private = ioremap(bgrt_tab->image_address, image_attr.size);
if (!image_attr.private) {
ret = -EINVAL;
goto out_err;
}
bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj);
if (!bgrt_kobj) {
ret = -EINVAL;
goto out_iounmap;
}
ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group);
if (ret)
goto out_kobject;
ret = sysfs_create_bin_file(bgrt_kobj, &image_attr);
if (ret)
goto out_group;
return 0;
out_group:
sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
out_kobject:
kobject_put(bgrt_kobj);
out_iounmap:
iounmap(image_attr.private);
out_err:
return ret;
}
static void __exit bgrt_exit(void)
{
iounmap(image_attr.private);
sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group);
sysfs_remove_bin_file(bgrt_kobj, &image_attr);
}
module_init(bgrt_init);
module_exit(bgrt_exit);
MODULE_AUTHOR("Matthew Garrett");
MODULE_DESCRIPTION("BGRT boot graphic support");
MODULE_LICENSE("GPL");

View file

@ -1010,6 +1010,7 @@ static int __init acpi_bus_init(void)
}
struct kobject *acpi_kobj;
EXPORT_SYMBOL_GPL(acpi_kobj);
static int __init acpi_init(void)
{

View file

@ -445,6 +445,16 @@ int ec_transaction(u8 command,
EXPORT_SYMBOL(ec_transaction);
/* Get the handle to the EC device */
acpi_handle ec_get_handle(void)
{
if (!first_ec)
return NULL;
return first_ec->handle;
}
EXPORT_SYMBOL(ec_get_handle);
void acpi_ec_block_transactions(void)
{
struct acpi_ec *ec = first_ec;
@ -812,10 +822,10 @@ static int acpi_ec_add(struct acpi_device *device)
first_ec = ec;
device->driver_data = ec;
WARN(!request_region(ec->data_addr, 1, "EC data"),
"Could not request EC data io port 0x%lx", ec->data_addr);
WARN(!request_region(ec->command_addr, 1, "EC cmd"),
"Could not request EC cmd io port 0x%lx", ec->command_addr);
ret = !!request_region(ec->data_addr, 1, "EC data");
WARN(!ret, "Could not request EC data io port 0x%lx", ec->data_addr);
ret = !!request_region(ec->command_addr, 1, "EC cmd");
WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);
pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr);

View file

@ -95,8 +95,8 @@ static int suspend_nvs_register(unsigned long start, unsigned long size)
{
struct nvs_page *entry, *next;
pr_info("PM: Registering ACPI NVS region at %lx (%ld bytes)\n",
start, size);
pr_info("PM: Registering ACPI NVS region [mem %#010lx-%#010lx] (%ld bytes)\n",
start, start + size - 1, size);
while (size > 0) {
unsigned int nr_bytes;

View file

@ -77,6 +77,9 @@ EXPORT_SYMBOL(acpi_in_debugger);
extern char line_buf[80];
#endif /*ENABLE_DEBUGGER */
static int (*__acpi_os_prepare_sleep)(u8 sleep_state, u32 pm1a_ctrl,
u32 pm1b_ctrl);
static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
@ -347,7 +350,7 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
unsigned long pfn;
pfn = pg_off >> PAGE_SHIFT;
if (page_is_ram(pfn))
if (should_use_kmap(pfn))
kunmap(pfn_to_page(pfn));
else
iounmap(vaddr);
@ -554,6 +557,15 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
return AE_OK;
}
acpi_status
acpi_os_physical_table_override(struct acpi_table_header *existing_table,
acpi_physical_address * new_address,
u32 *new_table_length)
{
return AE_SUPPORT;
}
static irqreturn_t acpi_irq(int irq, void *dev_id)
{
u32 handled;
@ -595,7 +607,8 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
acpi_irq_handler = handler;
acpi_irq_context = context;
if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
if (request_threaded_irq(irq, NULL, acpi_irq, IRQF_SHARED, "acpi",
acpi_irq)) {
printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
acpi_irq_handler = NULL;
return AE_NOT_ACQUIRED;
@ -699,49 +712,6 @@ acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
EXPORT_SYMBOL(acpi_os_write_port);
acpi_status
acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
{
void __iomem *virt_addr;
unsigned int size = width / 8;
bool unmap = false;
u32 dummy;
rcu_read_lock();
virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
if (!virt_addr) {
rcu_read_unlock();
virt_addr = acpi_os_ioremap(phys_addr, size);
if (!virt_addr)
return AE_BAD_ADDRESS;
unmap = true;
}
if (!value)
value = &dummy;
switch (width) {
case 8:
*(u8 *) value = readb(virt_addr);
break;
case 16:
*(u16 *) value = readw(virt_addr);
break;
case 32:
*(u32 *) value = readl(virt_addr);
break;
default:
BUG();
}
if (unmap)
iounmap(virt_addr);
else
rcu_read_unlock();
return AE_OK;
}
#ifdef readq
static inline u64 read64(const volatile void __iomem *addr)
{
@ -758,7 +728,7 @@ static inline u64 read64(const volatile void __iomem *addr)
#endif
acpi_status
acpi_os_read_memory64(acpi_physical_address phys_addr, u64 *value, u32 width)
acpi_os_read_memory(acpi_physical_address phys_addr, u64 *value, u32 width)
{
void __iomem *virt_addr;
unsigned int size = width / 8;
@ -803,45 +773,6 @@ acpi_os_read_memory64(acpi_physical_address phys_addr, u64 *value, u32 width)
return AE_OK;
}
acpi_status
acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
{
void __iomem *virt_addr;
unsigned int size = width / 8;
bool unmap = false;
rcu_read_lock();
virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
if (!virt_addr) {
rcu_read_unlock();
virt_addr = acpi_os_ioremap(phys_addr, size);
if (!virt_addr)
return AE_BAD_ADDRESS;
unmap = true;
}
switch (width) {
case 8:
writeb(value, virt_addr);
break;
case 16:
writew(value, virt_addr);
break;
case 32:
writel(value, virt_addr);
break;
default:
BUG();
}
if (unmap)
iounmap(virt_addr);
else
rcu_read_unlock();
return AE_OK;
}
#ifdef writeq
static inline void write64(u64 val, volatile void __iomem *addr)
{
@ -856,7 +787,7 @@ static inline void write64(u64 val, volatile void __iomem *addr)
#endif
acpi_status
acpi_os_write_memory64(acpi_physical_address phys_addr, u64 value, u32 width)
acpi_os_write_memory(acpi_physical_address phys_addr, u64 value, u32 width)
{
void __iomem *virt_addr;
unsigned int size = width / 8;
@ -1641,3 +1572,24 @@ acpi_status acpi_os_terminate(void)
return AE_OK;
}
acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control,
u32 pm1b_control)
{
int rc = 0;
if (__acpi_os_prepare_sleep)
rc = __acpi_os_prepare_sleep(sleep_state,
pm1a_control, pm1b_control);
if (rc < 0)
return AE_ERROR;
else if (rc > 0)
return AE_CTRL_SKIP;
return AE_OK;
}
void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
u32 pm1a_ctrl, u32 pm1b_ctrl))
{
__acpi_os_prepare_sleep = func;
}

View file

@ -40,9 +40,11 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include "sleep.h"
#include "internal.h"
#define PREFIX "ACPI: "
@ -77,6 +79,20 @@ static struct acpi_driver acpi_power_driver = {
},
};
/*
* A power managed device
* A device may rely on multiple power resources.
* */
struct acpi_power_managed_device {
struct device *dev; /* The physical device */
acpi_handle *handle;
};
struct acpi_power_resource_device {
struct acpi_power_managed_device *device;
struct acpi_power_resource_device *next;
};
struct acpi_power_resource {
struct acpi_device * device;
acpi_bus_id name;
@ -84,6 +100,9 @@ struct acpi_power_resource {
u32 order;
unsigned int ref_count;
struct mutex resource_lock;
/* List of devices relying on this power resource */
struct acpi_power_resource_device *devices;
};
static struct list_head acpi_power_resource_list;
@ -183,8 +202,26 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
return 0;
}
/* Resume the device when all power resources in _PR0 are on */
static void acpi_power_on_device(struct acpi_power_managed_device *device)
{
struct acpi_device *acpi_dev;
acpi_handle handle = device->handle;
int state;
if (acpi_bus_get_device(handle, &acpi_dev))
return;
if(acpi_power_get_inferred_state(acpi_dev, &state))
return;
if (state == ACPI_STATE_D0 && pm_runtime_suspended(device->dev))
pm_request_resume(device->dev);
}
static int __acpi_power_on(struct acpi_power_resource *resource)
{
struct acpi_power_resource_device *device_list = resource->devices;
acpi_status status = AE_OK;
status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
@ -197,6 +234,12 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
resource->name));
while (device_list) {
acpi_power_on_device(device_list->device);
device_list = device_list->next;
}
return 0;
}
@ -299,6 +342,125 @@ static int acpi_power_on_list(struct acpi_handle_list *list)
return result;
}
static void __acpi_power_resource_unregister_device(struct device *dev,
acpi_handle res_handle)
{
struct acpi_power_resource *resource = NULL;
struct acpi_power_resource_device *prev, *curr;
if (acpi_power_get_context(res_handle, &resource))
return;
mutex_lock(&resource->resource_lock);
prev = NULL;
curr = resource->devices;
while (curr) {
if (curr->device->dev == dev) {
if (!prev)
resource->devices = curr->next;
else
prev->next = curr->next;
kfree(curr);
break;
}
prev = curr;
curr = curr->next;
}
mutex_unlock(&resource->resource_lock);
}
/* Unlink dev from all power resources in _PR0 */
void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handle)
{
struct acpi_device *acpi_dev;
struct acpi_handle_list *list;
int i;
if (!dev || !handle)
return;
if (acpi_bus_get_device(handle, &acpi_dev))
return;
list = &acpi_dev->power.states[ACPI_STATE_D0].resources;
for (i = 0; i < list->count; i++)
__acpi_power_resource_unregister_device(dev,
list->handles[i]);
}
static int __acpi_power_resource_register_device(
struct acpi_power_managed_device *powered_device, acpi_handle handle)
{
struct acpi_power_resource *resource = NULL;
struct acpi_power_resource_device *power_resource_device;
int result;
result = acpi_power_get_context(handle, &resource);
if (result)
return result;
power_resource_device = kzalloc(
sizeof(*power_resource_device), GFP_KERNEL);
if (!power_resource_device)
return -ENOMEM;
power_resource_device->device = powered_device;
mutex_lock(&resource->resource_lock);
power_resource_device->next = resource->devices;
resource->devices = power_resource_device;
mutex_unlock(&resource->resource_lock);
return 0;
}
/* Link dev to all power resources in _PR0 */
int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
{
struct acpi_device *acpi_dev;
struct acpi_handle_list *list;
struct acpi_power_managed_device *powered_device;
int i, ret;
if (!dev || !handle)
return -ENODEV;
ret = acpi_bus_get_device(handle, &acpi_dev);
if (ret)
goto no_power_resource;
if (!acpi_dev->power.flags.power_resources)
goto no_power_resource;
powered_device = kzalloc(sizeof(*powered_device), GFP_KERNEL);
if (!powered_device)
return -ENOMEM;
powered_device->dev = dev;
powered_device->handle = handle;
list = &acpi_dev->power.states[ACPI_STATE_D0].resources;
for (i = 0; i < list->count; i++) {
ret = __acpi_power_resource_register_device(powered_device,
list->handles[i]);
if (ret) {
acpi_power_resource_unregister_device(dev, handle);
break;
}
}
return ret;
no_power_resource:
printk(KERN_WARNING PREFIX "Invalid Power Resource to register!");
return -ENODEV;
}
/**
* acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
* ACPI 3.0) _PSW (Power State Wake)
@ -500,14 +662,14 @@ int acpi_power_transition(struct acpi_device *device, int state)
{
int result;
if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3))
if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
return -EINVAL;
if (device->power.state == state)
return 0;
if ((device->power.state < ACPI_STATE_D0)
|| (device->power.state > ACPI_STATE_D3))
|| (device->power.state > ACPI_STATE_D3_COLD))
return -ENODEV;
/* TBD: Resources must be ordered. */

View file

@ -46,7 +46,6 @@
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/cpu.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
@ -68,6 +67,7 @@
#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
#define ACPI_PROCESSOR_NOTIFY_POWER 0x81
#define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82
#define ACPI_PROCESSOR_DEVICE_HID "ACPI0007"
#define ACPI_PROCESSOR_LIMIT_USER 0
#define ACPI_PROCESSOR_LIMIT_THERMAL 1
@ -88,7 +88,7 @@ static int acpi_processor_start(struct acpi_processor *pr);
static const struct acpi_device_id processor_device_ids[] = {
{ACPI_PROCESSOR_OBJECT_HID, 0},
{"ACPI0007", 0},
{ACPI_PROCESSOR_DEVICE_HID, 0},
{"", 0},
};
MODULE_DEVICE_TABLE(acpi, processor_device_ids);
@ -474,6 +474,7 @@ static __ref int acpi_processor_start(struct acpi_processor *pr)
#ifdef CONFIG_CPU_FREQ
acpi_processor_ppc_has_changed(pr, 0);
acpi_processor_load_module(pr);
#endif
acpi_processor_get_throttling_info(pr);
acpi_processor_get_limit_info(pr);
@ -535,8 +536,8 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
return -ENOMEM;
if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
kfree(pr);
return -ENOMEM;
result = -ENOMEM;
goto err_free_pr;
}
pr->handle = device->handle;
@ -576,7 +577,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
dev = get_cpu_device(pr->id);
if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) {
result = -EFAULT;
goto err_free_cpumask;
goto err_clear_processor;
}
/*
@ -594,9 +595,15 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
err_remove_sysfs:
sysfs_remove_link(&device->dev.kobj, "sysdev");
err_clear_processor:
/*
* processor_device_array is not cleared to allow checks for buggy BIOS
*/
per_cpu(processors, pr->id) = NULL;
err_free_cpumask:
free_cpumask_var(pr->throttling.shared_cpu_map);
err_free_pr:
kfree(pr);
return result;
}
@ -741,20 +748,46 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
return;
}
static acpi_status is_processor_device(acpi_handle handle)
{
struct acpi_device_info *info;
char *hid;
acpi_status status;
status = acpi_get_object_info(handle, &info);
if (ACPI_FAILURE(status))
return status;
if (info->type == ACPI_TYPE_PROCESSOR) {
kfree(info);
return AE_OK; /* found a processor object */
}
if (!(info->valid & ACPI_VALID_HID)) {
kfree(info);
return AE_ERROR;
}
hid = info->hardware_id.string;
if ((hid == NULL) || strcmp(hid, ACPI_PROCESSOR_DEVICE_HID)) {
kfree(info);
return AE_ERROR;
}
kfree(info);
return AE_OK; /* found a processor device object */
}
static acpi_status
processor_walk_namespace_cb(acpi_handle handle,
u32 lvl, void *context, void **rv)
{
acpi_status status;
int *action = context;
acpi_object_type type = 0;
status = acpi_get_type(handle, &type);
status = is_processor_device(handle);
if (ACPI_FAILURE(status))
return (AE_OK);
if (type != ACPI_TYPE_PROCESSOR)
return (AE_OK);
return AE_OK; /* not a processor; continue to walk */
switch (*action) {
case INSTALL_NOTIFY_HANDLER:
@ -772,7 +805,8 @@ processor_walk_namespace_cb(acpi_handle handle,
break;
}
return (AE_OK);
/* found a processor; skip walking underneath */
return AE_CTRL_DEPTH;
}
static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
@ -830,7 +864,7 @@ void acpi_processor_install_hotplug_notify(void)
{
#ifdef CONFIG_ACPI_HOTPLUG_CPU
int action = INSTALL_NOTIFY_HANDLER;
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
acpi_walk_namespace(ACPI_TYPE_ANY,
ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX,
processor_walk_namespace_cb, NULL, &action, NULL);
@ -843,7 +877,7 @@ void acpi_processor_uninstall_hotplug_notify(void)
{
#ifdef CONFIG_ACPI_HOTPLUG_CPU
int action = UNINSTALL_NOTIFY_HANDLER;
acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
acpi_walk_namespace(ACPI_TYPE_ANY,
ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX,
processor_walk_namespace_cb, NULL, &action, NULL);

View file

@ -1190,8 +1190,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
* to make the code that updates C-States be called once.
*/
if (smp_processor_id() == 0 &&
cpuidle_get_driver() == &acpi_idle_driver) {
if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) {
cpuidle_pause_and_lock();
/* Protect against cpu-hotplug */

View file

@ -240,6 +240,28 @@ void acpi_processor_ppc_exit(void)
acpi_processor_ppc_status &= ~PPC_REGISTERED;
}
/*
* Do a quick check if the systems looks like it should use ACPI
* cpufreq. We look at a _PCT method being available, but don't
* do a whole lot of sanity checks.
*/
void acpi_processor_load_module(struct acpi_processor *pr)
{
static int requested;
acpi_status status = 0;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
if (!arch_has_acpi_pdc() || requested)
return;
status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer);
if (!ACPI_FAILURE(status)) {
printk(KERN_INFO PREFIX "Requesting acpi_cpufreq\n");
request_module_nowait("acpi_cpufreq");
requested = 1;
}
kfree(buffer.pointer);
}
static int acpi_processor_get_performance_control(struct acpi_processor *pr)
{
int result = 0;

View file

@ -57,6 +57,27 @@ ACPI_MODULE_NAME("processor_thermal");
static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg);
static unsigned int acpi_thermal_cpufreq_is_init = 0;
#define reduction_pctg(cpu) \
per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu))
/*
* Emulate "per package data" using per cpu data (which should really be
* provided elsewhere)
*
* Note we can lose a CPU on cpu hotunplug, in this case we forget the state
* temporarily. Fortunately that's not a big issue here (I hope)
*/
static int phys_package_first_cpu(int cpu)
{
int i;
int id = topology_physical_package_id(cpu);
for_each_online_cpu(i)
if (topology_physical_package_id(i) == id)
return i;
return 0;
}
static int cpu_has_cpufreq(unsigned int cpu)
{
struct cpufreq_policy policy;
@ -76,7 +97,7 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
max_freq = (
policy->cpuinfo.max_freq *
(100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20)
(100 - reduction_pctg(policy->cpu) * 20)
) / 100;
cpufreq_verify_within_limits(policy, 0, max_freq);
@ -102,16 +123,28 @@ static int cpufreq_get_cur_state(unsigned int cpu)
if (!cpu_has_cpufreq(cpu))
return 0;
return per_cpu(cpufreq_thermal_reduction_pctg, cpu);
return reduction_pctg(cpu);
}
static int cpufreq_set_cur_state(unsigned int cpu, int state)
{
int i;
if (!cpu_has_cpufreq(cpu))
return 0;
per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state;
cpufreq_update_policy(cpu);
reduction_pctg(cpu) = state;
/*
* Update all the CPUs in the same package because they all
* contribute to the temperature and often share the same
* frequency.
*/
for_each_online_cpu(i) {
if (topology_physical_package_id(i) ==
topology_physical_package_id(cpu))
cpufreq_update_policy(i);
}
return 0;
}
@ -119,10 +152,6 @@ void acpi_thermal_cpufreq_init(void)
{
int i;
for (i = 0; i < nr_cpu_ids; i++)
if (cpu_present(i))
per_cpu(cpufreq_thermal_reduction_pctg, i) = 0;
i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
CPUFREQ_POLICY_NOTIFIER);
if (!i)

View file

@ -769,7 +769,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr,
u64 *value)
{
u32 bit_width, bit_offset;
u64 ptc_value;
u32 ptc_value;
u64 ptc_mask;
struct acpi_processor_throttling *throttling;
int ret = -1;
@ -777,12 +777,11 @@ static int acpi_read_throttling_status(struct acpi_processor *pr,
throttling = &pr->throttling;
switch (throttling->status_register.space_id) {
case ACPI_ADR_SPACE_SYSTEM_IO:
ptc_value = 0;
bit_width = throttling->status_register.bit_width;
bit_offset = throttling->status_register.bit_offset;
acpi_os_read_port((acpi_io_address) throttling->status_register.
address, (u32 *) &ptc_value,
address, &ptc_value,
(u32) (bit_width + bit_offset));
ptc_mask = (1 << bit_width) - 1;
*value = (u64) ((ptc_value >> bit_offset) & ptc_mask);

View file

@ -23,8 +23,7 @@ void acpi_reboot(void)
/* Is the reset register supported? The spec says we should be
* checking the bit width and bit offset, but Windows ignores
* these fields */
if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
return;
/* Ignore also acpi_gbl_FADT.flags.ACPI_FADT_RESET_REGISTER */
reset_value = acpi_gbl_FADT.reset_value;

View file

@ -880,18 +880,22 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
int j;
device->power.flags.power_resources = 1;
ps->flags.valid = 1;
for (j = 0; j < ps->resources.count; j++)
acpi_bus_add_power_resource(ps->resources.handles[j]);
}
/* The exist of _PR3 indicates D3Cold support */
if (i == ACPI_STATE_D3) {
status = acpi_get_handle(device->handle, object_name, &handle);
if (ACPI_SUCCESS(status))
device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
}
/* Evaluate "_PSx" to see if we can do explicit sets */
object_name[2] = 'S';
status = acpi_get_handle(device->handle, object_name, &handle);
if (ACPI_SUCCESS(status)) {
if (ACPI_SUCCESS(status))
ps->flags.explicit_set = 1;
ps->flags.valid = 1;
}
/* State is valid if we have some power control */
if (ps->resources.count || ps->flags.explicit_set)

View file

@ -17,6 +17,8 @@
#include <linux/suspend.h>
#include <linux/reboot.h>
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <asm/io.h>
@ -26,6 +28,24 @@
#include "internal.h"
#include "sleep.h"
static unsigned int gts, bfs;
module_param(gts, uint, 0644);
module_param(bfs, uint, 0644);
MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend.");
MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".);
static u8 wake_sleep_flags(void)
{
u8 flags = ACPI_NO_OPTIONAL_METHODS;
if (gts)
flags |= ACPI_EXECUTE_GTS;
if (bfs)
flags |= ACPI_EXECUTE_BFS;
return flags;
}
static u8 sleep_states[ACPI_S_STATE_COUNT];
static void acpi_sleep_tts_switch(u32 acpi_state)
@ -243,6 +263,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
{
acpi_status status = AE_OK;
u32 acpi_state = acpi_target_sleep_state;
u8 flags = wake_sleep_flags();
int error;
ACPI_FLUSH_CPU_CACHE();
@ -250,7 +271,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
switch (acpi_state) {
case ACPI_STATE_S1:
barrier();
status = acpi_enter_sleep_state(acpi_state);
status = acpi_enter_sleep_state(acpi_state, flags);
break;
case ACPI_STATE_S3:
@ -265,7 +286,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(acpi_state);
acpi_leave_sleep_state_prep(acpi_state, flags);
/* ACPI 3.0 specs (P62) says that it's the responsibility
* of the OSPM to clear the status bit [ implying that the
@ -529,27 +550,30 @@ static int acpi_hibernation_begin(void)
static int acpi_hibernation_enter(void)
{
u8 flags = wake_sleep_flags();
acpi_status status = AE_OK;
ACPI_FLUSH_CPU_CACHE();
/* This shouldn't return. If it returns, we have a problem */
status = acpi_enter_sleep_state(ACPI_STATE_S4);
status = acpi_enter_sleep_state(ACPI_STATE_S4, flags);
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(ACPI_STATE_S4);
acpi_leave_sleep_state_prep(ACPI_STATE_S4, flags);
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
static void acpi_hibernation_leave(void)
{
u8 flags = wake_sleep_flags();
/*
* If ACPI is not enabled by the BIOS and the boot kernel, we need to
* enable it here.
*/
acpi_enable();
/* Reprogram control registers and execute _BFS */
acpi_leave_sleep_state_prep(ACPI_STATE_S4);
acpi_leave_sleep_state_prep(ACPI_STATE_S4, flags);
/* Check the hardware signature */
if (facs && s4_hardware_signature != facs->hardware_signature) {
printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
@ -729,6 +753,40 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
#endif /* CONFIG_PM */
#ifdef CONFIG_PM_SLEEP
/**
* acpi_pm_device_run_wake - Enable/disable wake-up for given device.
* @phys_dev: Device to enable/disable the platform to wake-up the system for.
* @enable: Whether enable or disable the wake-up functionality.
*
* Find the ACPI device object corresponding to @pci_dev and try to
* enable/disable the GPE associated with it.
*/
int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
{
struct acpi_device *dev;
acpi_handle handle;
if (!device_run_wake(phys_dev))
return -EINVAL;
handle = DEVICE_ACPI_HANDLE(phys_dev);
if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) {
dev_dbg(phys_dev, "ACPI handle has no context in %s!\n",
__func__);
return -ENODEV;
}
if (enable) {
acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0);
acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
} else {
acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
acpi_disable_wakeup_device_power(dev);
}
return 0;
}
/**
* acpi_pm_device_sleep_wake - enable or disable the system wake-up
* capability of given device
@ -770,10 +828,12 @@ static void acpi_power_off_prepare(void)
static void acpi_power_off(void)
{
u8 flags = wake_sleep_flags();
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
printk(KERN_DEBUG "%s called\n", __func__);
local_irq_disable();
acpi_enter_sleep_state(ACPI_STATE_S5);
acpi_enter_sleep_state(ACPI_STATE_S5, flags);
}
/*
@ -788,13 +848,13 @@ static void __init acpi_gts_bfs_check(void)
{
acpi_handle dummy;
if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_NAME__GTS, &dummy)))
if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__GTS, &dummy)))
{
printk(KERN_NOTICE PREFIX "BIOS offers _GTS\n");
printk(KERN_NOTICE PREFIX "If \"acpi.gts=1\" improves suspend, "
"please notify [email protected]\n");
}
if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_NAME__BFS, &dummy)))
if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__BFS, &dummy)))
{
printk(KERN_NOTICE PREFIX "BIOS offers _BFS\n");
printk(KERN_NOTICE PREFIX "If \"acpi.bfs=1\" improves resume, "

View file

@ -941,13 +941,13 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
if (!tz)
return -EINVAL;
/* Get temperature [_TMP] (required) */
result = acpi_thermal_get_temperature(tz);
/* Get trip points [_CRT, _PSV, etc.] (required) */
result = acpi_thermal_get_trip_points(tz);
if (result)
return result;
/* Get trip points [_CRT, _PSV, etc.] (required) */
result = acpi_thermal_get_trip_points(tz);
/* Get temperature [_TMP] (required) */
result = acpi_thermal_get_temperature(tz);
if (result)
return result;

View file

@ -548,27 +548,27 @@ acpi_video_device_EDID(struct acpi_video_device *device,
* 1. The system BIOS should NOT automatically control the brightness
* level of the LCD when the power changes from AC to DC.
* Return Value:
* -1 wrong arg.
* -EINVAL wrong arg.
*/
static int
acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
{
u64 status = 0;
acpi_status status;
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list args = { 1, &arg0 };
if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) {
status = -1;
goto Failed;
}
if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1)
return -EINVAL;
arg0.integer.value = (lcd_flag << 2) | bios_flag;
video->dos_setting = arg0.integer.value;
acpi_evaluate_object(video->device->handle, "_DOS", &args, NULL);
status = acpi_evaluate_object(video->device->handle, "_DOS",
&args, NULL);
if (ACPI_FAILURE(status))
return -EIO;
Failed:
return status;
return 0;
}
/*
@ -1343,15 +1343,17 @@ static int
acpi_video_bus_get_devices(struct acpi_video_bus *video,
struct acpi_device *device)
{
int status = 0;
int status;
struct acpi_device *dev;
acpi_video_device_enumerate(video);
status = acpi_video_device_enumerate(video);
if (status)
return status;
list_for_each_entry(dev, &device->children, node) {
status = acpi_video_bus_get_one_device(dev, video);
if (ACPI_FAILURE(status)) {
if (status) {
printk(KERN_WARNING PREFIX
"Can't attach device\n");
continue;
@ -1653,15 +1655,20 @@ static int acpi_video_bus_add(struct acpi_device *device)
mutex_init(&video->device_list_lock);
INIT_LIST_HEAD(&video->video_device_list);
acpi_video_bus_get_devices(video, device);
acpi_video_bus_start_devices(video);
error = acpi_video_bus_get_devices(video, device);
if (error)
goto err_free_video;
video->input = input = input_allocate_device();
if (!input) {
error = -ENOMEM;
goto err_stop_video;
goto err_put_video;
}
error = acpi_video_bus_start_devices(video);
if (error)
goto err_free_input_dev;
snprintf(video->phys, sizeof(video->phys),
"%s/video/input0", acpi_device_hid(video->device));
@ -1682,7 +1689,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
error = input_register_device(input);
if (error)
goto err_free_input_dev;
goto err_stop_video;
printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
@ -1692,14 +1699,19 @@ static int acpi_video_bus_add(struct acpi_device *device)
video->pm_nb.notifier_call = acpi_video_resume;
video->pm_nb.priority = 0;
register_pm_notifier(&video->pm_nb);
error = register_pm_notifier(&video->pm_nb);
if (error)
goto err_unregister_input_dev;
return 0;
err_free_input_dev:
input_free_device(input);
err_unregister_input_dev:
input_unregister_device(input);
err_stop_video:
acpi_video_bus_stop_devices(video);
err_free_input_dev:
input_free_device(input);
err_put_video:
acpi_video_bus_put_devices(video);
kfree(video->attached_array);
err_free_video:

View file

@ -23,7 +23,7 @@
* Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B)
* are available, video.ko should be used to handle the device.
*
* Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi,
* Otherwise vendor specific drivers like thinkpad_acpi, asus-laptop,
* sony_acpi,... can take care about backlight brightness.
*
* If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m)