提交 474829e8 编写于 作者: L Linus Torvalds

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

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (53 commits)
  ACPI: install ACPI table handler before any dynamic tables being loaded
  ACPI / PM: Blacklist another machine that needs acpi_sleep=nonvs
  ACPI: Page based coalescing of I/O remappings optimization
  ACPI: Convert simple locking to RCU based locking
  ACPI: Pre-map 'system event' related register blocks
  ACPI: Add interfaces for ioremapping/iounmapping ACPI registers
  ACPI: Maintain a list of ACPI memory mapped I/O remappings
  ACPI: Fix ioremap size for MMIO reads and writes
  ACPI / Battery: Return -ENODEV for unknown values in get_property()
  ACPI / PM: Fix reference counting of power resources
  Subject: [PATCH] ACPICA: Fix Scope() op in module level code
  ACPI battery: support percentage battery remaining capacity
  ACPI: Make Embedded Controller command timeout delay configurable
  ACPI dock: move some functions to .init.text
  ACPI: thermal: remove unused limit code
  ACPI: static sleep_states[] and acpi_gts_bfs_check
  ACPI: remove dead code
  ACPI: delete dedicated MAINTAINERS entries for ACPI EC and BATTERY drivers
  ACPI: Only processor needs CPU_IDLE
  ACPICA: Update version to 20101013
  ...
......@@ -243,21 +243,6 @@ F: drivers/pnp/pnpacpi/
F: include/linux/acpi.h
F: include/acpi/
ACPI BATTERY DRIVERS
M: Alexey Starikovskiy <astarikovskiy@suse.de>
L: linux-acpi@vger.kernel.org
W: http://www.lesswatts.org/projects/acpi/
S: Supported
F: drivers/acpi/battery.c
F: drivers/acpi/*sbs*
ACPI EC DRIVER
M: Alexey Starikovskiy <astarikovskiy@suse.de>
L: linux-acpi@vger.kernel.org
W: http://www.lesswatts.org/projects/acpi/
S: Supported
F: drivers/acpi/ec.c
ACPI FAN DRIVER
M: Zhang Rui <rui.zhang@intel.com>
L: linux-acpi@vger.kernel.org
......
......@@ -701,6 +701,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
per_cpu(acfreq_data, policy->cpu) = NULL;
acpi_processor_unregister_performance(data->acpi_data,
policy->cpu);
kfree(data->freq_table);
kfree(data);
}
......
......@@ -9,7 +9,6 @@ menuconfig ACPI
depends on PCI
depends on PM
select PNP
select CPU_IDLE
default y
help
Advanced Configuration and Power Interface (ACPI) support for
......@@ -66,7 +65,6 @@ config ACPI_PROCFS
config ACPI_PROCFS_POWER
bool "Deprecated power /proc/acpi directories"
depends on PROC_FS
default y
help
For backwards compatibility, this option allows
deprecated power /proc/acpi/ directories to exist, even when
......@@ -90,13 +88,6 @@ config ACPI_POWER_METER
To compile this driver as a module, choose M here:
the module will be called power-meter.
config ACPI_SYSFS_POWER
bool "Future power /sys interface"
select POWER_SUPPLY
default y
help
Say N to disable power /sys interface
config ACPI_EC_DEBUGFS
tristate "EC read/write access through /sys/kernel/debug/ec"
default n
......@@ -136,6 +127,7 @@ config ACPI_PROC_EVENT
config ACPI_AC
tristate "AC Adapter"
depends on X86
select POWER_SUPPLY
default y
help
This driver supports the AC Adapter object, which indicates
......@@ -148,6 +140,7 @@ config ACPI_AC
config ACPI_BATTERY
tristate "Battery"
depends on X86
select POWER_SUPPLY
default y
help
This driver adds support for battery information through
......@@ -206,6 +199,7 @@ config ACPI_DOCK
config ACPI_PROCESSOR
tristate "Processor"
select THERMAL
select CPU_IDLE
default y
help
This driver installs ACPI as the idle handler for Linux and uses
......@@ -364,6 +358,7 @@ config ACPI_HOTPLUG_MEMORY
config ACPI_SBS
tristate "Smart Battery System"
depends on X86
select POWER_SUPPLY
help
This driver supports the Smart Battery System, another
type of access to battery information, found on some laptops.
......
......@@ -32,9 +32,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#endif
#ifdef CONFIG_ACPI_SYSFS_POWER
#include <linux/power_supply.h>
#endif
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
......@@ -86,9 +84,7 @@ static struct acpi_driver acpi_ac_driver = {
};
struct acpi_ac {
#ifdef CONFIG_ACPI_SYSFS_POWER
struct power_supply charger;
#endif
struct acpi_device * device;
unsigned long long state;
};
......@@ -104,7 +100,6 @@ static const struct file_operations acpi_ac_fops = {
.release = single_release,
};
#endif
#ifdef CONFIG_ACPI_SYSFS_POWER
static int get_ac_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
......@@ -123,7 +118,6 @@ static int get_ac_property(struct power_supply *psy,
static enum power_supply_property ac_props[] = {
POWER_SUPPLY_PROP_ONLINE,
};
#endif
/* --------------------------------------------------------------------------
AC Adapter Management
-------------------------------------------------------------------------- */
......@@ -247,9 +241,7 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
dev_name(&device->dev), event,
(u32) ac->state);
acpi_notifier_call_chain(device, event, (u32) ac->state);
#ifdef CONFIG_ACPI_SYSFS_POWER
kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
#endif
}
return;
......@@ -282,14 +274,12 @@ static int acpi_ac_add(struct acpi_device *device)
#endif
if (result)
goto end;
#ifdef CONFIG_ACPI_SYSFS_POWER
ac->charger.name = acpi_device_bid(device);
ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
ac->charger.properties = ac_props;
ac->charger.num_properties = ARRAY_SIZE(ac_props);
ac->charger.get_property = get_ac_property;
power_supply_register(&ac->device->dev, &ac->charger);
#endif
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
acpi_device_name(device), acpi_device_bid(device),
......@@ -316,10 +306,8 @@ static int acpi_ac_resume(struct acpi_device *device)
old_state = ac->state;
if (acpi_ac_get_state(ac))
return 0;
#ifdef CONFIG_ACPI_SYSFS_POWER
if (old_state != ac->state)
kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
#endif
return 0;
}
......@@ -333,10 +321,8 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
ac = acpi_driver_data(device);
#ifdef CONFIG_ACPI_SYSFS_POWER
if (ac->charger.dev)
power_supply_unregister(&ac->charger);
#endif
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_remove_fs(device);
#endif
......
......@@ -21,7 +21,7 @@ acpi-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\
excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \
exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o exdebug.o
acpi-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o
acpi-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o hwpci.o
acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
......@@ -44,4 +44,5 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o
utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \
utosi.o utxferror.o
......@@ -105,6 +105,8 @@ void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg);
acpi_status
acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
acpi_status acpi_db_find_name_in_namespace(char *name_arg);
void acpi_db_set_scope(char *name);
......
......@@ -105,8 +105,9 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
struct acpi_gpe_block_info **return_gpe_block);
acpi_status
acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
struct acpi_gpe_block_info *gpe_block);
acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *ignored);
acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block);
......
......@@ -132,6 +132,7 @@ struct acpi_table_fadt acpi_gbl_FADT;
u32 acpi_current_gpe_count;
u32 acpi_gbl_trace_flags;
acpi_name acpi_gbl_trace_method_name;
u8 acpi_gbl_system_awake_and_running;
#endif
......@@ -187,6 +188,10 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width;
ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
/* Mutex for _OSI support */
ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex;
/* Reader/Writer lock is used for namespace walk and dynamic table unload */
ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock;
......@@ -255,6 +260,7 @@ ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler;
ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler;
ACPI_EXTERN void *acpi_gbl_table_handler_context;
ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler;
/* Owner ID support */
......@@ -273,8 +279,8 @@ ACPI_EXTERN u8 acpi_gbl_debugger_configuration;
ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
ACPI_EXTERN u8 acpi_gbl_events_initialized;
ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
ACPI_EXTERN u8 acpi_gbl_osi_data;
ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces;
#ifndef DEFINE_ACPI_GLOBALS
......@@ -364,6 +370,7 @@ 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];
ACPI_EXTERN u8 acpi_all_gpes_initialized;
/*****************************************************************************
*
......
......@@ -121,6 +121,13 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *context);
/*
* hwpci - PCI configuration support
*/
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
......
......@@ -413,6 +413,7 @@ struct acpi_handler_info {
void *context; /* Context to be passed to handler */
struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */
u8 orig_flags; /* Original misc info about this GPE */
u8 orig_enabled; /* Set if the GPE was originally enabled */
};
union acpi_gpe_dispatch_info {
......@@ -457,6 +458,7 @@ struct acpi_gpe_block_info {
u32 register_count; /* Number of register pairs in block */
u16 gpe_count; /* Number of individual GPEs in block */
u8 block_base_number; /* Base GPE number for this block */
u8 initialized; /* If set, the GPE block has been initialized */
};
/* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */
......@@ -473,7 +475,6 @@ struct acpi_gpe_walk_info {
struct acpi_gpe_block_info *gpe_block;
u16 count;
acpi_owner_id owner_id;
u8 enable_this_gpe;
u8 execute_by_owner_id;
};
......@@ -854,7 +855,7 @@ struct acpi_bit_register_info {
ACPI_BITMASK_POWER_BUTTON_STATUS | \
ACPI_BITMASK_SLEEP_BUTTON_STATUS | \
ACPI_BITMASK_RT_CLOCK_STATUS | \
ACPI_BITMASK_PCIEXP_WAKE_DISABLE | \
ACPI_BITMASK_PCIEXP_WAKE_STATUS | \
ACPI_BITMASK_WAKE_STATUS)
#define ACPI_BITMASK_TIMER_ENABLE 0x0001
......@@ -909,15 +910,21 @@ struct acpi_bit_register_info {
#define ACPI_OSI_WIN_VISTA 0x07
#define ACPI_OSI_WINSRV_2008 0x08
#define ACPI_OSI_WIN_VISTA_SP1 0x09
#define ACPI_OSI_WIN_7 0x0A
#define ACPI_OSI_WIN_VISTA_SP2 0x0A
#define ACPI_OSI_WIN_7 0x0B
#define ACPI_ALWAYS_ILLEGAL 0x00
struct acpi_interface_info {
char *name;
struct acpi_interface_info *next;
u8 flags;
u8 value;
};
#define ACPI_OSI_INVALID 0x01
#define ACPI_OSI_DYNAMIC 0x02
struct acpi_port_info {
char *name;
u16 start;
......@@ -997,7 +1004,7 @@ struct acpi_port_info {
struct acpi_db_method_info {
acpi_handle main_thread_gate;
acpi_handle thread_complete_gate;
u32 *threads;
acpi_thread_id *threads;
u32 num_threads;
u32 num_created;
u32 num_completed;
......
......@@ -338,8 +338,8 @@
* the plist contains a set of parens to allow variable-length lists.
* These macros are used for both the debug and non-debug versions of the code.
*/
#define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e);
#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e);
#define ACPI_ERROR_NAMESPACE(s, e) acpi_ut_namespace_error (AE_INFO, s, e);
#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ut_method_error (AE_INFO, s, n, p, e);
#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist
#define ACPI_INFO_PREDEFINED(plist) acpi_ut_predefined_info plist
......
......@@ -338,18 +338,6 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node *node);
u32 acpi_ns_local(acpi_object_type type);
void
acpi_ns_report_error(const char *module_name,
u32 line_number,
const char *internal_name, acpi_status lookup_status);
void
acpi_ns_report_method_error(const char *module_name,
u32 line_number,
const char *message,
struct acpi_namespace_node *node,
const char *path, acpi_status lookup_status);
void
acpi_ns_print_node_pathname(struct acpi_namespace_node *node, const char *msg);
......
......@@ -248,7 +248,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
u32 base_byte_offset; /* Byte offset within containing object */\
u32 value; /* Value to store into the Bank or Index register */\
u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
u8 access_bit_width; /* Read/Write size in bits (8-64) */
struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */
......
......@@ -312,8 +312,6 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list);
/*
* uteval - object evaluation
*/
acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
acpi_status
acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
char *path,
......@@ -394,6 +392,21 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size);
acpi_status
acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length);
/*
* utosi - Support for the _OSI predefined control method
*/
acpi_status acpi_ut_initialize_interfaces(void);
void acpi_ut_interface_terminate(void);
acpi_status acpi_ut_install_interface(acpi_string interface_name);
acpi_status acpi_ut_remove_interface(acpi_string interface_name);
struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name);
acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
/*
* utstate - Generic state creation/cache routines
*/
......@@ -473,17 +486,6 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position);
acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer);
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_warning(const char *module_name,
u32 line_number,
char *pathname,
u8 node_flags, const char *format, ...);
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_info(const char *module_name,
u32 line_number,
char *pathname, u8 node_flags, const char *format, ...);
/* Values for Base above (16=Hex, 10=Decimal) */
#define ACPI_ANY_BASE 0
......@@ -574,6 +576,32 @@ acpi_status
acpi_ut_create_list(char *list_name,
u16 object_size, struct acpi_memory_list **return_cache);
#endif
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
/*
* utxferror - various error/warning output functions
*/
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_warning(const char *module_name,
u32 line_number,
char *pathname,
u8 node_flags, const char *format, ...);
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_info(const char *module_name,
u32 line_number,
char *pathname, u8 node_flags, const char *format, ...);
void
acpi_ut_namespace_error(const char *module_name,
u32 line_number,
const char *internal_name, acpi_status lookup_status);
void
acpi_ut_method_error(const char *module_name,
u32 line_number,
const char *message,
struct acpi_namespace_node *node,
const char *path, acpi_status lookup_status);
#endif /* _ACUTILS_H */
......@@ -573,7 +573,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
acpi_os_release_mutex(method_desc->method.
mutex->mutex.os_mutex);
method_desc->method.mutex->mutex.thread_id = NULL;
method_desc->method.mutex->mutex.thread_id = 0;
}
}
......
......@@ -300,10 +300,25 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
* we must enter this object into the namespace. The created
* object is temporary and will be deleted upon completion of
* the execution of this method.
*
* Note 10/2010: Except for the Scope() op. This opcode does
* not actually create a new object, it refers to an existing
* object. However, for Scope(), we want to indeed open a
* new scope.
*/
status = acpi_ds_load2_begin_op(walk_state, NULL);
if (op->common.aml_opcode != AML_SCOPE_OP) {
status =
acpi_ds_load2_begin_op(walk_state, NULL);
} else {
status =
acpi_ds_scope_stack_push(op->named.node,
op->named.node->
type, walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
}
}
break;
case AML_CLASS_EXECUTE:
......
......@@ -93,47 +93,6 @@ acpi_status acpi_ev_initialize_events(void)
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_fadt_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Completes initialization of the FADT-defined GPE blocks
* (0 and 1). The HW must be fully initialized at this point,
* including global lock support.
*
******************************************************************************/
acpi_status acpi_ev_install_fadt_gpes(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(ev_install_fadt_gpes);
/* Namespace must be locked */
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
return (status);
}
/* FADT GPE Block 0 */
(void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
acpi_gbl_gpe_fadt_blocks[0]);
/* FADT GPE Block 1 */
(void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
acpi_gbl_gpe_fadt_blocks[1]);
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_xrupt_handlers
......
......@@ -363,6 +363,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number;
gpe_block->initialized = FALSE;
ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
sizeof(struct acpi_generic_address));
......@@ -385,11 +386,12 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
return_ACPI_STATUS(status);
}
acpi_all_gpes_initialized = FALSE;
/* Find all GPE methods (_Lxx or_Exx) for this block */
walk_info.gpe_block = gpe_block;
walk_info.gpe_device = gpe_device;
walk_info.enable_this_gpe = FALSE;
walk_info.execute_by_owner_id = FALSE;
status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
......@@ -434,35 +436,34 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
******************************************************************************/
acpi_status
acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
struct acpi_gpe_block_info *gpe_block)
acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block,
void *ignored)
{
acpi_status status;
struct acpi_gpe_event_info *gpe_event_info;
u32 gpe_enabled_count;
u32 gpe_index;
u32 gpe_number;
u32 i;
u32 j;
ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
/* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
if (!gpe_block) {
/*
* Ignore a null GPE block (e.g., if no GPE block 1 exists) and
* GPE blocks that have been initialized already.
*/
if (!gpe_block || gpe_block->initialized) {
return_ACPI_STATUS(AE_OK);
}
/*
* Enable all GPEs that have a corresponding method. Any other GPEs
* within this block must be enabled via the acpi_enable_gpe interface.
* Enable all GPEs that have a corresponding method and have the
* ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block must
* be enabled via the acpi_enable_gpe() interface.
*/
gpe_enabled_count = 0;
if (gpe_device == acpi_gbl_fadt_gpe_device) {
gpe_device = NULL;
}
for (i = 0; i < gpe_block->register_count; i++) {
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
......@@ -470,27 +471,19 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
gpe_event_info = &gpe_block->event_info[gpe_index];
gpe_number = gpe_index + gpe_block->block_base_number;
/* Ignore GPEs that have no corresponding _Lxx/_Exx method */
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) {
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
|| (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
continue;
}
/*
* If the GPE has already been enabled for runtime
* signaling, make sure it remains enabled, but do not
* increment its reference counter.
*/
status = gpe_event_info->runtime_count ?
acpi_ev_enable_gpe(gpe_event_info) :
acpi_enable_gpe(gpe_device, gpe_number);
status = acpi_raw_enable_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not enable GPE 0x%02X",
gpe_number));
"Could not enable GPE 0x%02X",
gpe_index + gpe_block->block_base_number));
continue;
}
......@@ -504,5 +497,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_enabled_count));
}
gpe_block->initialized = TRUE;
return_ACPI_STATUS(AE_OK);
}
......@@ -210,8 +210,7 @@ acpi_status acpi_ev_gpe_initialize(void)
*
* DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
* result of a Load() or load_table() operation. If new GPE
* methods have been installed, register the new methods and
* enable and runtime GPEs that are associated with them.
* methods have been installed, register the new methods.
*
******************************************************************************/
......@@ -239,7 +238,6 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
walk_info.owner_id = table_owner_id;
walk_info.execute_by_owner_id = TRUE;
walk_info.count = 0;
walk_info.enable_this_gpe = TRUE;
/* Walk the interrupt level descriptor list */
......@@ -301,8 +299,6 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
*
* If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods
* with that owner.
* If walk_info->enable_this_gpe is TRUE, the GPE that is referred to by a GPE
* method is immediately enabled (Used for Load/load_table operators)
*
******************************************************************************/
......@@ -315,8 +311,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
struct acpi_gpe_walk_info *walk_info =
ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_namespace_node *gpe_device;
acpi_status status;
u32 gpe_number;
char name[ACPI_NAME_SIZE + 1];
u8 type;
......@@ -421,29 +415,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
gpe_event_info->dispatch.method_node = method_node;
/*
* Enable this GPE if requested. This only happens when during the
* execution of a Load or load_table operator. We have found a new
* GPE method and want to immediately enable the GPE if it is a
* runtime GPE.
*/
if (walk_info->enable_this_gpe) {
walk_info->count++;
gpe_device = walk_info->gpe_device;
if (gpe_device == acpi_gbl_fadt_gpe_device) {
gpe_device = NULL;
}
status = acpi_enable_gpe(gpe_device, gpe_number);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Could not enable GPE 0x%02X",
gpe_number));
}
}
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
"Registered GPE method %s as GPE number 0x%.2X\n",
name, gpe_number));
......
......@@ -553,7 +553,7 @@ acpi_status acpi_ev_release_global_lock(void)
acpi_gbl_global_lock_acquired = FALSE;
/* Release the local GL mutex */
acpi_ev_global_lock_thread_id = NULL;
acpi_ev_global_lock_thread_id = 0;
acpi_ev_global_lock_acquired = 0;
acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex);
return_ACPI_STATUS(status);
......
......@@ -289,8 +289,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
}
/*
* Get the PCI device and function numbers from the _ADR object contained
* in the parent's scope.
* Get the PCI device and function numbers from the _ADR object
* contained in the parent's scope.
*/
status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
pci_device_node, &pci_value);
......@@ -320,9 +320,15 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
pci_id->bus = ACPI_LOWORD(pci_value);
}
/* Complete this device's pci_id */
/* Complete/update the PCI ID for this device */
acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id);
status =
acpi_hw_derive_pci_id(pci_id, pci_root_node,
region_obj->region.node);
if (ACPI_FAILURE(status)) {
ACPI_FREE(pci_id);
return_ACPI_STATUS(status);
}
*region_context = pci_id;
return_ACPI_STATUS(AE_OK);
......
......@@ -726,15 +726,16 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
/*
* If the GPE is associated with a method and it cannot wake up the
* system from sleep states, it was enabled automatically during
* initialization, so it has to be disabled now to avoid spurious
* execution of the handler.
* If the GPE is associated with a method, it might have been enabled
* automatically during initialization, in which case it has to be
* disabled now to avoid spurious execution of the handler.
*/
if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
&& !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
&& gpe_event_info->runtime_count) {
handler->orig_enabled = 1;
(void)acpi_raw_disable_gpe(gpe_event_info);
}
/* Install the handler */
......@@ -837,13 +838,13 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
gpe_event_info->flags |= handler->orig_flags;
/*
* If the GPE was previously associated with a method and it cannot wake
* up the system from sleep states, it should be enabled at this point
* to restore the post-initialization configuration.
* If the GPE was previously associated with a method and it was
* enabled, it should be enabled at this point to restore the
* post-initialization configuration.
*/
if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
&& !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
&& handler->orig_enabled)
(void)acpi_raw_enable_gpe(gpe_event_info);
/* Now we can free the handler object */
......
......@@ -379,21 +379,12 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
/* Ensure that we have a valid GPE number */
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
if (gpe_event_info) {
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
} else {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
goto unlock_and_exit;
}
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) {
(void)acpi_raw_disable_gpe(gpe_event_info);
}
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
......@@ -651,7 +642,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
struct acpi_generic_address *gpe_block_address,
u32 register_count, u32 interrupt_number)
{
acpi_status status;
acpi_status status = AE_OK;
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
struct acpi_gpe_block_info *gpe_block;
......@@ -715,10 +706,6 @@ acpi_install_gpe_block(acpi_handle gpe_device,
obj_desc->device.gpe_block = gpe_block;
/* Enable the runtime GPEs in the new block */
status = acpi_ev_initialize_gpe_block(node, gpe_block);
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
......@@ -924,3 +911,43 @@ acpi_status acpi_enable_all_runtime_gpes(void)
return_ACPI_STATUS(status);
}
/******************************************************************************
*
* FUNCTION: acpi_update_gpes
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and
* are not pointed to by any device _PRW methods indicating that
* these GPEs are generally intended for system or device wakeup
* (such GPEs have to be enabled directly when the devices whose
* _PRW methods point to them are set up for wakeup signaling).
*
******************************************************************************/
acpi_status acpi_update_gpes(void)
{
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_update_gpes);
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
} else if (acpi_all_gpes_initialized) {
goto unlock;
}
status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
if (ACPI_SUCCESS(status)) {
acpi_all_gpes_initialized = TRUE;
}
unlock:
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
return_ACPI_STATUS(status);
}
......@@ -64,6 +64,12 @@ ACPI_MODULE_NAME("evxfregn")
*
* DESCRIPTION: Install a handler for all op_regions of a given space_id.
*
* NOTE: This function should only be called after acpi_enable_subsystem has
* been called. This is because any _REG methods associated with the Space ID
* are executed here, and these methods can only be safely executed after
* the default handlers have been installed and the hardware has been
* initialized (via acpi_enable_subsystem.)
*
******************************************************************************/
acpi_status
acpi_install_address_space_handler(acpi_handle device,
......
......@@ -119,8 +119,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
}
/*
* Exit now for SMBus or IPMI address space, it has a non-linear address space
* and the request cannot be directly validated
* Exit now for SMBus or IPMI address space, it has a non-linear
* address space and the request cannot be directly validated
*/
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
......@@ -147,8 +147,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
* (Region length is specified in bytes)
*/
if (rgn_desc->region.length <
(obj_desc->common_field.base_byte_offset +
field_datum_byte_offset +
(obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
obj_desc->common_field.access_byte_width)) {
if (acpi_gbl_enable_interpreter_slack) {
/*
......@@ -680,6 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
u32 buffer_tail_bits;
u32 datum_count;
u32 field_datum_count;
u32 access_bit_width;
u32 i;
ACPI_FUNCTION_TRACE(ex_extract_from_field);
......@@ -694,16 +694,36 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
}
ACPI_MEMSET(buffer, 0, buffer_length);
access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
/* Handle the simple case here */
if ((obj_desc->common_field.start_field_bit_offset == 0) &&
(obj_desc->common_field.bit_length == access_bit_width)) {
status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ);
return_ACPI_STATUS(status);
}
/* TBD: Move to common setup code */
/* Field algorithm is limited to sizeof(u64), truncate if needed */
if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
obj_desc->common_field.access_byte_width = sizeof(u64);
access_bit_width = sizeof(u64) * 8;
}
/* Compute the number of datums (access width data items) */
datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
obj_desc->common_field.access_bit_width);
datum_count =
ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
access_bit_width);
field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
obj_desc->common_field.
start_field_bit_offset,
obj_desc->common_field.
access_bit_width);
/* Priming read from the field */
......@@ -738,12 +758,11 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
* This avoids the differences in behavior between different compilers
* concerning shift values larger than the target data width.
*/
if ((obj_desc->common_field.access_bit_width -
obj_desc->common_field.start_field_bit_offset) <
if (access_bit_width -
obj_desc->common_field.start_field_bit_offset <
ACPI_INTEGER_BIT_SIZE) {
merged_datum |=
raw_datum << (obj_desc->common_field.
access_bit_width -
raw_datum << (access_bit_width -
obj_desc->common_field.
start_field_bit_offset);
}
......@@ -765,8 +784,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
/* Mask off any extra bits in the last datum */
buffer_tail_bits = obj_desc->common_field.bit_length %
obj_desc->common_field.access_bit_width;
buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
if (buffer_tail_bits) {
merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
}
......@@ -798,6 +816,7 @@ acpi_status
acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
void *buffer, u32 buffer_length)
{
void *new_buffer;
acpi_status status;
u64 mask;
u64 width_mask;
......@@ -808,9 +827,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
u32 buffer_tail_bits;
u32 datum_count;
u32 field_datum_count;
u32 i;
u32 access_bit_width;
u32 required_length;
void *new_buffer;
u32 i;
ACPI_FUNCTION_TRACE(ex_insert_into_field);
......@@ -844,17 +863,24 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
buffer_length = required_length;
}
/* TBD: Move to common setup code */
/* Algo is limited to sizeof(u64), so cut the access_byte_width */
if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
obj_desc->common_field.access_byte_width = sizeof(u64);
}
access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
/*
* Create the bitmasks used for bit insertion.
* Note: This if/else is used to bypass compiler differences with the
* shift operator
*/
if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) {
if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
width_mask = ACPI_UINT64_MAX;
} else {
width_mask =
ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
access_bit_width);
width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
}
mask = width_mask &
......@@ -863,12 +889,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
/* Compute the number of datums (access width data items) */
datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
obj_desc->common_field.access_bit_width);
access_bit_width);
field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
obj_desc->common_field.
start_field_bit_offset,
obj_desc->common_field.
access_bit_width);
/* Get initial Datum from the input buffer */
......@@ -905,12 +930,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
* This avoids the differences in behavior between different compilers
* concerning shift values larger than the target data width.
*/
if ((obj_desc->common_field.access_bit_width -
if ((access_bit_width -
obj_desc->common_field.start_field_bit_offset) <
ACPI_INTEGER_BIT_SIZE) {
merged_datum =
raw_datum >> (obj_desc->common_field.
access_bit_width -
raw_datum >> (access_bit_width -
obj_desc->common_field.
start_field_bit_offset);
} else {
......@@ -929,6 +953,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
ACPI_MIN(obj_desc->common_field.access_byte_width,
buffer_length - buffer_offset));
merged_datum |=
raw_datum << obj_desc->common_field.start_field_bit_offset;
}
......@@ -937,7 +962,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
buffer_tail_bits = (obj_desc->common_field.bit_length +
obj_desc->common_field.start_field_bit_offset) %
obj_desc->common_field.access_bit_width;
access_bit_width;
if (buffer_tail_bits) {
mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
}
......
......@@ -336,7 +336,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
/* Clear mutex info */
obj_desc->mutex.thread_id = NULL;
obj_desc->mutex.thread_id = 0;
return_ACPI_STATUS(status);
}
......@@ -393,10 +393,10 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
if ((owner_thread->thread_id != walk_state->thread->thread_id) &&
(obj_desc != acpi_gbl_global_lock_mutex)) {
ACPI_ERROR((AE_INFO,
"Thread %p cannot release Mutex [%4.4s] acquired by thread %p",
ACPI_CAST_PTR(void, walk_state->thread->thread_id),
"Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
(u32)walk_state->thread->thread_id,
acpi_ut_get_node_name(obj_desc->mutex.node),
ACPI_CAST_PTR(void, owner_thread->thread_id)));
(u32)owner_thread->thread_id));
return_ACPI_STATUS(AE_AML_NOT_OWNER);
}
......@@ -488,7 +488,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
/* Mark mutex unowned */
obj_desc->mutex.owner_thread = NULL;
obj_desc->mutex.thread_id = NULL;
obj_desc->mutex.thread_id = 0;
/* Update Thread sync_level (Last mutex is the important one) */
......
......@@ -355,12 +355,10 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
/* Setup width (access granularity) fields */
/* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */
obj_desc->common_field.access_byte_width = (u8)
ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */
obj_desc->common_field.access_bit_width = (u8) access_bit_width;
ACPI_DIV_8(access_bit_width);
/*
* base_byte_offset is the address of the start of the field within the
......@@ -405,8 +403,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *second_desc = NULL;
u32 type;
acpi_status status;
u32 access_byte_width;
u32 type;
ACPI_FUNCTION_TRACE(ex_prep_field_value);
......@@ -421,8 +420,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
type = acpi_ns_get_type(info->region_node);
if (type != ACPI_TYPE_REGION) {
ACPI_ERROR((AE_INFO,
"Needed Region, found type 0x%X (%s)",
type, acpi_ut_get_type_name(type)));
"Needed Region, found type 0x%X (%s)", type,
acpi_ut_get_type_name(type)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
......@@ -438,7 +437,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
/* Initialize areas of the object that are common to all fields */
obj_desc->common_field.node = info->field_node;
status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags,
status = acpi_ex_prep_common_field_object(obj_desc,
info->field_flags,
info->attribute,
info->field_bit_position,
info->field_bit_length);
......@@ -455,26 +455,25 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
obj_desc->field.region_obj =
acpi_ns_get_attached_object(info->region_node);
/* An additional reference for the container */
/* Allow full data read from EC address space */
acpi_ut_add_reference(obj_desc->field.region_obj);
if ((obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_EC)
&& (obj_desc->common_field.bit_length > 8)) {
access_byte_width =
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.
bit_length);
/* Maximum byte width supported is 255 */
/* allow full data read from EC address space */
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_EC) {
if (obj_desc->common_field.bit_length > 8) {
unsigned width =
ACPI_ROUND_BITS_UP_TO_BYTES(
obj_desc->common_field.bit_length);
// access_bit_width is u8, don't overflow it
if (width > 8)
width = 8;
if (access_byte_width < 256) {
obj_desc->common_field.access_byte_width =
width;
obj_desc->common_field.access_bit_width =
8 * width;
(u8)access_byte_width;
}
}
/* An additional reference for the container */
acpi_ut_add_reference(obj_desc->field.region_obj);
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
......
......@@ -353,7 +353,6 @@ acpi_ex_pci_config_space_handler(u32 function,
acpi_status status = AE_OK;
struct acpi_pci_id *pci_id;
u16 pci_register;
u32 value32;
ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
......@@ -381,8 +380,7 @@ acpi_ex_pci_config_space_handler(u32 function,
case ACPI_READ:
status = acpi_os_read_pci_configuration(pci_id, pci_register,
&value32, bit_width);
*value = value32;
value, bit_width);
break;
case ACPI_WRITE:
......
/*******************************************************************************
*
* Module Name: hwpci - Obtain PCI bus, device, and function numbers
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2010, 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_NAMESPACE
ACPI_MODULE_NAME("hwpci")
/* PCI configuration space values */
#define PCI_CFG_HEADER_TYPE_REG 0x0E
#define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18
#define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19
/* PCI header values */
#define PCI_HEADER_TYPE_MASK 0x7F
#define PCI_TYPE_BRIDGE 0x01
#define PCI_TYPE_CARDBUS_BRIDGE 0x02
typedef struct acpi_pci_device {
acpi_handle device;
struct acpi_pci_device *next;
} acpi_pci_device;
/* Local prototypes */
static acpi_status
acpi_hw_build_pci_list(acpi_handle root_pci_device,
acpi_handle pci_region,
struct acpi_pci_device **return_list_head);
static acpi_status
acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
struct acpi_pci_device *list_head);
static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head);
static acpi_status
acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
acpi_handle pci_device,
u16 *bus_number, u8 *is_bridge);
/*******************************************************************************
*
* FUNCTION: acpi_hw_derive_pci_id
*
* PARAMETERS: pci_id - Initial values for the PCI ID. May be
* modified by this function.
* root_pci_device - A handle to a PCI device object. This
* object must be a PCI Root Bridge having a
* _HID value of either PNP0A03 or PNP0A08
* pci_region - A handle to a PCI configuration space
* Operation Region being initialized
*
* RETURN: Status
*
* DESCRIPTION: This function derives a full PCI ID for a PCI device,
* consisting of a Segment number, Bus number, Device number,
* and function code.
*
* The PCI hardware dynamically configures PCI bus numbers
* depending on the bus topology discovered during system
* initialization. This function is invoked during configuration
* of a PCI_Config Operation Region in order to (possibly) update
* the Bus/Device/Function numbers in the pci_id with the actual
* values as determined by the hardware and operating system
* configuration.
*
* The pci_id parameter is initially populated during the Operation
* Region initialization. This function is then called, and is
* will make any necessary modifications to the Bus, Device, or
* Function number PCI ID subfields as appropriate for the
* current hardware and OS configuration.
*
* NOTE: Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id
* interface since this feature is OS-independent. This module
* specifically avoids any use of recursion by building a local
* temporary device list.
*
******************************************************************************/
acpi_status
acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
acpi_handle root_pci_device, acpi_handle pci_region)
{
acpi_status status;
struct acpi_pci_device *list_head = NULL;
ACPI_FUNCTION_TRACE(hw_derive_pci_id);
if (!pci_id) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/* Build a list of PCI devices, from pci_region up to root_pci_device */
status =
acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head);
if (ACPI_SUCCESS(status)) {
/* Walk the list, updating the PCI device/function/bus numbers */
status = acpi_hw_process_pci_list(pci_id, list_head);
}
/* Always delete the list */
acpi_hw_delete_pci_list(list_head);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_build_pci_list
*
* PARAMETERS: root_pci_device - A handle to a PCI device object. This
* object is guaranteed to be a PCI Root
* Bridge having a _HID value of either
* PNP0A03 or PNP0A08
* pci_region - A handle to the PCI configuration space
* Operation Region
* return_list_head - Where the PCI device list is returned
*
* RETURN: Status
*
* DESCRIPTION: Builds a list of devices from the input PCI region up to the
* Root PCI device for this namespace subtree.
*
******************************************************************************/
static acpi_status
acpi_hw_build_pci_list(acpi_handle root_pci_device,
acpi_handle pci_region,
struct acpi_pci_device **return_list_head)
{
acpi_handle current_device;
acpi_handle parent_device;
acpi_status status;
struct acpi_pci_device *list_element;
struct acpi_pci_device *list_head = NULL;
/*
* Ascend namespace branch until the root_pci_device is reached, building
* a list of device nodes. Loop will exit when either the PCI device is
* found, or the root of the namespace is reached.
*/
current_device = pci_region;
while (1) {
status = acpi_get_parent(current_device, &parent_device);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */
if (parent_device == root_pci_device) {
*return_list_head = list_head;
return (AE_OK);
}
list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device));
if (!list_element) {
return (AE_NO_MEMORY);
}
/* Put new element at the head of the list */
list_element->next = list_head;
list_element->device = parent_device;
list_head = list_element;
current_device = parent_device;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_process_pci_list
*
* PARAMETERS: pci_id - Initial values for the PCI ID. May be
* modified by this function.
* list_head - Device list created by
* acpi_hw_build_pci_list
*
* RETURN: Status
*
* DESCRIPTION: Walk downward through the PCI device list, getting the device
* info for each, via the PCI configuration space and updating
* the PCI ID as necessary. Deletes the list during traversal.
*
******************************************************************************/
static acpi_status
acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
struct acpi_pci_device *list_head)
{
acpi_status status = AE_OK;
struct acpi_pci_device *info;
u16 bus_number;
u8 is_bridge = TRUE;
ACPI_FUNCTION_NAME(hw_process_pci_list);
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
pci_id->segment, pci_id->bus, pci_id->device,
pci_id->function));
bus_number = pci_id->bus;
/*
* Descend down the namespace tree, collecting PCI device, function,
* and bus numbers. bus_number is only important for PCI bridges.
* Algorithm: As we descend the tree, use the last valid PCI device,
* function, and bus numbers that are discovered, and assign them
* to the PCI ID for the target device.
*/
info = list_head;
while (info) {
status = acpi_hw_get_pci_device_info(pci_id, info->device,
&bus_number, &is_bridge);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
info = info->next;
}
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X "
"Status %X BusNumber %X IsBridge %X\n",
pci_id->segment, pci_id->bus, pci_id->device,
pci_id->function, status, bus_number, is_bridge));
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_delete_pci_list
*
* PARAMETERS: list_head - Device list created by
* acpi_hw_build_pci_list
*
* RETURN: None
*
* DESCRIPTION: Free the entire PCI list.
*
******************************************************************************/
static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head)
{
struct acpi_pci_device *next;
struct acpi_pci_device *previous;
next = list_head;
while (next) {
previous = next;
next = previous->next;
ACPI_FREE(previous);
}
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_get_pci_device_info
*
* PARAMETERS: pci_id - Initial values for the PCI ID. May be
* modified by this function.
* pci_device - Handle for the PCI device object
* bus_number - Where a PCI bridge bus number is returned
* is_bridge - Return value, indicates if this PCI
* device is a PCI bridge
*
* RETURN: Status
*
* DESCRIPTION: Get the device info for a single PCI device object. Get the
* _ADR (contains PCI device and function numbers), and for PCI
* bridge devices, get the bus number from PCI configuration
* space.
*
******************************************************************************/
static acpi_status
acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
acpi_handle pci_device,
u16 *bus_number, u8 *is_bridge)
{
acpi_status status;
acpi_object_type object_type;
u64 return_value;
u64 pci_value;
/* We only care about objects of type Device */
status = acpi_get_type(pci_device, &object_type);
if (ACPI_FAILURE(status)) {
return (status);
}
if (object_type != ACPI_TYPE_DEVICE) {
return (AE_OK);
}
/* We need an _ADR. Ignore device if not present */
status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
pci_device, &return_value);
if (ACPI_FAILURE(status)) {
return (AE_OK);
}
/*
* From _ADR, get the PCI Device and Function and
* update the PCI ID.
*/
pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value));
pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value));
/*
* If the previous device was a bridge, use the previous
* device bus number
*/
if (*is_bridge) {
pci_id->bus = *bus_number;
}
/*
* Get the bus numbers from PCI Config space:
*
* First, get the PCI header_type
*/
*is_bridge = FALSE;
status = acpi_os_read_pci_configuration(pci_id,
PCI_CFG_HEADER_TYPE_REG,
&pci_value, 8);
if (ACPI_FAILURE(status)) {
return (status);
}
/* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */
pci_value &= PCI_HEADER_TYPE_MASK;
if ((pci_value != PCI_TYPE_BRIDGE) &&
(pci_value != PCI_TYPE_CARDBUS_BRIDGE)) {
return (AE_OK);
}
/* Bridge: Get the Primary bus_number */
status = acpi_os_read_pci_configuration(pci_id,
PCI_CFG_PRIMARY_BUS_NUMBER_REG,
&pci_value, 8);
if (ACPI_FAILURE(status)) {
return (status);
}
*is_bridge = TRUE;
pci_id->bus = (u16)pci_value;
/* Bridge: Get the Secondary bus_number */
status = acpi_os_read_pci_configuration(pci_id,
PCI_CFG_SECONDARY_BUS_NUMBER_REG,
&pci_value, 8);
if (ACPI_FAILURE(status)) {
return (status);
}
*bus_number = (u16)pci_value;
return (AE_OK);
}
......@@ -73,10 +73,18 @@ static acpi_status
acpi_ns_repair_ALR(struct acpi_predefined_data *data,
union acpi_operand_object **return_object_ptr);
static acpi_status
acpi_ns_repair_CID(struct acpi_predefined_data *data,
union acpi_operand_object **return_object_ptr);
static acpi_status
acpi_ns_repair_FDE(struct acpi_predefined_data *data,
union acpi_operand_object **return_object_ptr);
static acpi_status
acpi_ns_repair_HID(struct acpi_predefined_data *data,
union acpi_operand_object **return_object_ptr);
static acpi_status
acpi_ns_repair_PSS(struct acpi_predefined_data *data,
union acpi_operand_object **return_object_ptr);
......@@ -108,8 +116,10 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
* As necessary:
*
* _ALR: Sort the list ascending by ambient_illuminance
* _CID: Strings: uppercase all, remove any leading asterisk
* _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
* _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
* _HID: Strings: uppercase all, remove any leading asterisk
* _PSS: Sort the list descending by Power
* _TSS: Sort the list descending by Power
*
......@@ -122,8 +132,10 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
*/
static const struct acpi_repair_info acpi_ns_repairable_names[] = {
{"_ALR", acpi_ns_repair_ALR},
{"_CID", acpi_ns_repair_CID},
{"_FDE", acpi_ns_repair_FDE},
{"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */
{"_HID", acpi_ns_repair_HID},
{"_PSS", acpi_ns_repair_PSS},
{"_TSS", acpi_ns_repair_TSS},
{{0, 0, 0, 0}, NULL} /* Table terminator */
......@@ -319,6 +331,157 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data,
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_ns_repair_CID
*
* PARAMETERS: Data - Pointer to validation data structure
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN: Status. AE_OK if object is OK or was repaired successfully
*
* DESCRIPTION: Repair for the _CID object. If a string, ensure that all
* letters are uppercase and that there is no leading asterisk.
* If a Package, ensure same for all string elements.
*
*****************************************************************************/
static acpi_status
acpi_ns_repair_CID(struct acpi_predefined_data *data,
union acpi_operand_object **return_object_ptr)
{
acpi_status status;
union acpi_operand_object *return_object = *return_object_ptr;
union acpi_operand_object **element_ptr;
union acpi_operand_object *original_element;
u16 original_ref_count;
u32 i;
/* Check for _CID as a simple string */
if (return_object->common.type == ACPI_TYPE_STRING) {
status = acpi_ns_repair_HID(data, return_object_ptr);
return (status);
}
/* Exit if not a Package */
if (return_object->common.type != ACPI_TYPE_PACKAGE) {
return (AE_OK);
}
/* Examine each element of the _CID package */
element_ptr = return_object->package.elements;
for (i = 0; i < return_object->package.count; i++) {
original_element = *element_ptr;
original_ref_count = original_element->common.reference_count;
status = acpi_ns_repair_HID(data, element_ptr);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Take care with reference counts */
if (original_element != *element_ptr) {
/* Element was replaced */
(*element_ptr)->common.reference_count =
original_ref_count;
acpi_ut_remove_reference(original_element);
}
element_ptr++;
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_ns_repair_HID
*
* PARAMETERS: Data - Pointer to validation data structure
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN: Status. AE_OK if object is OK or was repaired successfully
*
* DESCRIPTION: Repair for the _HID object. If a string, ensure that all
* letters are uppercase and that there is no leading asterisk.
*
*****************************************************************************/
static acpi_status
acpi_ns_repair_HID(struct acpi_predefined_data *data,
union acpi_operand_object **return_object_ptr)
{
union acpi_operand_object *return_object = *return_object_ptr;
union acpi_operand_object *new_string;
char *source;
char *dest;
ACPI_FUNCTION_NAME(ns_repair_HID);
/* We only care about string _HID objects (not integers) */
if (return_object->common.type != ACPI_TYPE_STRING) {
return (AE_OK);
}
if (return_object->string.length == 0) {
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
"Invalid zero-length _HID or _CID string"));
/* Return AE_OK anyway, let driver handle it */
data->flags |= ACPI_OBJECT_REPAIRED;
return (AE_OK);
}
/* It is simplest to always create a new string object */
new_string = acpi_ut_create_string_object(return_object->string.length);
if (!new_string) {
return (AE_NO_MEMORY);
}
/*
* Remove a leading asterisk if present. For some unknown reason, there
* are many machines in the field that contains IDs like this.
*
* Examples: "*PNP0C03", "*ACPI0003"
*/
source = return_object->string.pointer;
if (*source == '*') {
source++;
new_string->string.length--;
ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
"%s: Removed invalid leading asterisk\n",
data->pathname));
}
/*
* Copy and uppercase the string. From the ACPI specification:
*
* A valid PNP ID must be of the form "AAA####" where A is an uppercase
* letter and # is a hex digit. A valid ACPI ID must be of the form
* "ACPI####" where # is a hex digit.
*/
for (dest = new_string->string.pointer; *source; dest++, source++) {
*dest = (char)ACPI_TOUPPER(*source);
}
acpi_ut_remove_reference(return_object);
*return_object_ptr = new_string;
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_ns_repair_TSS
......
......@@ -58,104 +58,6 @@ static u8 acpi_ns_valid_path_separator(char sep);
acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
#endif
/*******************************************************************************
*
* FUNCTION: acpi_ns_report_error
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* internal_name - Name or path of the namespace node
* lookup_status - Exception code from NS lookup
*
* RETURN: None
*
* DESCRIPTION: Print warning message with full pathname
*
******************************************************************************/
void
acpi_ns_report_error(const char *module_name,
u32 line_number,
const char *internal_name, acpi_status lookup_status)
{
acpi_status status;
u32 bad_name;
char *name = NULL;
acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
if (lookup_status == AE_BAD_CHARACTER) {
/* There is a non-ascii character in the name */
ACPI_MOVE_32_TO_32(&bad_name,
ACPI_CAST_PTR(u32, internal_name));
acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
} else {
/* Convert path to external format */
status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
internal_name, NULL, &name);
/* Print target name */
if (ACPI_SUCCESS(status)) {
acpi_os_printf("[%s]", name);
} else {
acpi_os_printf("[COULD NOT EXTERNALIZE NAME]");
}
if (name) {
ACPI_FREE(name);
}
}
acpi_os_printf(" Namespace lookup failure, %s\n",
acpi_format_exception(lookup_status));
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_report_method_error
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Message - Error message to use on failure
* prefix_node - Prefix relative to the path
* Path - Path to the node (optional)
* method_status - Execution status
*
* RETURN: None
*
* DESCRIPTION: Print warning message with full pathname
*
******************************************************************************/
void
acpi_ns_report_method_error(const char *module_name,
u32 line_number,
const char *message,
struct acpi_namespace_node *prefix_node,
const char *path, acpi_status method_status)
{
acpi_status status;
struct acpi_namespace_node *node = prefix_node;
acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
if (path) {
status =
acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
&node);
if (ACPI_FAILURE(status)) {
acpi_os_printf("[Could not get node by pathname]");
}
}
acpi_ns_print_node_pathname(node, message);
acpi_os_printf(", %s\n", acpi_format_exception(method_status));
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_print_node_pathname
......
......@@ -49,7 +49,7 @@
ACPI_MODULE_NAME("tbfadt")
/* Local prototypes */
static inline void
static ACPI_INLINE void
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
u8 space_id, u8 byte_width, u64 address);
......@@ -181,7 +181,7 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = {
*
******************************************************************************/
static inline void
static ACPI_INLINE void
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
u8 space_id, u8 byte_width, u64 address)
{
......
......@@ -179,9 +179,8 @@ acpi_debug_print(u32 requested_debug_level,
if (thread_id != acpi_gbl_prev_thread_id) {
if (ACPI_LV_THREADS & acpi_dbg_level) {
acpi_os_printf
("\n**** Context Switch from TID %p to TID %p ****\n\n",
ACPI_CAST_PTR(void, acpi_gbl_prev_thread_id),
ACPI_CAST_PTR(void, thread_id));
("\n**** Context Switch from TID %u to TID %u ****\n\n",
(u32)acpi_gbl_prev_thread_id, (u32)thread_id);
}
acpi_gbl_prev_thread_id = thread_id;
......@@ -194,7 +193,7 @@ acpi_debug_print(u32 requested_debug_level,
acpi_os_printf("%8s-%04ld ", module_name, line_number);
if (ACPI_LV_THREADS & acpi_dbg_level) {
acpi_os_printf("[%p] ", ACPI_CAST_PTR(void, thread_id));
acpi_os_printf("[%u] ", (u32)thread_id);
}
acpi_os_printf("[%02ld] %-22.22s: ",
......
......@@ -48,153 +48,6 @@
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("uteval")
/*
* Strings supported by the _OSI predefined (internal) method.
*
* March 2009: Removed "Linux" as this host no longer wants to respond true
* for this string. Basically, the only safe OS strings are windows-related
* and in many or most cases represent the only test path within the
* BIOS-provided ASL code.
*
* The second element of each entry is used to track the newest version of
* Windows that the BIOS has requested.
*/
static struct acpi_interface_info acpi_interfaces_supported[] = {
/* Operating System Vendor Strings */
{"Windows 2000", ACPI_OSI_WIN_2000}, /* Windows 2000 */
{"Windows 2001", ACPI_OSI_WIN_XP}, /* Windows XP */
{"Windows 2001 SP1", ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */
{"Windows 2001.1", ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */
{"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */
{"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */
{"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */
{"Windows 2006.1", ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */
{"Windows 2006 SP1", ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */
{"Windows 2009", ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */
/* Feature Group Strings */
{"Extended Address Space Descriptor", 0}
/*
* All "optional" feature group strings (features that are implemented
* by the host) should be implemented in the host version of
* acpi_os_validate_interface and should not be added here.
*/
};
/*******************************************************************************
*
* FUNCTION: acpi_ut_osi_implementation
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Implementation of the _OSI predefined control method
*
******************************************************************************/
acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
{
acpi_status status;
union acpi_operand_object *string_desc;
union acpi_operand_object *return_desc;
u32 return_value;
u32 i;
ACPI_FUNCTION_TRACE(ut_osi_implementation);
/* Validate the string input argument */
string_desc = walk_state->arguments[0].object;
if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
return_ACPI_STATUS(AE_TYPE);
}
/* Create a return object */
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Default return value is 0, NOT SUPPORTED */
return_value = 0;
/* Compare input string to static table of supported interfaces */
for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
if (!ACPI_STRCMP(string_desc->string.pointer,
acpi_interfaces_supported[i].name)) {
/*
* The interface is supported.
* Update the osi_data if necessary. We keep track of the latest
* version of Windows that has been requested by the BIOS.
*/
if (acpi_interfaces_supported[i].value >
acpi_gbl_osi_data) {
acpi_gbl_osi_data =
acpi_interfaces_supported[i].value;
}
return_value = ACPI_UINT32_MAX;
goto exit;
}
}
/*
* Did not match the string in the static table, call the host OSL to
* check for a match with one of the optional strings (such as
* "Module Device", "3.0 Thermal Model", etc.)
*/
status = acpi_os_validate_interface(string_desc->string.pointer);
if (ACPI_SUCCESS(status)) {
/* The interface is supported */
return_value = ACPI_UINT32_MAX;
}
exit:
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,
"ACPI: BIOS _OSI(%s) is %ssupported\n",
string_desc->string.pointer, return_value == 0 ? "not " : ""));
/* Complete the return value */
return_desc->integer.value = return_value;
walk_state->return_desc = return_desc;
return_ACPI_STATUS (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_osi_invalidate
*
* PARAMETERS: interface_string
*
* RETURN: Status
*
* DESCRIPTION: invalidate string in pre-defiend _OSI string list
*
******************************************************************************/
acpi_status acpi_osi_invalidate(char *interface)
{
int i;
for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i].name)) {
*acpi_interfaces_supported[i].name = '\0';
return AE_OK;
}
}
return AE_NOT_FOUND;
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_evaluate_object
......
......@@ -154,14 +154,16 @@ ACPI_EXPORT_SYMBOL(acpi_format_exception)
* 1) _SB_ is defined to be a device to allow \_SB_._INI to be run
* during the initialization sequence.
* 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to
* perform a Notify() operation on it.
* perform a Notify() operation on it. 09/2010: Changed to type Device.
* This still allows notifies, but does not confuse host code that
* searches for valid thermal_zone objects.
*/
const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = {
{"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
{"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
{"_SB_", ACPI_TYPE_DEVICE, NULL},
{"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
{"_TZ_", ACPI_TYPE_THERMAL, NULL},
{"_TZ_", ACPI_TYPE_DEVICE, NULL},
{"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
{"_GL_", ACPI_TYPE_MUTEX, (char *)1},
......@@ -766,6 +768,7 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_gpe_fadt_blocks[0] = NULL;
acpi_gbl_gpe_fadt_blocks[1] = NULL;
acpi_current_gpe_count = 0;
acpi_all_gpes_initialized = FALSE;
/* Global handlers */
......@@ -774,6 +777,7 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_exception_handler = NULL;
acpi_gbl_init_handler = NULL;
acpi_gbl_table_handler = NULL;
acpi_gbl_interface_handler = NULL;
/* Global Lock support */
......@@ -800,6 +804,7 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
acpi_gbl_osi_data = 0;
acpi_gbl_osi_mutex = NULL;
/* Hardware oriented */
......
......@@ -48,42 +48,6 @@
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utids")
/* Local prototypes */
static void acpi_ut_copy_id_string(char *destination, char *source);
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_id_string
*
* PARAMETERS: Destination - Where to copy the string
* Source - Source string
*
* RETURN: None
*
* DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
* Performs removal of a leading asterisk if present -- workaround
* for a known issue on a bunch of machines.
*
******************************************************************************/
static void acpi_ut_copy_id_string(char *destination, char *source)
{
/*
* Workaround for ID strings that have a leading asterisk. This construct
* is not allowed by the ACPI specification (ID strings must be
* alphanumeric), but enough existing machines have this embedded in their
* ID strings that the following code is useful.
*/
if (*source == '*') {
source++;
}
/* Do the actual copy */
ACPI_STRCPY(destination, source);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_HID
......@@ -101,7 +65,6 @@ static void acpi_ut_copy_id_string(char *destination, char *source)
* NOTE: Internal function, no parameter validation
*
******************************************************************************/
acpi_status
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
struct acpica_device_id **return_id)
......@@ -147,7 +110,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value);
} else {
acpi_ut_copy_id_string(hid->string, obj_desc->string.pointer);
ACPI_STRCPY(hid->string, obj_desc->string.pointer);
}
hid->length = length;
......@@ -224,7 +187,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
acpi_ex_integer_to_string(uid->string, obj_desc->integer.value);
} else {
acpi_ut_copy_id_string(uid->string, obj_desc->string.pointer);
ACPI_STRCPY(uid->string, obj_desc->string.pointer);
}
uid->length = length;
......@@ -357,8 +320,8 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
/* Copy the String CID from the returned object */
acpi_ut_copy_id_string(next_id_string,
cid_objects[i]->string.pointer);
ACPI_STRCPY(next_id_string,
cid_objects[i]->string.pointer);
length = cid_objects[i]->string.length + 1;
}
......
......@@ -117,6 +117,10 @@ void acpi_ut_subsystem_shutdown(void)
/* Close the acpi_event Handling */
acpi_ev_terminate();
/* Delete any dynamic _OSI interfaces */
acpi_ut_interface_terminate();
#endif
/* Close the Namespace */
......
......@@ -48,11 +48,27 @@
ACPI_MODULE_NAME("utmath")
/*
* Support for double-precision integer divide. This code is included here
* in order to support kernel environments where the double-precision math
* library is not available.
* Optional support for 64-bit double-precision integer divide. This code
* is configurable and is implemented in order to support 32-bit kernel
* environments where a 64-bit double-precision math library is not available.
*
* Support for a more normal 64-bit divide/modulo (with check for a divide-
* by-zero) appears after this optional section of code.
*/
#ifndef ACPI_USE_NATIVE_DIVIDE
/* Structures used only for 64-bit divide */
typedef struct uint64_struct {
u32 lo;
u32 hi;
} uint64_struct;
typedef union uint64_overlay {
u64 full;
struct uint64_struct part;
} uint64_overlay;
/*******************************************************************************
*
* FUNCTION: acpi_ut_short_divide
......@@ -69,6 +85,7 @@ ACPI_MODULE_NAME("utmath")
* 32-bit remainder.
*
******************************************************************************/
acpi_status
acpi_ut_short_divide(u64 dividend,
u32 divisor, u64 *out_quotient, u32 *out_remainder)
......
......@@ -50,11 +50,6 @@
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utmisc")
/*
* Common suffix for messages
*/
#define ACPI_COMMON_MSG_SUFFIX \
acpi_os_printf(" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number)
/*******************************************************************************
*
* FUNCTION: acpi_ut_validate_exception
......@@ -1044,160 +1039,3 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
return_ACPI_STATUS(AE_AML_INTERNAL);
}
/*******************************************************************************
*
* FUNCTION: acpi_error, acpi_exception, acpi_warning, acpi_info
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Print message with module/line/version info
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_error(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
acpi_os_printf("ACPI Error: ");
va_start(args, format);
acpi_os_vprintf(format, args);
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}
void ACPI_INTERNAL_VAR_XFACE
acpi_exception(const char *module_name,
u32 line_number, acpi_status status, const char *format, ...)
{
va_list args;
acpi_os_printf("ACPI Exception: %s, ", acpi_format_exception(status));
va_start(args, format);
acpi_os_vprintf(format, args);
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}
void ACPI_INTERNAL_VAR_XFACE
acpi_warning(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
acpi_os_printf("ACPI Warning: ");
va_start(args, format);
acpi_os_vprintf(format, args);
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}
void ACPI_INTERNAL_VAR_XFACE
acpi_info(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
acpi_os_printf("ACPI: ");
va_start(args, format);
acpi_os_vprintf(format, args);
acpi_os_printf("\n");
va_end(args);
}
ACPI_EXPORT_SYMBOL(acpi_error)
ACPI_EXPORT_SYMBOL(acpi_exception)
ACPI_EXPORT_SYMBOL(acpi_warning)
ACPI_EXPORT_SYMBOL(acpi_info)
/*******************************************************************************
*
* FUNCTION: acpi_ut_predefined_warning
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Pathname - Full pathname to the node
* node_flags - From Namespace node for the method/object
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Warnings for the predefined validation module. Messages are
* only emitted the first time a problem with a particular
* method/object is detected. This prevents a flood of error
* messages for methods that are repeatedly evaluated.
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_warning(const char *module_name,
u32 line_number,
char *pathname,
u8 node_flags, const char *format, ...)
{
va_list args;
/*
* Warning messages for this method/object will be disabled after the
* first time a validation fails or an object is successfully repaired.
*/
if (node_flags & ANOBJ_EVALUATED) {
return;
}
acpi_os_printf("ACPI Warning for %s: ", pathname);
va_start(args, format);
acpi_os_vprintf(format, args);
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_predefined_info
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Pathname - Full pathname to the node
* node_flags - From Namespace node for the method/object
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Info messages for the predefined validation module. Messages
* are only emitted the first time a problem with a particular
* method/object is detected. This prevents a flood of
* messages for methods that are repeatedly evaluated.
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_info(const char *module_name,
u32 line_number,
char *pathname, u8 node_flags, const char *format, ...)
{
va_list args;
/*
* Warning messages for this method/object will be disabled after the
* first time a validation fails or an object is successfully repaired.
*/
if (node_flags & ANOBJ_EVALUATED) {
return;
}
acpi_os_printf("ACPI Info for %s: ", pathname);
va_start(args, format);
acpi_os_vprintf(format, args);
ACPI_COMMON_MSG_SUFFIX;
va_end(args);
}
......@@ -86,6 +86,12 @@ acpi_status acpi_ut_mutex_initialize(void)
spin_lock_init(acpi_gbl_gpe_lock);
spin_lock_init(acpi_gbl_hardware_lock);
/* Mutex for _OSI support */
status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Create the reader/writer lock for namespace access */
status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
......@@ -117,6 +123,8 @@ void acpi_ut_mutex_terminate(void)
acpi_ut_delete_mutex(i);
}
acpi_os_delete_mutex(acpi_gbl_osi_mutex);
/* Delete the spinlocks */
acpi_os_delete_lock(acpi_gbl_gpe_lock);
......@@ -220,18 +228,17 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
if (i == mutex_id) {
ACPI_ERROR((AE_INFO,
"Mutex [%s] already acquired by this thread [%p]",
"Mutex [%s] already acquired by this thread [%u]",
acpi_ut_get_mutex_name
(mutex_id),
ACPI_CAST_PTR(void,
this_thread_id)));
(u32)this_thread_id));
return (AE_ALREADY_ACQUIRED);
}
ACPI_ERROR((AE_INFO,
"Invalid acquire order: Thread %p owns [%s], wants [%s]",
ACPI_CAST_PTR(void, this_thread_id),
"Invalid acquire order: Thread %u owns [%s], wants [%s]",
(u32)this_thread_id,
acpi_ut_get_mutex_name(i),
acpi_ut_get_mutex_name(mutex_id)));
......@@ -242,24 +249,24 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
#endif
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
"Thread %p attempting to acquire Mutex [%s]\n",
ACPI_CAST_PTR(void, this_thread_id),
"Thread %u attempting to acquire Mutex [%s]\n",
(u32)this_thread_id,
acpi_ut_get_mutex_name(mutex_id)));
status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
ACPI_WAIT_FOREVER);
if (ACPI_SUCCESS(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
"Thread %p acquired Mutex [%s]\n",
ACPI_CAST_PTR(void, this_thread_id),
"Thread %u acquired Mutex [%s]\n",
(u32)this_thread_id,
acpi_ut_get_mutex_name(mutex_id)));
acpi_gbl_mutex_info[mutex_id].use_count++;
acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
} else {
ACPI_EXCEPTION((AE_INFO, status,
"Thread %p could not acquire Mutex [0x%X]",
ACPI_CAST_PTR(void, this_thread_id), mutex_id));
"Thread %u could not acquire Mutex [0x%X]",
(u32)this_thread_id, mutex_id));
}
return (status);
......@@ -279,10 +286,14 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
{
acpi_thread_id this_thread_id;
ACPI_FUNCTION_NAME(ut_release_mutex);
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n",
ACPI_CAST_PTR(void, acpi_os_get_thread_id()),
this_thread_id = acpi_os_get_thread_id();
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
(u32)this_thread_id,
acpi_ut_get_mutex_name(mutex_id)));
if (mutex_id > ACPI_MAX_MUTEX) {
......
/******************************************************************************
*
* Module Name: utosi - Support for the _OSI predefined control method
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2010, 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_UTILITIES
ACPI_MODULE_NAME("utosi")
/*
* Strings supported by the _OSI predefined control method (which is
* implemented internally within this module.)
*
* March 2009: Removed "Linux" as this host no longer wants to respond true
* for this string. Basically, the only safe OS strings are windows-related
* and in many or most cases represent the only test path within the
* BIOS-provided ASL code.
*
* The last element of each entry is used to track the newest version of
* Windows that the BIOS has requested.
*/
static struct acpi_interface_info acpi_default_supported_interfaces[] = {
/* Operating System Vendor Strings */
{"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */
{"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */
{"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */
{"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */
{"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */
{"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */
{"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */
{"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */
{"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */
{"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */
{"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */
/* Feature Group Strings */
{"Extended Address Space Descriptor", NULL, 0, 0}
/*
* All "optional" feature group strings (features that are implemented
* by the host) should be dynamically added by the host via
* acpi_install_interface and should not be manually added here.
*
* Examples of optional feature group strings:
*
* "Module Device"
* "Processor Device"
* "3.0 Thermal Model"
* "3.0 _SCP Extensions"
* "Processor Aggregator Device"
*/
};
/*******************************************************************************
*
* FUNCTION: acpi_ut_initialize_interfaces
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Initialize the global _OSI supported interfaces list
*
******************************************************************************/
acpi_status acpi_ut_initialize_interfaces(void)
{
u32 i;
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
acpi_gbl_supported_interfaces = acpi_default_supported_interfaces;
/* Link the static list of supported interfaces */
for (i = 0;
i < (ACPI_ARRAY_LENGTH(acpi_default_supported_interfaces) - 1);
i++) {
acpi_default_supported_interfaces[i].next =
&acpi_default_supported_interfaces[(acpi_size) i + 1];
}
acpi_os_release_mutex(acpi_gbl_osi_mutex);
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_interface_terminate
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Delete all interfaces in the global list. Sets
* acpi_gbl_supported_interfaces to NULL.
*
******************************************************************************/
void acpi_ut_interface_terminate(void)
{
struct acpi_interface_info *next_interface;
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
next_interface = acpi_gbl_supported_interfaces;
while (next_interface) {
acpi_gbl_supported_interfaces = next_interface->next;
/* Only interfaces added at runtime can be freed */
if (next_interface->flags & ACPI_OSI_DYNAMIC) {
ACPI_FREE(next_interface->name);
ACPI_FREE(next_interface);
}
next_interface = acpi_gbl_supported_interfaces;
}
acpi_os_release_mutex(acpi_gbl_osi_mutex);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_install_interface
*
* PARAMETERS: interface_name - The interface to install
*
* RETURN: Status
*
* DESCRIPTION: Install the interface into the global interface list.
* Caller MUST hold acpi_gbl_osi_mutex
*
******************************************************************************/
acpi_status acpi_ut_install_interface(acpi_string interface_name)
{
struct acpi_interface_info *interface_info;
/* Allocate info block and space for the name string */
interface_info =
ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_interface_info));
if (!interface_info) {
return (AE_NO_MEMORY);
}
interface_info->name =
ACPI_ALLOCATE_ZEROED(ACPI_STRLEN(interface_name) + 1);
if (!interface_info->name) {
ACPI_FREE(interface_info);
return (AE_NO_MEMORY);
}
/* Initialize new info and insert at the head of the global list */
ACPI_STRCPY(interface_info->name, interface_name);
interface_info->flags = ACPI_OSI_DYNAMIC;
interface_info->next = acpi_gbl_supported_interfaces;
acpi_gbl_supported_interfaces = interface_info;
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_remove_interface
*
* PARAMETERS: interface_name - The interface to remove
*
* RETURN: Status
*
* DESCRIPTION: Remove the interface from the global interface list.
* Caller MUST hold acpi_gbl_osi_mutex
*
******************************************************************************/
acpi_status acpi_ut_remove_interface(acpi_string interface_name)
{
struct acpi_interface_info *previous_interface;
struct acpi_interface_info *next_interface;
previous_interface = next_interface = acpi_gbl_supported_interfaces;
while (next_interface) {
if (!ACPI_STRCMP(interface_name, next_interface->name)) {
/* Found: name is in either the static list or was added at runtime */
if (next_interface->flags & ACPI_OSI_DYNAMIC) {
/* Interface was added dynamically, remove and free it */
if (previous_interface == next_interface) {
acpi_gbl_supported_interfaces =
next_interface->next;
} else {
previous_interface->next =
next_interface->next;
}
ACPI_FREE(next_interface->name);
ACPI_FREE(next_interface);
} else {
/*
* Interface is in static list. If marked invalid, then it
* does not actually exist. Else, mark it invalid.
*/
if (next_interface->flags & ACPI_OSI_INVALID) {
return (AE_NOT_EXIST);
}
next_interface->flags |= ACPI_OSI_INVALID;
}
return (AE_OK);
}
previous_interface = next_interface;
next_interface = next_interface->next;
}
/* Interface was not found */
return (AE_NOT_EXIST);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_get_interface
*
* PARAMETERS: interface_name - The interface to find
*
* RETURN: struct acpi_interface_info if found. NULL if not found.
*
* DESCRIPTION: Search for the specified interface name in the global list.
* Caller MUST hold acpi_gbl_osi_mutex
*
******************************************************************************/
struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name)
{
struct acpi_interface_info *next_interface;
next_interface = acpi_gbl_supported_interfaces;
while (next_interface) {
if (!ACPI_STRCMP(interface_name, next_interface->name)) {
return (next_interface);
}
next_interface = next_interface->next;
}
return (NULL);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_osi_implementation
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Implementation of the _OSI predefined control method. When
* an invocation of _OSI is encountered in the system AML,
* control is transferred to this function.
*
******************************************************************************/
acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state)
{
union acpi_operand_object *string_desc;
union acpi_operand_object *return_desc;
struct acpi_interface_info *interface_info;
acpi_interface_handler interface_handler;
u32 return_value;
ACPI_FUNCTION_TRACE(ut_osi_implementation);
/* Validate the string input argument (from the AML caller) */
string_desc = walk_state->arguments[0].object;
if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
return_ACPI_STATUS(AE_TYPE);
}
/* Create a return object */
return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!return_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Default return value is 0, NOT SUPPORTED */
return_value = 0;
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
/* Lookup the interface in the global _OSI list */
interface_info = acpi_ut_get_interface(string_desc->string.pointer);
if (interface_info && !(interface_info->flags & ACPI_OSI_INVALID)) {
/*
* The interface is supported.
* Update the osi_data if necessary. We keep track of the latest
* version of Windows that has been requested by the BIOS.
*/
if (interface_info->value > acpi_gbl_osi_data) {
acpi_gbl_osi_data = interface_info->value;
}
return_value = ACPI_UINT32_MAX;
}
acpi_os_release_mutex(acpi_gbl_osi_mutex);
/*
* Invoke an optional _OSI interface handler. The host OS may wish
* to do some interface-specific handling. For example, warn about
* certain interfaces or override the true/false support value.
*/
interface_handler = acpi_gbl_interface_handler;
if (interface_handler) {
return_value =
interface_handler(string_desc->string.pointer,
return_value);
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
"ACPI: BIOS _OSI(\"%s\") is %ssupported\n",
string_desc->string.pointer,
return_value == 0 ? "not " : ""));
/* Complete the return object */
return_desc->integer.value = return_value;
walk_state->return_desc = return_desc;
return_ACPI_STATUS(AE_OK);
}
......@@ -110,6 +110,15 @@ acpi_status __init acpi_initialize_subsystem(void)
return_ACPI_STATUS(status);
}
/* Initialize the global OSI interfaces list with the static names */
status = acpi_ut_initialize_interfaces();
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"During OSI interfaces initialization"));
return_ACPI_STATUS(status);
}
/* If configured, initialize the AML debugger */
ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
......@@ -289,19 +298,6 @@ acpi_status acpi_initialize_objects(u32 flags)
}
}
/*
* Complete the GPE initialization for the GPE blocks defined in the FADT
* (GPE block 0 and 1).
*
* NOTE: Currently, there seems to be no need to run the _REG methods
* before enabling the GPEs.
*/
if (!(flags & ACPI_NO_EVENT_INIT)) {
status = acpi_ev_install_fadt_gpes();
if (ACPI_FAILURE(status))
return (status);
}
/*
* Empty the caches (delete the cached objects) on the assumption that
* the table load filled them up more than they will be at runtime --
......@@ -506,6 +502,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
#endif /* ACPI_FUTURE_USAGE */
/*****************************************************************************
*
* FUNCTION: acpi_purge_cached_objects
......@@ -529,4 +526,117 @@ acpi_status acpi_purge_cached_objects(void)
}
ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects)
#endif
/*****************************************************************************
*
* FUNCTION: acpi_install_interface
*
* PARAMETERS: interface_name - The interface to install
*
* RETURN: Status
*
* DESCRIPTION: Install an _OSI interface to the global list
*
****************************************************************************/
acpi_status acpi_install_interface(acpi_string interface_name)
{
acpi_status status;
struct acpi_interface_info *interface_info;
/* Parameter validation */
if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) {
return (AE_BAD_PARAMETER);
}
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
/* Check if the interface name is already in the global list */
interface_info = acpi_ut_get_interface(interface_name);
if (interface_info) {
/*
* The interface already exists in the list. This is OK if the
* interface has been marked invalid -- just clear the bit.
*/
if (interface_info->flags & ACPI_OSI_INVALID) {
interface_info->flags &= ~ACPI_OSI_INVALID;
status = AE_OK;
} else {
status = AE_ALREADY_EXISTS;
}
} else {
/* New interface name, install into the global list */
status = acpi_ut_install_interface(interface_name);
}
acpi_os_release_mutex(acpi_gbl_osi_mutex);
return (status);
}
ACPI_EXPORT_SYMBOL(acpi_install_interface)
/*****************************************************************************
*
* FUNCTION: acpi_remove_interface
*
* PARAMETERS: interface_name - The interface to remove
*
* RETURN: Status
*
* DESCRIPTION: Remove an _OSI interface from the global list
*
****************************************************************************/
acpi_status acpi_remove_interface(acpi_string interface_name)
{
acpi_status status;
/* Parameter validation */
if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) {
return (AE_BAD_PARAMETER);
}
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
status = acpi_ut_remove_interface(interface_name);
acpi_os_release_mutex(acpi_gbl_osi_mutex);
return (status);
}
ACPI_EXPORT_SYMBOL(acpi_remove_interface)
/*****************************************************************************
*
* FUNCTION: acpi_install_interface_handler
*
* PARAMETERS: Handler - The _OSI interface handler to install
* NULL means "remove existing handler"
*
* RETURN: Status
*
* DESCRIPTION: Install a handler for the predefined _OSI ACPI method.
* invoked during execution of the internal implementation of
* _OSI. A NULL handler simply removes any existing handler.
*
****************************************************************************/
acpi_status acpi_install_interface_handler(acpi_interface_handler handler)
{
acpi_status status = AE_OK;
(void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
if (handler && acpi_gbl_interface_handler) {
status = AE_ALREADY_EXISTS;
} else {
acpi_gbl_interface_handler = handler;
}
acpi_os_release_mutex(acpi_gbl_osi_mutex);
return (status);
}
ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
#endif /* !ACPI_ASL_COMPILER */
/*******************************************************************************
*
* Module Name: utxferror - Various error/warning output functions
*
******************************************************************************/
/*
* Copyright (C) 2000 - 2010, 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 "acnamesp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utxferror")
/*
* This module is used for the in-kernel ACPICA as well as the ACPICA
* tools/applications.
*
* For the i_aSL compiler case, the output is redirected to stderr so that
* any of the various ACPI errors and warnings do not appear in the output
* files, for either the compiler or disassembler portions of the tool.
*/
#ifdef ACPI_ASL_COMPILER
#include <stdio.h>
extern FILE *acpi_gbl_output_file;
#define ACPI_MSG_REDIRECT_BEGIN \
FILE *output_file = acpi_gbl_output_file; \
acpi_os_redirect_output (stderr);
#define ACPI_MSG_REDIRECT_END \
acpi_os_redirect_output (output_file);
#else
/*
* non-i_aSL case - no redirection, nothing to do
*/
#define ACPI_MSG_REDIRECT_BEGIN
#define ACPI_MSG_REDIRECT_END
#endif
/*
* Common message prefixes
*/
#define ACPI_MSG_ERROR "ACPI Error: "
#define ACPI_MSG_EXCEPTION "ACPI Exception: "
#define ACPI_MSG_WARNING "ACPI Warning: "
#define ACPI_MSG_INFO "ACPI: "
/*
* Common message suffix
*/
#define ACPI_MSG_SUFFIX \
acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number)
/*******************************************************************************
*
* FUNCTION: acpi_error
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Print "ACPI Error" message with module/line/version info
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_error(const char *module_name, u32 line_number, const char *format, ...)
{
va_list arg_list;
ACPI_MSG_REDIRECT_BEGIN;
acpi_os_printf(ACPI_MSG_ERROR);
va_start(arg_list, format);
acpi_os_vprintf(format, arg_list);
ACPI_MSG_SUFFIX;
va_end(arg_list);
ACPI_MSG_REDIRECT_END;
}
ACPI_EXPORT_SYMBOL(acpi_error)
/*******************************************************************************
*
* FUNCTION: acpi_exception
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Status - Status to be formatted
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Print "ACPI Exception" message with module/line/version info
* and decoded acpi_status.
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_exception(const char *module_name,
u32 line_number, acpi_status status, const char *format, ...)
{
va_list arg_list;
ACPI_MSG_REDIRECT_BEGIN;
acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ",
acpi_format_exception(status));
va_start(arg_list, format);
acpi_os_vprintf(format, arg_list);
ACPI_MSG_SUFFIX;
va_end(arg_list);
ACPI_MSG_REDIRECT_END;
}
ACPI_EXPORT_SYMBOL(acpi_exception)
/*******************************************************************************
*
* FUNCTION: acpi_warning
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Print "ACPI Warning" message with module/line/version info
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_warning(const char *module_name, u32 line_number, const char *format, ...)
{
va_list arg_list;
ACPI_MSG_REDIRECT_BEGIN;
acpi_os_printf(ACPI_MSG_WARNING);
va_start(arg_list, format);
acpi_os_vprintf(format, arg_list);
ACPI_MSG_SUFFIX;
va_end(arg_list);
ACPI_MSG_REDIRECT_END;
}
ACPI_EXPORT_SYMBOL(acpi_warning)
/*******************************************************************************
*
* FUNCTION: acpi_info
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Print generic "ACPI:" information message. There is no
* module/line/version info in order to keep the message simple.
*
* TBD: module_name and line_number args are not needed, should be removed.
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_info(const char *module_name, u32 line_number, const char *format, ...)
{
va_list arg_list;
ACPI_MSG_REDIRECT_BEGIN;
acpi_os_printf(ACPI_MSG_INFO);
va_start(arg_list, format);
acpi_os_vprintf(format, arg_list);
acpi_os_printf("\n");
va_end(arg_list);
ACPI_MSG_REDIRECT_END;
}
ACPI_EXPORT_SYMBOL(acpi_info)
/*
* The remainder of this module contains internal error functions that may
* be configured out.
*/
#if !defined (ACPI_NO_ERROR_MESSAGES) && !defined (ACPI_BIN_APP)
/*******************************************************************************
*
* FUNCTION: acpi_ut_predefined_warning
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Pathname - Full pathname to the node
* node_flags - From Namespace node for the method/object
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Warnings for the predefined validation module. Messages are
* only emitted the first time a problem with a particular
* method/object is detected. This prevents a flood of error
* messages for methods that are repeatedly evaluated.
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_warning(const char *module_name,
u32 line_number,
char *pathname,
u8 node_flags, const char *format, ...)
{
va_list arg_list;
/*
* Warning messages for this method/object will be disabled after the
* first time a validation fails or an object is successfully repaired.
*/
if (node_flags & ANOBJ_EVALUATED) {
return;
}
acpi_os_printf(ACPI_MSG_WARNING "For %s: ", pathname);
va_start(arg_list, format);
acpi_os_vprintf(format, arg_list);
ACPI_MSG_SUFFIX;
va_end(arg_list);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_predefined_info
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Pathname - Full pathname to the node
* node_flags - From Namespace node for the method/object
* Format - Printf format string + additional args
*
* RETURN: None
*
* DESCRIPTION: Info messages for the predefined validation module. Messages
* are only emitted the first time a problem with a particular
* method/object is detected. This prevents a flood of
* messages for methods that are repeatedly evaluated.
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_info(const char *module_name,
u32 line_number,
char *pathname, u8 node_flags, const char *format, ...)
{
va_list arg_list;
/*
* Warning messages for this method/object will be disabled after the
* first time a validation fails or an object is successfully repaired.
*/
if (node_flags & ANOBJ_EVALUATED) {
return;
}
acpi_os_printf(ACPI_MSG_INFO "For %s: ", pathname);
va_start(arg_list, format);
acpi_os_vprintf(format, arg_list);
ACPI_MSG_SUFFIX;
va_end(arg_list);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_namespace_error
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* internal_name - Name or path of the namespace node
* lookup_status - Exception code from NS lookup
*
* RETURN: None
*
* DESCRIPTION: Print error message with the full pathname for the NS node.
*
******************************************************************************/
void
acpi_ut_namespace_error(const char *module_name,
u32 line_number,
const char *internal_name, acpi_status lookup_status)
{
acpi_status status;
u32 bad_name;
char *name = NULL;
ACPI_MSG_REDIRECT_BEGIN;
acpi_os_printf(ACPI_MSG_ERROR);
if (lookup_status == AE_BAD_CHARACTER) {
/* There is a non-ascii character in the name */
ACPI_MOVE_32_TO_32(&bad_name,
ACPI_CAST_PTR(u32, internal_name));
acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
} else {
/* Convert path to external format */
status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
internal_name, NULL, &name);
/* Print target name */
if (ACPI_SUCCESS(status)) {
acpi_os_printf("[%s]", name);
} else {
acpi_os_printf("[COULD NOT EXTERNALIZE NAME]");
}
if (name) {
ACPI_FREE(name);
}
}
acpi_os_printf(" Namespace lookup failure, %s",
acpi_format_exception(lookup_status));
ACPI_MSG_SUFFIX;
ACPI_MSG_REDIRECT_END;
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_method_error
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
* Message - Error message to use on failure
* prefix_node - Prefix relative to the path
* Path - Path to the node (optional)
* method_status - Execution status
*
* RETURN: None
*
* DESCRIPTION: Print error message with the full pathname for the method.
*
******************************************************************************/
void
acpi_ut_method_error(const char *module_name,
u32 line_number,
const char *message,
struct acpi_namespace_node *prefix_node,
const char *path, acpi_status method_status)
{
acpi_status status;
struct acpi_namespace_node *node = prefix_node;
ACPI_MSG_REDIRECT_BEGIN;
acpi_os_printf(ACPI_MSG_ERROR);
if (path) {
status =
acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
&node);
if (ACPI_FAILURE(status)) {
acpi_os_printf("[Could not get node by pathname]");
}
}
acpi_ns_print_node_pathname(node, message);
acpi_os_printf(", %s", acpi_format_exception(method_status));
ACPI_MSG_SUFFIX;
ACPI_MSG_REDIRECT_END;
}
#endif /* ACPI_NO_ERROR_MESSAGES */
......@@ -42,10 +42,7 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#ifdef CONFIG_ACPI_SYSFS_POWER
#include <linux/power_supply.h>
#endif
#define PREFIX "ACPI: "
......@@ -98,13 +95,12 @@ enum {
* due to bad math.
*/
ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
};
struct acpi_battery {
struct mutex lock;
#ifdef CONFIG_ACPI_SYSFS_POWER
struct power_supply bat;
#endif
struct acpi_device *device;
unsigned long update_time;
int rate_now;
......@@ -141,7 +137,6 @@ inline int acpi_battery_present(struct acpi_battery *battery)
return battery->device->status.battery_present;
}
#ifdef CONFIG_ACPI_SYSFS_POWER
static int acpi_battery_technology(struct acpi_battery *battery)
{
if (!strcasecmp("NiCd", battery->type))
......@@ -186,6 +181,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
int ret = 0;
struct acpi_battery *battery = to_acpi_battery(psy);
if (acpi_battery_present(battery)) {
......@@ -214,26 +210,44 @@ static int acpi_battery_get_property(struct power_supply *psy,
val->intval = battery->cycle_count;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
val->intval = battery->design_voltage * 1000;
if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
ret = -ENODEV;
else
val->intval = battery->design_voltage * 1000;
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
val->intval = battery->voltage_now * 1000;
if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
ret = -ENODEV;
else
val->intval = battery->voltage_now * 1000;
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
case POWER_SUPPLY_PROP_POWER_NOW:
val->intval = battery->rate_now * 1000;
if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
ret = -ENODEV;
else
val->intval = battery->rate_now * 1000;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
val->intval = battery->design_capacity * 1000;
if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
ret = -ENODEV;
else
val->intval = battery->design_capacity * 1000;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
case POWER_SUPPLY_PROP_ENERGY_FULL:
val->intval = battery->full_charge_capacity * 1000;
if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
ret = -ENODEV;
else
val->intval = battery->full_charge_capacity * 1000;
break;
case POWER_SUPPLY_PROP_CHARGE_NOW:
case POWER_SUPPLY_PROP_ENERGY_NOW:
val->intval = battery->capacity_now * 1000;
if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
ret = -ENODEV;
else
val->intval = battery->capacity_now * 1000;
break;
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = battery->model_number;
......@@ -245,9 +259,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
val->strval = battery->serial_number;
break;
default:
return -EINVAL;
ret = -EINVAL;
}
return 0;
return ret;
}
static enum power_supply_property charge_battery_props[] = {
......@@ -281,7 +295,6 @@ static enum power_supply_property energy_battery_props[] = {
POWER_SUPPLY_PROP_MANUFACTURER,
POWER_SUPPLY_PROP_SERIAL_NUMBER,
};
#endif
#ifdef CONFIG_ACPI_PROCFS_POWER
inline char *acpi_battery_units(struct acpi_battery *battery)
......@@ -412,6 +425,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
result = extract_package(battery, buffer.pointer,
info_offsets, ARRAY_SIZE(info_offsets));
kfree(buffer.pointer);
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
battery->full_charge_capacity = battery->design_capacity;
return result;
}
......@@ -448,6 +463,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
battery->rate_now != -1)
battery->rate_now = abs((s16)battery->rate_now);
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
&& battery->capacity_now >= 0 && battery->capacity_now <= 100)
battery->capacity_now = (battery->capacity_now *
battery->full_charge_capacity) / 100;
return result;
}
......@@ -492,7 +511,6 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery)
return acpi_battery_set_alarm(battery);
}
#ifdef CONFIG_ACPI_SYSFS_POWER
static ssize_t acpi_battery_alarm_show(struct device *dev,
struct device_attribute *attr,
char *buf)
......@@ -552,7 +570,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
power_supply_unregister(&battery->bat);
battery->bat.dev = NULL;
}
#endif
static void acpi_battery_quirks(struct acpi_battery *battery)
{
......@@ -561,6 +578,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
}
}
/*
* According to the ACPI spec, some kinds of primary batteries can
* report percentage battery remaining capacity directly to OS.
* In this case, it reports the Last Full Charged Capacity == 100
* and BatteryPresentRate == 0xFFFFFFFF.
*
* Now we found some battery reports percentage remaining capacity
* even if it's rechargeable.
* https://bugzilla.kernel.org/show_bug.cgi?id=15979
*
* Handle this correctly so that they won't break userspace.
*/
static void acpi_battery_quirks2(struct acpi_battery *battery)
{
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
return ;
if (battery->full_charge_capacity == 100 &&
battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
battery->capacity_now >=0 && battery->capacity_now <= 100) {
set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
battery->full_charge_capacity = battery->design_capacity;
battery->capacity_now = (battery->capacity_now *
battery->full_charge_capacity) / 100;
}
}
static int acpi_battery_update(struct acpi_battery *battery)
{
int result, old_present = acpi_battery_present(battery);
......@@ -568,9 +612,7 @@ static int acpi_battery_update(struct acpi_battery *battery)
if (result)
return result;
if (!acpi_battery_present(battery)) {
#ifdef CONFIG_ACPI_SYSFS_POWER
sysfs_remove_battery(battery);
#endif
battery->update_time = 0;
return 0;
}
......@@ -582,11 +624,11 @@ static int acpi_battery_update(struct acpi_battery *battery)
acpi_battery_quirks(battery);
acpi_battery_init_alarm(battery);
}
#ifdef CONFIG_ACPI_SYSFS_POWER
if (!battery->bat.dev)
sysfs_add_battery(battery);
#endif
return acpi_battery_get_state(battery);
result = acpi_battery_get_state(battery);
acpi_battery_quirks2(battery);
return result;
}
/* --------------------------------------------------------------------------
......@@ -867,26 +909,20 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
static void acpi_battery_notify(struct acpi_device *device, u32 event)
{
struct acpi_battery *battery = acpi_driver_data(device);
#ifdef CONFIG_ACPI_SYSFS_POWER
struct device *old;
#endif
if (!battery)
return;
#ifdef CONFIG_ACPI_SYSFS_POWER
old = battery->bat.dev;
#endif
acpi_battery_update(battery);
acpi_bus_generate_proc_event(device, event,
acpi_battery_present(battery));
acpi_bus_generate_netlink_event(device->pnp.device_class,
dev_name(&device->dev), event,
acpi_battery_present(battery));
#ifdef CONFIG_ACPI_SYSFS_POWER
/* acpi_battery_update could remove power_supply object */
if (old && battery->bat.dev)
power_supply_changed(&battery->bat);
#endif
}
static int acpi_battery_add(struct acpi_device *device)
......@@ -934,9 +970,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_remove_fs(device);
#endif
#ifdef CONFIG_ACPI_SYSFS_POWER
sysfs_remove_battery(battery);
#endif
mutex_destroy(&battery->lock);
kfree(battery);
return 0;
......
......@@ -935,6 +935,12 @@ static int __init acpi_bus_init(void)
goto error1;
}
/*
* _PDC control method may load dynamic SSDT tables,
* and we need to install the table handler before that.
*/
acpi_sysfs_init();
acpi_early_processor_set_pdc();
/*
......@@ -1026,7 +1032,6 @@ static int __init acpi_init(void)
acpi_scan_init();
acpi_ec_init();
acpi_power_init();
acpi_sysfs_init();
acpi_debugfs_init();
acpi_sleep_proc_init();
acpi_wakeup_device_init();
......
......@@ -338,7 +338,8 @@ static int acpi_button_add(struct acpi_device *device)
{
struct acpi_button *button;
struct input_dev *input;
char *hid, *name, *class;
const char *hid = acpi_device_hid(device);
char *name, *class;
int error;
button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
......@@ -353,7 +354,6 @@ static int acpi_button_add(struct acpi_device *device)
goto err_free_button;
}
hid = acpi_device_hid(device);
name = acpi_device_name(device);
class = acpi_device_class(device);
......
......@@ -725,6 +725,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
complete_dock(ds);
dock_event(ds, event, DOCK_EVENT);
dock_lock(ds, 1);
acpi_update_gpes();
break;
}
if (dock_present(ds) || dock_in_progress(ds))
......@@ -929,7 +930,7 @@ static struct attribute_group dock_attribute_group = {
* allocated and initialize a new dock station device. Find all devices
* that are on the dock station, and register for dock event notifications.
*/
static int dock_add(acpi_handle handle)
static int __init dock_add(acpi_handle handle)
{
int ret, id;
struct dock_station ds, *dock_station;
......@@ -1023,7 +1024,7 @@ static int dock_remove(struct dock_station *ds)
*
* This is called by acpi_walk_namespace to look for dock stations.
*/
static acpi_status
static __init acpi_status
find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
{
if (is_dock(handle))
......@@ -1032,7 +1033,7 @@ find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
return AE_OK;
}
static acpi_status
static __init acpi_status
find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
{
/* If bay is a dock, it's already handled */
......
......@@ -83,6 +83,11 @@ enum {
EC_FLAGS_BLOCKED, /* Transactions are blocked */
};
/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */
static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
module_param(ec_delay, uint, 0644);
MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
/* If we find an EC via the ECDT, we need to keep a ptr to its context */
/* External interfaces use first EC only, so remember */
typedef int (*acpi_ec_query_func) (void *data);
......@@ -210,7 +215,7 @@ static int ec_poll(struct acpi_ec *ec)
int repeat = 2; /* number of command restarts */
while (repeat--) {
unsigned long delay = jiffies +
msecs_to_jiffies(ACPI_EC_DELAY);
msecs_to_jiffies(ec_delay);
do {
/* don't sleep with disabled interrupts */
if (EC_FLAGS_MSI || irqs_disabled()) {
......@@ -265,7 +270,7 @@ static int ec_check_ibf0(struct acpi_ec *ec)
static int ec_wait_ibf0(struct acpi_ec *ec)
{
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
unsigned long delay = jiffies + msecs_to_jiffies(ec_delay);
/* interrupt wait manually if GPE mode is not active */
while (time_before(jiffies, delay))
if (wait_event_timeout(ec->wait, ec_check_ibf0(ec),
......
......@@ -27,8 +27,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <linux/thermal.h>
#include <acpi/acpi_bus.h>
......@@ -118,122 +116,6 @@ static struct thermal_cooling_device_ops fan_cooling_ops = {
.set_cur_state = fan_set_cur_state,
};
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCFS
static struct proc_dir_entry *acpi_fan_dir;
static int acpi_fan_read_state(struct seq_file *seq, void *offset)
{
struct acpi_device *device = seq->private;
int state = 0;
if (device) {
if (acpi_bus_get_power(device->handle, &state))
seq_printf(seq, "status: ERROR\n");
else
seq_printf(seq, "status: %s\n",
!state ? "on" : "off");
}
return 0;
}
static int acpi_fan_state_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_fan_read_state, PDE(inode)->data);
}
static ssize_t
acpi_fan_write_state(struct file *file, const char __user * buffer,
size_t count, loff_t * ppos)
{
int result = 0;
struct seq_file *m = file->private_data;
struct acpi_device *device = m->private;
char state_string[3] = { '\0' };
if (count > sizeof(state_string) - 1)
return -EINVAL;
if (copy_from_user(state_string, buffer, count))
return -EFAULT;
state_string[count] = '\0';
if ((state_string[0] < '0') || (state_string[0] > '3'))
return -EINVAL;
if (state_string[1] == '\n')
state_string[1] = '\0';
if (state_string[1] != '\0')
return -EINVAL;
result = acpi_bus_set_power(device->handle,
simple_strtoul(state_string, NULL, 0));
if (result)
return result;
return count;
}
static const struct file_operations acpi_fan_state_ops = {
.open = acpi_fan_state_open_fs,
.read = seq_read,
.write = acpi_fan_write_state,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
};
static int acpi_fan_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;
if (!device)
return -EINVAL;
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
acpi_fan_dir);
if (!acpi_device_dir(device))
return -ENODEV;
}
/* 'status' [R/W] */
entry = proc_create_data(ACPI_FAN_FILE_STATE,
S_IFREG | S_IRUGO | S_IWUSR,
acpi_device_dir(device),
&acpi_fan_state_ops,
device);
if (!entry)
return -ENODEV;
return 0;
}
static int acpi_fan_remove_fs(struct acpi_device *device)
{
if (acpi_device_dir(device)) {
remove_proc_entry(ACPI_FAN_FILE_STATE, acpi_device_dir(device));
remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
acpi_device_dir(device) = NULL;
}
return 0;
}
#else
static int acpi_fan_add_fs(struct acpi_device *device)
{
return 0;
}
static int acpi_fan_remove_fs(struct acpi_device *device)
{
return 0;
}
#endif
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
......@@ -284,10 +166,6 @@ static int acpi_fan_add(struct acpi_device *device)
dev_err(&device->dev, "Failed to create sysfs link "
"'device'\n");
result = acpi_fan_add_fs(device);
if (result)
goto end;
printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
acpi_device_name(device), acpi_device_bid(device),
!device->power.state ? "on" : "off");
......@@ -303,7 +181,6 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
if (!device || !cdev)
return -EINVAL;
acpi_fan_remove_fs(device);
sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
sysfs_remove_link(&cdev->device.kobj, "device");
thermal_cooling_device_unregister(cdev);
......@@ -347,19 +224,9 @@ static int __init acpi_fan_init(void)
{
int result = 0;
#ifdef CONFIG_ACPI_PROCFS
acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
if (!acpi_fan_dir)
return -ENODEV;
#endif
result = acpi_bus_register_driver(&acpi_fan_driver);
if (result < 0) {
#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
#endif
if (result < 0)
return -ENODEV;
}
return 0;
}
......@@ -369,10 +236,6 @@ static void __exit acpi_fan_exit(void)
acpi_bus_unregister_driver(&acpi_fan_driver);
#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
#endif
return;
}
......
......@@ -95,8 +95,25 @@ struct acpi_res_list {
static LIST_HEAD(resource_list_head);
static DEFINE_SPINLOCK(acpi_res_lock);
/*
* This list of permanent mappings is for memory that may be accessed from
* interrupt context, where we can't do the ioremap().
*/
struct acpi_ioremap {
struct list_head list;
void __iomem *virt;
acpi_physical_address phys;
acpi_size size;
struct kref ref;
};
static LIST_HEAD(acpi_ioremaps);
static DEFINE_SPINLOCK(acpi_ioremap_lock);
#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
static char osi_additional_string[OSI_STRING_LENGTH_MAX];
static char osi_setup_string[OSI_STRING_LENGTH_MAX];
static void __init acpi_osi_setup_late(void);
/*
* The story of _OSI(Linux)
......@@ -138,6 +155,20 @@ static struct osi_linux {
unsigned int known:1;
} osi_linux = { 0, 0, 0, 0};
static u32 acpi_osi_handler(acpi_string interface, u32 supported)
{
if (!strcmp("Linux", interface)) {
printk(KERN_NOTICE FW_BUG PREFIX
"BIOS _OSI(Linux) query %s%s\n",
osi_linux.enable ? "honored" : "ignored",
osi_linux.cmdline ? " via cmdline" :
osi_linux.dmi ? " via DMI" : "");
}
return supported;
}
static void __init acpi_request_region (struct acpi_generic_address *addr,
unsigned int length, char *desc)
{
......@@ -185,36 +216,6 @@ static int __init acpi_reserve_resources(void)
}
device_initcall(acpi_reserve_resources);
acpi_status __init acpi_os_initialize(void)
{
return AE_OK;
}
acpi_status acpi_os_initialize1(void)
{
kacpid_wq = create_workqueue("kacpid");
kacpi_notify_wq = create_workqueue("kacpi_notify");
kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
BUG_ON(!kacpid_wq);
BUG_ON(!kacpi_notify_wq);
BUG_ON(!kacpi_hotplug_wq);
return AE_OK;
}
acpi_status acpi_os_terminate(void)
{
if (acpi_irq_handler) {
acpi_os_remove_interrupt_handler(acpi_irq_irq,
acpi_irq_handler);
}
destroy_workqueue(kacpid_wq);
destroy_workqueue(kacpi_notify_wq);
destroy_workqueue(kacpi_hotplug_wq);
return AE_OK;
}
void acpi_os_printf(const char *fmt, ...)
{
va_list args;
......@@ -260,29 +261,135 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
}
}
/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
static struct acpi_ioremap *
acpi_map_lookup(acpi_physical_address phys, acpi_size size)
{
struct acpi_ioremap *map;
list_for_each_entry_rcu(map, &acpi_ioremaps, list)
if (map->phys <= phys &&
phys + size <= map->phys + map->size)
return map;
return NULL;
}
/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
static void __iomem *
acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size)
{
struct acpi_ioremap *map;
map = acpi_map_lookup(phys, size);
if (map)
return map->virt + (phys - map->phys);
return NULL;
}
/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
static struct acpi_ioremap *
acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
{
struct acpi_ioremap *map;
list_for_each_entry_rcu(map, &acpi_ioremaps, list)
if (map->virt <= virt &&
virt + size <= map->virt + map->size)
return map;
return NULL;
}
void __iomem *__init_refok
acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
{
struct acpi_ioremap *map, *tmp_map;
unsigned long flags, pg_sz;
void __iomem *virt;
phys_addr_t pg_off;
if (phys > ULONG_MAX) {
printk(KERN_ERR PREFIX "Cannot map memory that high\n");
return NULL;
}
if (acpi_gbl_permanent_mmap)
/*
* ioremap checks to ensure this is in reserved space
*/
return ioremap((unsigned long)phys, size);
else
if (!acpi_gbl_permanent_mmap)
return __acpi_map_table((unsigned long)phys, size);
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (!map)
return NULL;
pg_off = round_down(phys, PAGE_SIZE);
pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
virt = ioremap(pg_off, pg_sz);
if (!virt) {
kfree(map);
return NULL;
}
INIT_LIST_HEAD(&map->list);
map->virt = virt;
map->phys = pg_off;
map->size = pg_sz;
kref_init(&map->ref);
spin_lock_irqsave(&acpi_ioremap_lock, flags);
/* Check if page has already been mapped. */
tmp_map = acpi_map_lookup(phys, size);
if (tmp_map) {
kref_get(&tmp_map->ref);
spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
iounmap(map->virt);
kfree(map);
return tmp_map->virt + (phys - tmp_map->phys);
}
list_add_tail_rcu(&map->list, &acpi_ioremaps);
spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
return map->virt + (phys - map->phys);
}
EXPORT_SYMBOL_GPL(acpi_os_map_memory);
static void acpi_kref_del_iomap(struct kref *ref)
{
struct acpi_ioremap *map;
map = container_of(ref, struct acpi_ioremap, ref);
list_del_rcu(&map->list);
}
void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
{
if (acpi_gbl_permanent_mmap)
iounmap(virt);
else
struct acpi_ioremap *map;
unsigned long flags;
int del;
if (!acpi_gbl_permanent_mmap) {
__acpi_unmap_table(virt, size);
return;
}
spin_lock_irqsave(&acpi_ioremap_lock, flags);
map = acpi_map_lookup_virt(virt, size);
if (!map) {
spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt);
dump_stack();
return;
}
del = kref_put(&map->ref, acpi_kref_del_iomap);
spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
if (!del)
return;
synchronize_rcu();
iounmap(map->virt);
kfree(map);
}
EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
......@@ -292,6 +399,44 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
__acpi_unmap_table(virt, size);
}
int acpi_os_map_generic_address(struct acpi_generic_address *addr)
{
void __iomem *virt;
if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return 0;
if (!addr->address || !addr->bit_width)
return -EINVAL;
virt = acpi_os_map_memory(addr->address, addr->bit_width / 8);
if (!virt)
return -EIO;
return 0;
}
EXPORT_SYMBOL_GPL(acpi_os_map_generic_address);
void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
{
void __iomem *virt;
unsigned long flags;
acpi_size size = addr->bit_width / 8;
if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
return;
if (!addr->address || !addr->bit_width)
return;
spin_lock_irqsave(&acpi_ioremap_lock, flags);
virt = acpi_map_vaddr_lookup(addr->address, size);
spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
acpi_os_unmap_memory(virt, size);
}
EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address);
#ifdef ACPI_FUTURE_USAGE
acpi_status
acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
......@@ -495,8 +640,15 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
{
u32 dummy;
void __iomem *virt_addr;
virt_addr = ioremap(phys_addr, width);
int size = width / 8, unmap = 0;
rcu_read_lock();
virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
rcu_read_unlock();
if (!virt_addr) {
virt_addr = ioremap(phys_addr, size);
unmap = 1;
}
if (!value)
value = &dummy;
......@@ -514,7 +666,8 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
BUG();
}
iounmap(virt_addr);
if (unmap)
iounmap(virt_addr);
return AE_OK;
}
......@@ -523,8 +676,15 @@ acpi_status
acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
{
void __iomem *virt_addr;
virt_addr = ioremap(phys_addr, width);
int size = width / 8, unmap = 0;
rcu_read_lock();
virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
rcu_read_unlock();
if (!virt_addr) {
virt_addr = ioremap(phys_addr, size);
unmap = 1;
}
switch (width) {
case 8:
......@@ -540,16 +700,18 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
BUG();
}
iounmap(virt_addr);
if (unmap)
iounmap(virt_addr);
return AE_OK;
}
acpi_status
acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
u32 *value, u32 width)
u64 *value, u32 width)
{
int result, size;
u32 value32;
if (!value)
return AE_BAD_PARAMETER;
......@@ -570,7 +732,8 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
result = raw_pci_read(pci_id->segment, pci_id->bus,
PCI_DEVFN(pci_id->device, pci_id->function),
reg, size, value);
reg, size, &value32);
*value = value32;
return (result ? AE_ERROR : AE_OK);
}
......@@ -602,74 +765,6 @@ acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
return (result ? AE_ERROR : AE_OK);
}
/* TODO: Change code to take advantage of driver model more */
static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */
acpi_handle chandle, /* current node */
struct acpi_pci_id **id,
int *is_bridge, u8 * bus_number)
{
acpi_handle handle;
struct acpi_pci_id *pci_id = *id;
acpi_status status;
unsigned long long temp;
acpi_object_type type;
acpi_get_parent(chandle, &handle);
if (handle != rhandle) {
acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
bus_number);
status = acpi_get_type(handle, &type);
if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
return;
status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
&temp);
if (ACPI_SUCCESS(status)) {
u32 val;
pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
if (*is_bridge)
pci_id->bus = *bus_number;
/* any nicer way to get bus number of bridge ? */
status =
acpi_os_read_pci_configuration(pci_id, 0x0e, &val,
8);
if (ACPI_SUCCESS(status)
&& ((val & 0x7f) == 1 || (val & 0x7f) == 2)) {
status =
acpi_os_read_pci_configuration(pci_id, 0x18,
&val, 8);
if (!ACPI_SUCCESS(status)) {
/* Certainly broken... FIX ME */
return;
}
*is_bridge = 1;
pci_id->bus = val;
status =
acpi_os_read_pci_configuration(pci_id, 0x19,
&val, 8);
if (ACPI_SUCCESS(status)) {
*bus_number = val;
}
} else
*is_bridge = 0;
}
}
}
void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
acpi_handle chandle, /* current node */
struct acpi_pci_id **id)
{
int is_bridge = 1;
u8 bus_number = (*id)->bus;
acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
}
static void acpi_os_execute_deferred(struct work_struct *work)
{
struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
......@@ -779,16 +874,6 @@ void acpi_os_wait_events_complete(void *context)
EXPORT_SYMBOL(acpi_os_wait_events_complete);
/*
* Allocate the memory for a spinlock and initialize it.
*/
acpi_status acpi_os_create_lock(acpi_spinlock * handle)
{
spin_lock_init(*handle);
return AE_OK;
}
/*
* Deallocate the memory for a spinlock.
*/
......@@ -977,6 +1062,12 @@ static void __init set_osi_linux(unsigned int enable)
printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
enable ? "Add": "Delet");
}
if (osi_linux.enable)
acpi_osi_setup("Linux");
else
acpi_osi_setup("!Linux");
return;
}
......@@ -1011,21 +1102,33 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
* string starting with '!' disables that string
* otherwise string is added to list, augmenting built-in strings
*/
int __init acpi_osi_setup(char *str)
static void __init acpi_osi_setup_late(void)
{
if (str == NULL || *str == '\0') {
printk(KERN_INFO PREFIX "_OSI method disabled\n");
acpi_gbl_create_osi_method = FALSE;
} else if (!strcmp("!Linux", str)) {
char *str = osi_setup_string;
if (*str == '\0')
return;
if (!strcmp("!Linux", str)) {
acpi_cmdline_osi_linux(0); /* !enable */
} else if (*str == '!') {
if (acpi_osi_invalidate(++str) == AE_OK)
if (acpi_remove_interface(++str) == AE_OK)
printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
} else if (!strcmp("Linux", str)) {
acpi_cmdline_osi_linux(1); /* enable */
} else if (*osi_additional_string == '\0') {
strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX);
printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
} else {
if (acpi_install_interface(str) == AE_OK)
printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
}
}
int __init acpi_osi_setup(char *str)
{
if (str == NULL || *str == '\0') {
printk(KERN_INFO PREFIX "_OSI method disabled\n");
acpi_gbl_create_osi_method = FALSE;
} else {
strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX);
}
return 1;
......@@ -1152,21 +1255,6 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
}
EXPORT_SYMBOL(acpi_check_region);
int acpi_check_mem_region(resource_size_t start, resource_size_t n,
const char *name)
{
struct resource res = {
.start = start,
.end = start + n - 1,
.name = name,
.flags = IORESOURCE_MEM,
};
return acpi_check_resource_conflict(&res);
}
EXPORT_SYMBOL(acpi_check_mem_region);
/*
* Let drivers know whether the resource checks are effective
*/
......@@ -1282,38 +1370,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_os_validate_interface
*
* PARAMETERS: interface - Requested interface to be validated
*
* RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise
*
* DESCRIPTION: Match an interface string to the interfaces supported by the
* host. Strings originate from an AML call to the _OSI method.
*
*****************************************************************************/
acpi_status
acpi_os_validate_interface (char *interface)
{
if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
return AE_OK;
if (!strcmp("Linux", interface)) {
printk(KERN_NOTICE PREFIX
"BIOS _OSI(Linux) query %s%s\n",
osi_linux.enable ? "honored" : "ignored",
osi_linux.cmdline ? " via cmdline" :
osi_linux.dmi ? " via DMI" : "");
if (osi_linux.enable)
return AE_OK;
}
return AE_SUPPORT;
}
static inline int acpi_res_list_add(struct acpi_res_list *res)
{
struct acpi_res_list *res_list_elem;
......@@ -1462,5 +1518,46 @@ acpi_os_validate_address (
}
return AE_OK;
}
#endif
acpi_status __init acpi_os_initialize(void)
{
acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1b_event_block);
acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe0_block);
acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe1_block);
return AE_OK;
}
acpi_status acpi_os_initialize1(void)
{
kacpid_wq = create_workqueue("kacpid");
kacpi_notify_wq = create_workqueue("kacpi_notify");
kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
BUG_ON(!kacpid_wq);
BUG_ON(!kacpi_notify_wq);
BUG_ON(!kacpi_hotplug_wq);
acpi_install_interface_handler(acpi_osi_handler);
acpi_osi_setup_late();
return AE_OK;
}
acpi_status acpi_os_terminate(void)
{
if (acpi_irq_handler) {
acpi_os_remove_interrupt_handler(acpi_irq_irq,
acpi_irq_handler);
}
acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe1_block);
acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe0_block);
acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1b_event_block);
acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
destroy_workqueue(kacpid_wq);
destroy_workqueue(kacpi_notify_wq);
destroy_workqueue(kacpi_hotplug_wq);
return AE_OK;
}
......@@ -32,7 +32,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <linux/pci.h>
......
......@@ -34,7 +34,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <linux/pci.h>
......
......@@ -27,7 +27,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
......
......@@ -80,18 +80,13 @@ static struct acpi_driver acpi_power_driver = {
},
};
struct acpi_power_reference {
struct list_head node;
struct acpi_device *device;
};
struct acpi_power_resource {
struct acpi_device * device;
acpi_bus_id name;
u32 system_level;
u32 order;
unsigned int ref_count;
struct mutex resource_lock;
struct list_head reference;
};
static struct list_head acpi_power_resource_list;
......@@ -184,101 +179,89 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
return result;
}
static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
static int __acpi_power_on(struct acpi_power_resource *resource)
{
int result = 0;
int found = 0;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
struct list_head *node, *next;
struct acpi_power_reference *ref;
status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
if (ACPI_FAILURE(status))
return -ENODEV;
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
resource->name));
return 0;
}
static int acpi_power_on(acpi_handle handle)
{
int result = 0;
struct acpi_power_resource *resource = NULL;
result = acpi_power_get_context(handle, &resource);
if (result)
return result;
mutex_lock(&resource->resource_lock);
list_for_each_safe(node, next, &resource->reference) {
ref = container_of(node, struct acpi_power_reference, node);
if (dev->handle == ref->device->handle) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already referenced by resource [%s]\n",
dev->pnp.bus_id, resource->name));
found = 1;
break;
}
}
if (!found) {
ref = kmalloc(sizeof (struct acpi_power_reference),
irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
if (!ref) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "kmalloc() failed\n"));
mutex_unlock(&resource->resource_lock);
return -ENOMEM;
}
list_add_tail(&ref->node, &resource->reference);
ref->device = dev;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] added to resource [%s] references\n",
dev->pnp.bus_id, resource->name));
if (resource->ref_count++) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Power resource [%s] already on",
resource->name));
} else {
result = __acpi_power_on(resource);
}
mutex_unlock(&resource->resource_lock);
status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
if (ACPI_FAILURE(status))
return -ENODEV;
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D0;
mutex_unlock(&resource->resource_lock);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
resource->name));
return 0;
}
static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
static int acpi_power_off_device(acpi_handle handle)
{
int result = 0;
acpi_status status = AE_OK;
struct acpi_power_resource *resource = NULL;
struct list_head *node, *next;
struct acpi_power_reference *ref;
result = acpi_power_get_context(handle, &resource);
if (result)
return result;
mutex_lock(&resource->resource_lock);
list_for_each_safe(node, next, &resource->reference) {
ref = container_of(node, struct acpi_power_reference, node);
if (dev->handle == ref->device->handle) {
list_del(&ref->node);
kfree(ref);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] removed from resource [%s] references\n",
dev->pnp.bus_id, resource->name));
break;
}
if (!resource->ref_count) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Power resource [%s] already off",
resource->name));
goto unlock;
}
if (!list_empty(&resource->reference)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cannot turn resource [%s] off - resource is in use\n",
resource->name));
mutex_unlock(&resource->resource_lock);
return 0;
if (--resource->ref_count) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Power resource [%s] still in use\n",
resource->name));
goto unlock;
}
mutex_unlock(&resource->resource_lock);
status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL);
if (ACPI_FAILURE(status))
return -ENODEV;
if (ACPI_FAILURE(status)) {
result = -ENODEV;
} else {
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D3;
/* Update the power resource's _device_ power state */
resource->device->power.state = ACPI_STATE_D3;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Power resource [%s] turned off\n",
resource->name));
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
resource->name));
unlock:
mutex_unlock(&resource->resource_lock);
return 0;
return result;
}
/**
......@@ -364,7 +347,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
/* Open power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) {
int ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
int ret = acpi_power_on(dev->wakeup.resources.handles[i]);
if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
......@@ -420,7 +403,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
/* Close power resource */
for (i = 0; i < dev->wakeup.resources.count; i++) {
int ret = acpi_power_off_device(
dev->wakeup.resources.handles[i], dev);
dev->wakeup.resources.handles[i]);
if (ret) {
printk(KERN_ERR PREFIX "Transition power state\n");
dev->wakeup.flags.valid = 0;
......@@ -500,7 +483,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
* (e.g. so the device doesn't lose power while transitioning).
*/
for (i = 0; i < tl->count; i++) {
result = acpi_power_on(tl->handles[i], device);
result = acpi_power_on(tl->handles[i]);
if (result)
goto end;
}
......@@ -513,7 +496,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
* Then we dereference all power resources used in the current list.
*/
for (i = 0; i < cl->count; i++) {
result = acpi_power_off_device(cl->handles[i], device);
result = acpi_power_off_device(cl->handles[i]);
if (result)
goto end;
}
......@@ -551,7 +534,6 @@ static int acpi_power_add(struct acpi_device *device)
resource->device = device;
mutex_init(&resource->resource_lock);
INIT_LIST_HEAD(&resource->reference);
strcpy(resource->name, device->pnp.bus_id);
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
......@@ -594,22 +576,14 @@ static int acpi_power_add(struct acpi_device *device)
static int acpi_power_remove(struct acpi_device *device, int type)
{
struct acpi_power_resource *resource = NULL;
struct list_head *node, *next;
struct acpi_power_resource *resource;
if (!device || !acpi_driver_data(device))
if (!device)
return -EINVAL;
resource = acpi_driver_data(device);
mutex_lock(&resource->resource_lock);
list_for_each_safe(node, next, &resource->reference) {
struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node);
list_del(&ref->node);
kfree(ref);
}
mutex_unlock(&resource->resource_lock);
if (!resource)
return -EINVAL;
kfree(resource);
......@@ -619,29 +593,28 @@ static int acpi_power_remove(struct acpi_device *device, int type)
static int acpi_power_resume(struct acpi_device *device)
{
int result = 0, state;
struct acpi_power_resource *resource = NULL;
struct acpi_power_reference *ref;
struct acpi_power_resource *resource;
if (!device || !acpi_driver_data(device))
if (!device)
return -EINVAL;
resource = acpi_driver_data(device);
if (!resource)
return -EINVAL;
mutex_lock(&resource->resource_lock);
result = acpi_power_get_state(device->handle, &state);
if (result)
return result;
goto unlock;
mutex_lock(&resource->resource_lock);
if (state == ACPI_POWER_RESOURCE_STATE_OFF &&
!list_empty(&resource->reference)) {
ref = container_of(resource->reference.next, struct acpi_power_reference, node);
mutex_unlock(&resource->resource_lock);
result = acpi_power_on(device->handle, ref->device);
return result;
}
if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count)
result = __acpi_power_on(resource);
unlock:
mutex_unlock(&resource->resource_lock);
return 0;
return result;
}
int __init acpi_power_init(void)
......
......@@ -40,8 +40,10 @@
#include <linux/pm.h>
#include <linux/cpufreq.h>
#include <linux/cpu.h>
#ifdef CONFIG_ACPI_PROCFS
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#endif
#include <linux/dmi.h>
#include <linux/moduleparam.h>
#include <linux/cpuidle.h>
......@@ -244,6 +246,7 @@ static int acpi_processor_errata(struct acpi_processor *pr)
return result;
}
#ifdef CONFIG_ACPI_PROCFS
static struct proc_dir_entry *acpi_processor_dir = NULL;
static int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
......@@ -280,7 +283,16 @@ static int acpi_processor_remove_fs(struct acpi_device *device)
return 0;
}
#else
static inline int acpi_processor_add_fs(struct acpi_device *device)
{
return 0;
}
static inline int acpi_processor_remove_fs(struct acpi_device *device)
{
return 0;
}
#endif
/* --------------------------------------------------------------------------
Driver Interface
-------------------------------------------------------------------------- */
......@@ -842,9 +854,11 @@ static int __init acpi_processor_init(void)
memset(&errata, 0, sizeof(errata));
#ifdef CONFIG_ACPI_PROCFS
acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
if (!acpi_processor_dir)
return -ENOMEM;
#endif
if (!cpuidle_register_driver(&acpi_idle_driver)) {
printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
......@@ -871,7 +885,9 @@ static int __init acpi_processor_init(void)
out_cpuidle:
cpuidle_unregister_driver(&acpi_idle_driver);
#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
#endif
return result;
}
......@@ -891,7 +907,9 @@ static void __exit acpi_processor_exit(void)
cpuidle_unregister_driver(&acpi_idle_driver);
#ifdef CONFIG_ACPI_PROCFS
remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
#endif
return;
}
......@@ -899,6 +917,4 @@ static void __exit acpi_processor_exit(void)
module_init(acpi_processor_init);
module_exit(acpi_processor_exit);
EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
MODULE_ALIAS("processor");
......@@ -64,7 +64,6 @@
#define ACPI_PROCESSOR_CLASS "processor"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_idle");
#define ACPI_PROCESSOR_FILE_POWER "power"
#define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY)
#define C2_OVERHEAD 1 /* 1us */
#define C3_OVERHEAD 1 /* 1us */
......
此差异已折叠。
......@@ -32,8 +32,10 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/cpufreq.h>
#ifdef CONFIG_ACPI_PROCFS
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#endif
#include <asm/io.h>
#include <asm/uaccess.h>
......@@ -1214,6 +1216,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
return result;
}
#ifdef CONFIG_ACPI_PROCFS
/* proc interface */
static int acpi_processor_throttling_seq_show(struct seq_file *seq,
void *offset)
......@@ -1322,3 +1325,4 @@ const struct file_operations acpi_processor_throttling_fops = {
.llseek = seq_lseek,
.release = single_release,
};
#endif
此差异已折叠。
此差异已折叠。
......@@ -25,7 +25,9 @@
#include "internal.h"
#include "sleep.h"
u8 sleep_states[ACPI_S_STATE_COUNT];
static u8 sleep_states[ACPI_S_STATE_COUNT];
static u32 acpi_target_sleep_state = ACPI_STATE_S0;
static void acpi_sleep_tts_switch(u32 acpi_state)
{
......@@ -79,8 +81,6 @@ static int acpi_sleep_prepare(u32 acpi_state)
}
#ifdef CONFIG_ACPI_SLEEP
static u32 acpi_target_sleep_state = ACPI_STATE_S0;
/*
* The ACPI specification wants us to save NVS memory regions during hibernation
* and to restore them during the subsequent resume. Windows does that also for
......@@ -419,6 +419,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
},
},
{
.callback = init_nvs_nosave,
.ident = "Sony Vaio VPCEB1Z1E",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
},
},
{},
};
#endif /* CONFIG_SUSPEND */
......@@ -562,7 +570,7 @@ int acpi_suspend(u32 acpi_state)
return -EINVAL;
}
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM_OPS
/**
* acpi_pm_device_sleep_state - return preferred power state of ACPI device
* in the system sleep state given by %acpi_target_sleep_state
......@@ -624,7 +632,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
* can wake the system. _S0W may be valid, too.
*/
if (acpi_target_sleep_state == ACPI_STATE_S0 ||
(device_may_wakeup(dev) && adev->wakeup.state.enabled &&
(device_may_wakeup(dev) &&
adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
acpi_status status;
......@@ -632,7 +640,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
status = acpi_evaluate_integer(handle, acpi_method, NULL,
&d_max);
if (ACPI_FAILURE(status)) {
d_max = d_min;
if (acpi_target_sleep_state != ACPI_STATE_S0 ||
status != AE_NOT_FOUND)
d_max = d_min;
} else if (d_max < d_min) {
/* Warn the user of the broken DSDT */
printk(KERN_WARNING "ACPI: Wrong value from %s\n",
......@@ -646,7 +656,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
*d_min_p = d_min;
return d_max;
}
#endif /* CONFIG_PM_OPS */
#ifdef CONFIG_PM_SLEEP
/**
* acpi_pm_device_sleep_wake - enable or disable the system wake-up
* capability of given device
......@@ -677,7 +689,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
return error;
}
#endif
#endif /* CONFIG_PM_SLEEP */
static void acpi_power_off_prepare(void)
{
......@@ -702,7 +714,7 @@ static void acpi_power_off(void)
* paths through the BIOS, so disable _GTS and _BFS by default,
* but do speak up and offer the option to enable them.
*/
void __init acpi_gts_bfs_check(void)
static void __init acpi_gts_bfs_check(void)
{
acpi_handle dummy;
......
extern u8 sleep_states[];
extern int acpi_suspend(u32 state);
extern void acpi_enable_wakeup_devices(u8 sleep_state);
......
此差异已折叠。
此差异已折叠。
......@@ -12,11 +12,12 @@ void pnp_unregister_protocol(struct pnp_protocol *protocol);
#define PNP_EISA_ID_MASK 0x7fffffff
void pnp_eisa_id_to_string(u32 id, char *str);
struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid);
struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id,
const char *pnpid);
struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
int pnp_add_device(struct pnp_dev *dev);
struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id);
int pnp_add_card(struct pnp_card *card);
void pnp_remove_card(struct pnp_card *card);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册