diff options
Diffstat (limited to 'drivers/acpi')
62 files changed, 2337 insertions, 2632 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 88681aca88c5..3f3489c5ca8c 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -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. diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 56205a0b85df..ba9afeaa23ac 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -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 diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index d93cc06f4bf8..a7e1d1aa4107 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -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 diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 48faf3eba9fb..72e9d5eb083c 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -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); diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 36867cd70eac..a6f99cc37a19 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -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); diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 1d192142c691..ad88fcae4eb9 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -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; /***************************************************************************** * diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 120b3af56596..167470ad2d21 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -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 diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 7dad9160f209..2ceb0c05b2d7 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -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; diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 9894929a2abb..8d5c9e0a495f 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -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 diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 9f60ff002203..d44d3bc5b847 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -339,18 +339,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); acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info); diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 54857fa87aaf..bdbfaf22bd14 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -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) */ diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 35df755251ce..72e4183c1937 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -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, @@ -395,6 +393,21 @@ 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 */ void @@ -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 */ diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index 64750ee96e20..d94dd8974b55 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -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; } } diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index d555b374e314..6b0b5d08d97a 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -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: diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index 303618889da0..c61c3039c31a 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -95,47 +95,6 @@ acpi_status acpi_ev_initialize_events(void) /******************************************************************************* * - * 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 * * PARAMETERS: None diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 85445fb5844e..020add3eee1c 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -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); } diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 3084c5de1bba..2c7def95f721 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -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)); diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index df0aea9a8cfd..fcaed9fb44ff 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -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); diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index f40d271bf568..0b47a6dc9290 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -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); diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 14e48add32fa..36af222cac65 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -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 */ diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 304825528d48..a1dabe3fd8ae 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -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); +} diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 541cbc1544d5..ce9314f79451 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -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, diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 047217303a4b..38293fd3e088 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -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); } diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index f73be97043c0..6af14e43f839 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -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) */ diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 98a331d2249b..7aae29f73d3f 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -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", diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 8819d2ac5aee..de17e10da0ed 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -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: diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c new file mode 100644 index 000000000000..ad21c7d8bf4f --- /dev/null +++ b/drivers/acpi/acpica/hwpci.c @@ -0,0 +1,412 @@ +/******************************************************************************* + * + * 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); +} diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 4009498fbabd..4ef9f43ea926 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -74,10 +74,18 @@ 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 */ @@ -321,6 +333,157 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, /****************************************************************************** * + * 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 * * PARAMETERS: Data - Pointer to validation data structure diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index e1add3491b04..a7d6ad9c111b 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -60,104 +60,6 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search); /******************************************************************************* * - * 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 * * PARAMETERS: Node - Object diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 1728cb9bf600..d2ff4325c427 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -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) { diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 983510640059..f21c486929a5 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -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: ", diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 6dfdeb653490..22f59ef604e0 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -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 diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 0558747579ef..e87bc6760be6 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -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 */ diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index 1397fadd0d4b..d2906328535d 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -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; } diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index a39c93dac719..c1b1c803ea9b 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -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 */ diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c index 35059a14eb72..49cf7b7fd816 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c @@ -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) diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index e8d0724ee403..c7d0e05ef5a4 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -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); -} diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index f5cca3a1300c..d9efa495b433 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -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) { diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c new file mode 100644 index 000000000000..18c59a85fdca --- /dev/null +++ b/drivers/acpi/acpica/utosi.c @@ -0,0 +1,380 @@ +/****************************************************************************** + * + * 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); +} diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 7f8cefcb2b32..1f484c9a6888 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -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()); @@ -290,19 +299,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 -- * thus wasting non-paged memory. @@ -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 */ diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c new file mode 100644 index 000000000000..6f12e314fbae --- /dev/null +++ b/drivers/acpi/acpica/utxferror.c @@ -0,0 +1,415 @@ +/******************************************************************************* + * + * 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 */ diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 98417201e9ce..95649d373071 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -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; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 310e3b9749cb..d68bd61072bb 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -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(); diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 1575a9b51f1d..71ef9cd0735f 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -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); diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 3fe29e992be8..81514a4918cc 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -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 */ diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index f31291ba94d0..372ff80b7b0c 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -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), diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index d94d2953c974..60049080c869 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -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> @@ -119,122 +117,6 @@ static struct thermal_cooling_device_ops fan_cooling_ops = { }; /* -------------------------------------------------------------------------- - 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; } diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 65b25a303b86..966feddf6b1b 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -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); @@ -780,16 +875,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. */ void acpi_os_delete_lock(acpi_spinlock handle) @@ -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; +} diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index e4804fb05e23..f907cfbfa13c 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -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> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 8d47a5846aeb..9ff80a7e9f6a 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -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> diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 3ba8d1f44a73..96668ad09622 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -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> diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 844c155aeb0f..67dedeed144c 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -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) diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 347eb21b2353..85e48047d7b0 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -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"); diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 07a8bb6506f7..dcb38f8ddfda 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -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 */ diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 953b25fb9869..fde49b9b1d99 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -44,47 +44,6 @@ #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_thermal"); -/* -------------------------------------------------------------------------- - Limit Interface - -------------------------------------------------------------------------- */ -static int acpi_processor_apply_limit(struct acpi_processor *pr) -{ - int result = 0; - u16 px = 0; - u16 tx = 0; - - - if (!pr) - return -EINVAL; - - if (!pr->flags.limit) - return -ENODEV; - - if (pr->flags.throttling) { - if (pr->limit.user.tx > tx) - tx = pr->limit.user.tx; - if (pr->limit.thermal.tx > tx) - tx = pr->limit.thermal.tx; - - result = acpi_processor_set_throttling(pr, tx, false); - if (result) - goto end; - } - - pr->limit.state.px = px; - pr->limit.state.tx = tx; - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Processor [%d] limit set to (P%d:T%d)\n", pr->id, - pr->limit.state.px, pr->limit.state.tx)); - - end: - if (result) - printk(KERN_ERR PREFIX "Unable to set limit\n"); - - return result; -} - #ifdef CONFIG_CPU_FREQ /* If a passive cooling situation is detected, primarily CPUfreq is used, as it @@ -107,36 +66,6 @@ static int cpu_has_cpufreq(unsigned int cpu) return 1; } -static int acpi_thermal_cpufreq_increase(unsigned int cpu) -{ - if (!cpu_has_cpufreq(cpu)) - return -ENODEV; - - if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) < - CPUFREQ_THERMAL_MAX_STEP) { - per_cpu(cpufreq_thermal_reduction_pctg, cpu)++; - cpufreq_update_policy(cpu); - return 0; - } - - return -ERANGE; -} - -static int acpi_thermal_cpufreq_decrease(unsigned int cpu) -{ - if (!cpu_has_cpufreq(cpu)) - return -ENODEV; - - if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) > - (CPUFREQ_THERMAL_MIN_STEP + 1)) - per_cpu(cpufreq_thermal_reduction_pctg, cpu)--; - else - per_cpu(cpufreq_thermal_reduction_pctg, cpu) = 0; - cpufreq_update_policy(cpu); - /* We reached max freq again and can leave passive mode */ - return !per_cpu(cpufreq_thermal_reduction_pctg, cpu); -} - static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, unsigned long event, void *data) { @@ -238,113 +167,6 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu) #endif -int acpi_processor_set_thermal_limit(acpi_handle handle, int type) -{ - int result = 0; - struct acpi_processor *pr = NULL; - struct acpi_device *device = NULL; - int tx = 0, max_tx_px = 0; - - - if ((type < ACPI_PROCESSOR_LIMIT_NONE) - || (type > ACPI_PROCESSOR_LIMIT_DECREMENT)) - return -EINVAL; - - result = acpi_bus_get_device(handle, &device); - if (result) - return result; - - pr = acpi_driver_data(device); - if (!pr) - return -ENODEV; - - /* Thermal limits are always relative to the current Px/Tx state. */ - if (pr->flags.throttling) - pr->limit.thermal.tx = pr->throttling.state; - - /* - * Our default policy is to only use throttling at the lowest - * performance state. - */ - - tx = pr->limit.thermal.tx; - - switch (type) { - - case ACPI_PROCESSOR_LIMIT_NONE: - do { - result = acpi_thermal_cpufreq_decrease(pr->id); - } while (!result); - tx = 0; - break; - - case ACPI_PROCESSOR_LIMIT_INCREMENT: - /* if going up: P-states first, T-states later */ - - result = acpi_thermal_cpufreq_increase(pr->id); - if (!result) - goto end; - else if (result == -ERANGE) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "At maximum performance state\n")); - - if (pr->flags.throttling) { - if (tx == (pr->throttling.state_count - 1)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "At maximum throttling state\n")); - else - tx++; - } - break; - - case ACPI_PROCESSOR_LIMIT_DECREMENT: - /* if going down: T-states first, P-states later */ - - if (pr->flags.throttling) { - if (tx == 0) { - max_tx_px = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "At minimum throttling state\n")); - } else { - tx--; - goto end; - } - } - - result = acpi_thermal_cpufreq_decrease(pr->id); - if (result) { - /* - * We only could get -ERANGE, 1 or 0. - * In the first two cases we reached max freq again. - */ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "At minimum performance state\n")); - max_tx_px = 1; - } else - max_tx_px = 0; - - break; - } - - end: - if (pr->flags.throttling) { - pr->limit.thermal.px = 0; - pr->limit.thermal.tx = tx; - - result = acpi_processor_apply_limit(pr); - if (result) - printk(KERN_ERR PREFIX "Unable to set thermal limit\n"); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n", - pr->limit.thermal.px, pr->limit.thermal.tx)); - } else - result = 0; - if (max_tx_px) - return 1; - else - return result; -} - int acpi_processor_get_limit_info(struct acpi_processor *pr) { diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 730863855ed5..ff3632717c51 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -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 diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 4ff76e8174eb..e5dbedb16bbf 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -40,10 +40,7 @@ #include <linux/timer.h> #include <linux/jiffies.h> #include <linux/delay.h> - -#ifdef CONFIG_ACPI_SYSFS_POWER #include <linux/power_supply.h> -#endif #include "sbshc.h" @@ -85,9 +82,7 @@ static const struct acpi_device_id sbs_device_ids[] = { MODULE_DEVICE_TABLE(acpi, sbs_device_ids); struct acpi_battery { -#ifdef CONFIG_ACPI_SYSFS_POWER struct power_supply bat; -#endif struct acpi_sbs *sbs; #ifdef CONFIG_ACPI_PROCFS_POWER struct proc_dir_entry *proc_entry; @@ -120,9 +115,7 @@ struct acpi_battery { #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); struct acpi_sbs { -#ifdef CONFIG_ACPI_SYSFS_POWER struct power_supply charger; -#endif struct acpi_device *device; struct acpi_smb_hc *hc; struct mutex lock; @@ -166,7 +159,6 @@ static inline int acpi_battery_scale(struct acpi_battery *battery) acpi_battery_ipscale(battery); } -#ifdef CONFIG_ACPI_SYSFS_POWER static int sbs_get_ac_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -313,7 +305,6 @@ static enum power_supply_property sbs_energy_battery_props[] = { POWER_SUPPLY_PROP_MANUFACTURER, }; -#endif /* -------------------------------------------------------------------------- Smart Battery System Management @@ -449,7 +440,6 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) return result; } -#ifdef CONFIG_ACPI_SYSFS_POWER static ssize_t acpi_battery_alarm_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -479,7 +469,6 @@ static struct device_attribute alarm_attr = { .show = acpi_battery_alarm_show, .store = acpi_battery_alarm_store, }; -#endif /* -------------------------------------------------------------------------- FS Interface (/proc/acpi) @@ -798,7 +787,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) &acpi_battery_state_fops, &acpi_battery_alarm_fops, battery); #endif -#ifdef CONFIG_ACPI_SYSFS_POWER battery->bat.name = battery->name; battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; if (!acpi_battery_mode(battery)) { @@ -819,7 +807,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) goto end; battery->have_sysfs_alarm = 1; end: -#endif printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), battery->name, battery->present ? "present" : "absent"); @@ -828,17 +815,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { -#if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER) struct acpi_battery *battery = &sbs->battery[id]; -#endif -#ifdef CONFIG_ACPI_SYSFS_POWER if (battery->bat.dev) { if (battery->have_sysfs_alarm) device_remove_file(battery->bat.dev, &alarm_attr); power_supply_unregister(&battery->bat); } -#endif #ifdef CONFIG_ACPI_PROCFS_POWER if (battery->proc_entry) acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir); @@ -859,14 +842,12 @@ static int acpi_charger_add(struct acpi_sbs *sbs) if (result) goto end; #endif -#ifdef CONFIG_ACPI_SYSFS_POWER sbs->charger.name = "sbs-charger"; sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; sbs->charger.properties = sbs_ac_props; sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); sbs->charger.get_property = sbs_get_ac_property; power_supply_register(&sbs->device->dev, &sbs->charger); -#endif printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); @@ -876,10 +857,8 @@ static int acpi_charger_add(struct acpi_sbs *sbs) static void acpi_charger_remove(struct acpi_sbs *sbs) { -#ifdef CONFIG_ACPI_SYSFS_POWER if (sbs->charger.dev) power_supply_unregister(&sbs->charger); -#endif #ifdef CONFIG_ACPI_PROCFS_POWER if (sbs->charger_entry) acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); @@ -900,9 +879,7 @@ static void acpi_sbs_callback(void *context) ACPI_SBS_NOTIFY_STATUS, sbs->charger_present); #endif -#ifdef CONFIG_ACPI_SYSFS_POWER kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); -#endif } if (sbs->manager_present) { for (id = 0; id < MAX_SBS_BAT; ++id) { @@ -919,9 +896,7 @@ static void acpi_sbs_callback(void *context) ACPI_SBS_NOTIFY_STATUS, bat->present); #endif -#ifdef CONFIG_ACPI_SYSFS_POWER kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); -#endif } } } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b23825ecfa37..2b6c21d86b98 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -26,6 +26,8 @@ extern struct acpi_device *acpi_root; #define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent) +static const char *dummy_hid = "device"; + static LIST_HEAD(acpi_device_list); static LIST_HEAD(acpi_bus_id_list); DEFINE_MUTEX(acpi_device_lock); @@ -49,6 +51,9 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, int count; struct acpi_hardware_id *id; + if (list_empty(&acpi_dev->pnp.ids)) + return 0; + len = snprintf(modalias, size, "acpi:"); size -= len; @@ -202,13 +207,15 @@ static int acpi_device_setup_files(struct acpi_device *dev) goto end; } - result = device_create_file(&dev->dev, &dev_attr_hid); - if (result) - goto end; + if (!list_empty(&dev->pnp.ids)) { + result = device_create_file(&dev->dev, &dev_attr_hid); + if (result) + goto end; - result = device_create_file(&dev->dev, &dev_attr_modalias); - if (result) - goto end; + result = device_create_file(&dev->dev, &dev_attr_modalias); + if (result) + goto end; + } /* * If device has _EJ0, 'eject' file is created that is used to trigger @@ -316,6 +323,9 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) struct acpi_device *acpi_dev = to_acpi_device(dev); int len; + if (list_empty(&acpi_dev->pnp.ids)) + return 0; + if (add_uevent_var(env, "MODALIAS=")) return -ENOMEM; len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], @@ -1010,10 +1020,13 @@ static int acpi_dock_match(struct acpi_device *device) return acpi_get_handle(device->handle, "_DCK", &tmp); } -char *acpi_device_hid(struct acpi_device *device) +const char *acpi_device_hid(struct acpi_device *device) { struct acpi_hardware_id *hid; + if (list_empty(&device->pnp.ids)) + return dummy_hid; + hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list); return hid->id; } @@ -1142,16 +1155,6 @@ static void acpi_device_set_id(struct acpi_device *device) acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF); break; } - - /* - * We build acpi_devices for some objects that don't have _HID or _CID, - * e.g., PCI bridges and slots. Drivers can't bind to these objects, - * but we do use them indirectly by traversing the acpi_device tree. - * This generic ID isn't useful for driver binding, but it provides - * the useful property that "every acpi_device has an ID." - */ - if (list_empty(&device->pnp.ids)) - acpi_add_id(device, "device"); } static int acpi_device_set_context(struct acpi_device *device) @@ -1431,6 +1434,7 @@ EXPORT_SYMBOL(acpi_bus_add); int acpi_bus_start(struct acpi_device *device) { struct acpi_bus_ops ops; + int result; if (!device) return -EINVAL; @@ -1438,7 +1442,11 @@ int acpi_bus_start(struct acpi_device *device) memset(&ops, 0, sizeof(ops)); ops.acpi_op_start = 1; - return acpi_bus_scan(device->handle, &ops, NULL); + result = acpi_bus_scan(device->handle, &ops, NULL); + + acpi_update_gpes(); + + return result; } EXPORT_SYMBOL(acpi_bus_start); @@ -1552,6 +1560,8 @@ int __init acpi_scan_init(void) if (result) acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); + else + acpi_update_gpes(); return result; } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 4754ff6e70e6..721d93b3ceee 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -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; diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h index d8821805c3bc..74d59c8f4678 100644 --- a/drivers/acpi/sleep.h +++ b/drivers/acpi/sleep.h @@ -1,5 +1,4 @@ -extern u8 sleep_states[]; extern int acpi_suspend(u32 state); extern void acpi_enable_wakeup_devices(u8 sleep_state); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 2f8f17131d9f..5a27b0a31315 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -37,12 +37,6 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/types.h> - -#ifdef CONFIG_ACPI_PROCFS -#include <linux/proc_fs.h> -#include <linux/seq_file.h> -#endif - #include <linux/jiffies.h> #include <linux/kmod.h> #include <linux/reboot.h> @@ -195,61 +189,6 @@ struct acpi_thermal { struct mutex lock; }; -#ifdef CONFIG_ACPI_PROCFS -static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); -static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); -static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); -static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); -static ssize_t acpi_thermal_write_cooling_mode(struct file *, - const char __user *, size_t, - loff_t *); -static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file); -static ssize_t acpi_thermal_write_polling(struct file *, const char __user *, - size_t, loff_t *); - -static const struct file_operations acpi_thermal_state_fops = { - .owner = THIS_MODULE, - .open = acpi_thermal_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations acpi_thermal_temp_fops = { - .owner = THIS_MODULE, - .open = acpi_thermal_temp_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations acpi_thermal_trip_fops = { - .owner = THIS_MODULE, - .open = acpi_thermal_trip_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations acpi_thermal_cooling_fops = { - .owner = THIS_MODULE, - .open = acpi_thermal_cooling_open_fs, - .read = seq_read, - .write = acpi_thermal_write_cooling_mode, - .llseek = seq_lseek, - .release = single_release, -}; - -static const struct file_operations acpi_thermal_polling_fops = { - .owner = THIS_MODULE, - .open = acpi_thermal_polling_open_fs, - .read = seq_read, - .write = acpi_thermal_write_polling, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* CONFIG_ACPI_PROCFS*/ - /* -------------------------------------------------------------------------- Thermal Zone Management -------------------------------------------------------------------------- */ @@ -958,358 +897,6 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) /* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ -#ifdef CONFIG_ACPI_PROCFS -static struct proc_dir_entry *acpi_thermal_dir; - -static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_thermal *tz = seq->private; - - - if (!tz) - goto end; - - seq_puts(seq, "state: "); - - if (!tz->state.critical && !tz->state.hot && !tz->state.passive - && !tz->state.active) - seq_puts(seq, "ok\n"); - else { - if (tz->state.critical) - seq_puts(seq, "critical "); - if (tz->state.hot) - seq_puts(seq, "hot "); - if (tz->state.passive) - seq_puts(seq, "passive "); - if (tz->state.active) - seq_printf(seq, "active[%d]", tz->state.active_index); - seq_puts(seq, "\n"); - } - - end: - return 0; -} - -static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data); -} - -static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset) -{ - int result = 0; - struct acpi_thermal *tz = seq->private; - - - if (!tz) - goto end; - - result = acpi_thermal_get_temperature(tz); - if (result) - goto end; - - seq_printf(seq, "temperature: %ld C\n", - KELVIN_TO_CELSIUS(tz->temperature)); - - end: - return 0; -} - -static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data); -} - -static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_thermal *tz = seq->private; - struct acpi_device *device; - acpi_status status; - - int i = 0; - int j = 0; - - - if (!tz) - goto end; - - if (tz->trips.critical.flags.valid) - seq_printf(seq, "critical (S5): %ld C%s", - KELVIN_TO_CELSIUS(tz->trips.critical.temperature), - nocrt ? " <disabled>\n" : "\n"); - - if (tz->trips.hot.flags.valid) - seq_printf(seq, "hot (S4): %ld C%s", - KELVIN_TO_CELSIUS(tz->trips.hot.temperature), - nocrt ? " <disabled>\n" : "\n"); - - if (tz->trips.passive.flags.valid) { - seq_printf(seq, - "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=", - KELVIN_TO_CELSIUS(tz->trips.passive.temperature), - tz->trips.passive.tc1, tz->trips.passive.tc2, - tz->trips.passive.tsp); - for (j = 0; j < tz->trips.passive.devices.count; j++) { - status = acpi_bus_get_device(tz->trips.passive.devices. - handles[j], &device); - seq_printf(seq, "%4.4s ", status ? "" : - acpi_device_bid(device)); - } - seq_puts(seq, "\n"); - } else { - seq_printf(seq, "passive (forced):"); - if (tz->thermal_zone->forced_passive) - seq_printf(seq, " %i C\n", - tz->thermal_zone->forced_passive / 1000); - else - seq_printf(seq, "<not set>\n"); - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!(tz->trips.active[i].flags.valid)) - break; - seq_printf(seq, "active[%d]: %ld C: devices=", - i, - KELVIN_TO_CELSIUS(tz->trips.active[i].temperature)); - for (j = 0; j < tz->trips.active[i].devices.count; j++){ - status = acpi_bus_get_device(tz->trips.active[i]. - devices.handles[j], - &device); - seq_printf(seq, "%4.4s ", status ? "" : - acpi_device_bid(device)); - } - seq_puts(seq, "\n"); - } - - end: - return 0; -} - -static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data); -} - -static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_thermal *tz = seq->private; - - - if (!tz) - goto end; - - if (!tz->flags.cooling_mode) - seq_puts(seq, "<setting not supported>\n"); - else - seq_puts(seq, "0 - Active; 1 - Passive\n"); - - end: - return 0; -} - -static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_thermal_cooling_seq_show, - PDE(inode)->data); -} - -static ssize_t -acpi_thermal_write_cooling_mode(struct file *file, - const char __user * buffer, - size_t count, loff_t * ppos) -{ - struct seq_file *m = file->private_data; - struct acpi_thermal *tz = m->private; - int result = 0; - char mode_string[12] = { '\0' }; - - - if (!tz || (count > sizeof(mode_string) - 1)) - return -EINVAL; - - if (!tz->flags.cooling_mode) - return -ENODEV; - - if (copy_from_user(mode_string, buffer, count)) - return -EFAULT; - - mode_string[count] = '\0'; - - result = acpi_thermal_set_cooling_mode(tz, - simple_strtoul(mode_string, NULL, - 0)); - if (result) - return result; - - acpi_thermal_check(tz); - - return count; -} - -static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_thermal *tz = seq->private; - - - if (!tz) - goto end; - - if (!tz->thermal_zone->polling_delay) { - seq_puts(seq, "<polling disabled>\n"); - goto end; - } - - seq_printf(seq, "polling frequency: %d seconds\n", - (tz->thermal_zone->polling_delay / 1000)); - - end: - return 0; -} - -static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_thermal_polling_seq_show, - PDE(inode)->data); -} - -static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds) -{ - if (!tz) - return -EINVAL; - - /* Convert value to deci-seconds */ - tz->polling_frequency = seconds * 10; - - tz->thermal_zone->polling_delay = seconds * 1000; - - if (tz->tz_enabled) - thermal_zone_device_update(tz->thermal_zone); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Polling frequency set to %lu seconds\n", - tz->polling_frequency/10)); - - return 0; -} - -static ssize_t -acpi_thermal_write_polling(struct file *file, - const char __user * buffer, - size_t count, loff_t * ppos) -{ - struct seq_file *m = file->private_data; - struct acpi_thermal *tz = m->private; - int result = 0; - char polling_string[12] = { '\0' }; - int seconds = 0; - - - if (!tz || (count > sizeof(polling_string) - 1)) - return -EINVAL; - - if (copy_from_user(polling_string, buffer, count)) - return -EFAULT; - - polling_string[count] = '\0'; - - seconds = simple_strtoul(polling_string, NULL, 0); - - result = acpi_thermal_set_polling(tz, seconds); - if (result) - return result; - - acpi_thermal_check(tz); - - return count; -} - -static int acpi_thermal_add_fs(struct acpi_device *device) -{ - struct proc_dir_entry *entry = NULL; - - - if (!acpi_device_dir(device)) { - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), - acpi_thermal_dir); - if (!acpi_device_dir(device)) - return -ENODEV; - } - - /* 'state' [R] */ - entry = proc_create_data(ACPI_THERMAL_FILE_STATE, - S_IRUGO, acpi_device_dir(device), - &acpi_thermal_state_fops, - acpi_driver_data(device)); - if (!entry) - return -ENODEV; - - /* 'temperature' [R] */ - entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE, - S_IRUGO, acpi_device_dir(device), - &acpi_thermal_temp_fops, - acpi_driver_data(device)); - if (!entry) - return -ENODEV; - - /* 'trip_points' [R] */ - entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS, - S_IRUGO, - acpi_device_dir(device), - &acpi_thermal_trip_fops, - acpi_driver_data(device)); - if (!entry) - return -ENODEV; - - /* 'cooling_mode' [R/W] */ - entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE, - S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device), - &acpi_thermal_cooling_fops, - acpi_driver_data(device)); - if (!entry) - return -ENODEV; - - /* 'polling_frequency' [R/W] */ - entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ, - S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device), - &acpi_thermal_polling_fops, - acpi_driver_data(device)); - if (!entry) - return -ENODEV; - return 0; -} - -static int acpi_thermal_remove_fs(struct acpi_device *device) -{ - - if (acpi_device_dir(device)) { - remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ, - acpi_device_dir(device)); - remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE, - acpi_device_dir(device)); - remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS, - acpi_device_dir(device)); - remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE, - acpi_device_dir(device)); - remove_proc_entry(ACPI_THERMAL_FILE_STATE, - acpi_device_dir(device)); - remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir); - acpi_device_dir(device) = NULL; - } - - return 0; -} -#else -static inline int acpi_thermal_add_fs(struct acpi_device *device) { return 0; } -static inline int acpi_thermal_remove_fs(struct acpi_device *device) -{ - return 0; -} -#endif /* CONFIG_ACPI_PROCFS */ -/* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -1428,17 +1015,11 @@ static int acpi_thermal_add(struct acpi_device *device) if (result) goto free_memory; - result = acpi_thermal_add_fs(device); - if (result) - goto unregister_thermal_zone; - printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature)); goto end; -unregister_thermal_zone: - thermal_zone_device_unregister(tz->thermal_zone); free_memory: kfree(tz); end: @@ -1454,7 +1035,6 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) tz = acpi_driver_data(device); - acpi_thermal_remove_fs(device); acpi_thermal_unregister_thermal_zone(tz); mutex_destroy(&tz->lock); kfree(tz); @@ -1580,19 +1160,9 @@ static int __init acpi_thermal_init(void) return -ENODEV; } -#ifdef CONFIG_ACPI_PROCFS - acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); - if (!acpi_thermal_dir) - return -ENODEV; -#endif - result = acpi_bus_register_driver(&acpi_thermal_driver); - if (result < 0) { -#ifdef CONFIG_ACPI_PROCFS - remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); -#endif + if (result < 0) return -ENODEV; - } return 0; } @@ -1602,10 +1172,6 @@ static void __exit acpi_thermal_exit(void) acpi_bus_unregister_driver(&acpi_thermal_driver); -#ifdef CONFIG_ACPI_PROCFS - remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); -#endif - return; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 67dec0c675aa..5cd0228d2daa 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -30,8 +30,6 @@ #include <linux/types.h> #include <linux/list.h> #include <linux/mutex.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> #include <linux/input.h> #include <linux/backlight.h> #include <linux/thermal.h> @@ -152,9 +150,6 @@ struct acpi_video_bus { struct acpi_video_bus_flags flags; struct list_head video_device_list; struct mutex device_list_lock; /* protects video_device_list */ -#ifdef CONFIG_ACPI_PROCFS - struct proc_dir_entry *dir; -#endif struct input_dev *input; char phys[32]; /* for input device */ struct notifier_block pm_nb; @@ -210,108 +205,6 @@ struct acpi_video_device { struct output_device *output_dev; }; -#ifdef CONFIG_ACPI_PROCFS -/* bus */ -static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file); -static const struct file_operations acpi_video_bus_info_fops = { - .owner = THIS_MODULE, - .open = acpi_video_bus_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file); -static const struct file_operations acpi_video_bus_ROM_fops = { - .owner = THIS_MODULE, - .open = acpi_video_bus_ROM_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_video_bus_POST_info_open_fs(struct inode *inode, - struct file *file); -static const struct file_operations acpi_video_bus_POST_info_fops = { - .owner = THIS_MODULE, - .open = acpi_video_bus_POST_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file); -static ssize_t acpi_video_bus_write_POST(struct file *file, - const char __user *buffer, size_t count, loff_t *data); -static const struct file_operations acpi_video_bus_POST_fops = { - .owner = THIS_MODULE, - .open = acpi_video_bus_POST_open_fs, - .read = seq_read, - .write = acpi_video_bus_write_POST, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file); -static ssize_t acpi_video_bus_write_DOS(struct file *file, - const char __user *buffer, size_t count, loff_t *data); -static const struct file_operations acpi_video_bus_DOS_fops = { - .owner = THIS_MODULE, - .open = acpi_video_bus_DOS_open_fs, - .read = seq_read, - .write = acpi_video_bus_write_DOS, - .llseek = seq_lseek, - .release = single_release, -}; - -/* device */ -static int acpi_video_device_info_open_fs(struct inode *inode, - struct file *file); -static const struct file_operations acpi_video_device_info_fops = { - .owner = THIS_MODULE, - .open = acpi_video_device_info_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_video_device_state_open_fs(struct inode *inode, - struct file *file); -static ssize_t acpi_video_device_write_state(struct file *file, - const char __user *buffer, size_t count, loff_t *data); -static const struct file_operations acpi_video_device_state_fops = { - .owner = THIS_MODULE, - .open = acpi_video_device_state_open_fs, - .read = seq_read, - .write = acpi_video_device_write_state, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_video_device_brightness_open_fs(struct inode *inode, - struct file *file); -static ssize_t acpi_video_device_write_brightness(struct file *file, - const char __user *buffer, size_t count, loff_t *data); -static const struct file_operations acpi_video_device_brightness_fops = { - .owner = THIS_MODULE, - .open = acpi_video_device_brightness_open_fs, - .read = seq_read, - .write = acpi_video_device_write_brightness, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_video_device_EDID_open_fs(struct inode *inode, - struct file *file); -static const struct file_operations acpi_video_device_EDID_fops = { - .owner = THIS_MODULE, - .open = acpi_video_device_EDID_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* CONFIG_ACPI_PROCFS */ - static const char device_decode[][30] = { "motherboard VGA device", "PCI VGA device", @@ -1111,646 +1004,6 @@ static int acpi_video_bus_check(struct acpi_video_bus *video) } /* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ -#ifdef CONFIG_ACPI_PROCFS - -static struct proc_dir_entry *acpi_video_dir; - -/* video devices */ - -static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_video_device *dev = seq->private; - - - if (!dev) - goto end; - - seq_printf(seq, "device_id: 0x%04x\n", (u32) dev->device_id); - seq_printf(seq, "type: "); - if (dev->flags.crt) - seq_printf(seq, "CRT\n"); - else if (dev->flags.lcd) - seq_printf(seq, "LCD\n"); - else if (dev->flags.tvout) - seq_printf(seq, "TVOUT\n"); - else if (dev->flags.dvi) - seq_printf(seq, "DVI\n"); - else - seq_printf(seq, "UNKNOWN\n"); - - seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no"); - - end: - return 0; -} - -static int -acpi_video_device_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_video_device_info_seq_show, - PDE(inode)->data); -} - -static int -acpi_video_device_query(struct acpi_video_device *device, - unsigned long long *state) -{ - int status; - - status = acpi_evaluate_integer(device->dev->handle, "_DGS", - NULL, state); - - return status; -} - -static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset) -{ - int status; - struct acpi_video_device *dev = seq->private; - unsigned long long state; - - - if (!dev) - goto end; - - status = acpi_video_device_get_state(dev, &state); - seq_printf(seq, "state: "); - if (ACPI_SUCCESS(status)) - seq_printf(seq, "0x%02llx\n", state); - else - seq_printf(seq, "<not supported>\n"); - - status = acpi_video_device_query(dev, &state); - seq_printf(seq, "query: "); - if (ACPI_SUCCESS(status)) - seq_printf(seq, "0x%02llx\n", state); - else - seq_printf(seq, "<not supported>\n"); - - end: - return 0; -} - -static int -acpi_video_device_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_video_device_state_seq_show, - PDE(inode)->data); -} - -static ssize_t -acpi_video_device_write_state(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - int status; - struct seq_file *m = file->private_data; - struct acpi_video_device *dev = m->private; - char str[12] = { 0 }; - u32 state = 0; - - - if (!dev || count >= sizeof(str)) - return -EINVAL; - - if (copy_from_user(str, buffer, count)) - return -EFAULT; - - str[count] = 0; - state = simple_strtoul(str, NULL, 0); - state &= ((1ul << 31) | (1ul << 30) | (1ul << 0)); - - status = acpi_video_device_set_state(dev, state); - - if (status) - return -EFAULT; - - return count; -} - -static int -acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_video_device *dev = seq->private; - int i; - - - if (!dev || !dev->brightness) { - seq_printf(seq, "<not supported>\n"); - return 0; - } - - seq_printf(seq, "levels: "); - for (i = 2; i < dev->brightness->count; i++) - seq_printf(seq, " %d", dev->brightness->levels[i]); - seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr); - - return 0; -} - -static int -acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_video_device_brightness_seq_show, - PDE(inode)->data); -} - -static ssize_t -acpi_video_device_write_brightness(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - struct seq_file *m = file->private_data; - struct acpi_video_device *dev = m->private; - char str[5] = { 0 }; - unsigned int level = 0; - int i; - - - if (!dev || !dev->brightness || count >= sizeof(str)) - return -EINVAL; - - if (copy_from_user(str, buffer, count)) - return -EFAULT; - - str[count] = 0; - level = simple_strtoul(str, NULL, 0); - - if (level > 100) - return -EFAULT; - - /* validate through the list of available levels */ - for (i = 2; i < dev->brightness->count; i++) - if (level == dev->brightness->levels[i]) { - if (!acpi_video_device_lcd_set_level(dev, level)) - return count; - break; - } - - return -EINVAL; -} - -static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_video_device *dev = seq->private; - int status; - int i; - union acpi_object *edid = NULL; - - - if (!dev) - goto out; - - status = acpi_video_device_EDID(dev, &edid, 128); - if (ACPI_FAILURE(status)) { - status = acpi_video_device_EDID(dev, &edid, 256); - } - - if (ACPI_FAILURE(status)) { - goto out; - } - - if (edid && edid->type == ACPI_TYPE_BUFFER) { - for (i = 0; i < edid->buffer.length; i++) - seq_putc(seq, edid->buffer.pointer[i]); - } - - out: - if (!edid) - seq_printf(seq, "<not supported>\n"); - else - kfree(edid); - - return 0; -} - -static int -acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_video_device_EDID_seq_show, - PDE(inode)->data); -} - -static int acpi_video_device_add_fs(struct acpi_device *device) -{ - struct proc_dir_entry *entry, *device_dir; - struct acpi_video_device *vid_dev; - - vid_dev = acpi_driver_data(device); - if (!vid_dev) - return -ENODEV; - - device_dir = proc_mkdir(acpi_device_bid(device), - vid_dev->video->dir); - if (!device_dir) - return -ENOMEM; - - /* 'info' [R] */ - entry = proc_create_data("info", S_IRUGO, device_dir, - &acpi_video_device_info_fops, acpi_driver_data(device)); - if (!entry) - goto err_remove_dir; - - /* 'state' [R/W] */ - entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR, - device_dir, - &acpi_video_device_state_fops, - acpi_driver_data(device)); - if (!entry) - goto err_remove_info; - - /* 'brightness' [R/W] */ - entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR, - device_dir, - &acpi_video_device_brightness_fops, - acpi_driver_data(device)); - if (!entry) - goto err_remove_state; - - /* 'EDID' [R] */ - entry = proc_create_data("EDID", S_IRUGO, device_dir, - &acpi_video_device_EDID_fops, - acpi_driver_data(device)); - if (!entry) - goto err_remove_brightness; - - acpi_device_dir(device) = device_dir; - - return 0; - - err_remove_brightness: - remove_proc_entry("brightness", device_dir); - err_remove_state: - remove_proc_entry("state", device_dir); - err_remove_info: - remove_proc_entry("info", device_dir); - err_remove_dir: - remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); - return -ENOMEM; -} - -static int acpi_video_device_remove_fs(struct acpi_device *device) -{ - struct acpi_video_device *vid_dev; - struct proc_dir_entry *device_dir; - - vid_dev = acpi_driver_data(device); - if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) - return -ENODEV; - - device_dir = acpi_device_dir(device); - if (device_dir) { - remove_proc_entry("info", device_dir); - remove_proc_entry("state", device_dir); - remove_proc_entry("brightness", device_dir); - remove_proc_entry("EDID", device_dir); - remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); - acpi_device_dir(device) = NULL; - } - - return 0; -} - -/* video bus */ -static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_video_bus *video = seq->private; - - - if (!video) - goto end; - - seq_printf(seq, "Switching heads: %s\n", - video->flags.multihead ? "yes" : "no"); - seq_printf(seq, "Video ROM: %s\n", - video->flags.rom ? "yes" : "no"); - seq_printf(seq, "Device to be POSTed on boot: %s\n", - video->flags.post ? "yes" : "no"); - - end: - return 0; -} - -static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_video_bus_info_seq_show, - PDE(inode)->data); -} - -static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_video_bus *video = seq->private; - - - if (!video) - goto end; - - printk(KERN_INFO PREFIX "Please implement %s\n", __func__); - seq_printf(seq, "<TODO>\n"); - - end: - return 0; -} - -static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data); -} - -static int -acpi_video_bus_POST_options(struct acpi_video_bus *video, - unsigned long long *options) -{ - int status; - - status = acpi_evaluate_integer(video->device->handle, "_VPO", - NULL, options); - *options &= 3; - - return status; -} - -static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_video_bus *video = seq->private; - unsigned long long options; - int status; - - - if (!video) - goto end; - - status = acpi_video_bus_POST_options(video, &options); - if (ACPI_SUCCESS(status)) { - if (!(options & 1)) { - printk(KERN_WARNING PREFIX - "The motherboard VGA device is not listed as a possible POST device.\n"); - printk(KERN_WARNING PREFIX - "This indicates a BIOS bug. Please contact the manufacturer.\n"); - } - printk(KERN_WARNING "%llx\n", options); - seq_printf(seq, "can POST: <integrated video>"); - if (options & 2) - seq_printf(seq, " <PCI video>"); - if (options & 4) - seq_printf(seq, " <AGP video>"); - seq_putc(seq, '\n'); - } else - seq_printf(seq, "<not supported>\n"); - end: - return 0; -} - -static int -acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_video_bus_POST_info_seq_show, - PDE(inode)->data); -} - -static int -acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id) -{ - int status; - - status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id); - - return status; -} - -static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_video_bus *video = seq->private; - int status; - unsigned long long id; - - - if (!video) - goto end; - - status = acpi_video_bus_get_POST(video, &id); - if (!ACPI_SUCCESS(status)) { - seq_printf(seq, "<not supported>\n"); - goto end; - } - seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]); - - end: - return 0; -} - -static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_video_bus *video = seq->private; - - - seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting); - - return 0; -} - -static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_video_bus_POST_seq_show, - PDE(inode)->data); -} - -static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data); -} - -static int -acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option) -{ - int status; - unsigned long long tmp; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; - - - arg0.integer.value = option; - - status = acpi_evaluate_integer(video->device->handle, "_SPD", - &args, &tmp); - if (ACPI_SUCCESS(status)) - status = tmp ? (-EINVAL) : (AE_OK); - - return status; -} - -static ssize_t -acpi_video_bus_write_POST(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - int status; - struct seq_file *m = file->private_data; - struct acpi_video_bus *video = m->private; - char str[12] = { 0 }; - unsigned long long opt, options; - - - if (!video || count >= sizeof(str)) - return -EINVAL; - - status = acpi_video_bus_POST_options(video, &options); - if (!ACPI_SUCCESS(status)) - return -EINVAL; - - if (copy_from_user(str, buffer, count)) - return -EFAULT; - - str[count] = 0; - opt = strtoul(str, NULL, 0); - if (opt > 3) - return -EFAULT; - - /* just in case an OEM 'forgot' the motherboard... */ - options |= 1; - - if (options & (1ul << opt)) { - status = acpi_video_bus_set_POST(video, opt); - if (!ACPI_SUCCESS(status)) - return -EFAULT; - - } - - return count; -} - -static ssize_t -acpi_video_bus_write_DOS(struct file *file, - const char __user * buffer, - size_t count, loff_t * data) -{ - int status; - struct seq_file *m = file->private_data; - struct acpi_video_bus *video = m->private; - char str[12] = { 0 }; - unsigned long opt; - - - if (!video || count >= sizeof(str)) - return -EINVAL; - - if (copy_from_user(str, buffer, count)) - return -EFAULT; - - str[count] = 0; - opt = strtoul(str, NULL, 0); - if (opt > 7) - return -EFAULT; - - status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2); - - if (!ACPI_SUCCESS(status)) - return -EFAULT; - - return count; -} - -static int acpi_video_bus_add_fs(struct acpi_device *device) -{ - struct acpi_video_bus *video = acpi_driver_data(device); - struct proc_dir_entry *device_dir; - struct proc_dir_entry *entry; - - device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir); - if (!device_dir) - return -ENOMEM; - - /* 'info' [R] */ - entry = proc_create_data("info", S_IRUGO, device_dir, - &acpi_video_bus_info_fops, - acpi_driver_data(device)); - if (!entry) - goto err_remove_dir; - - /* 'ROM' [R] */ - entry = proc_create_data("ROM", S_IRUGO, device_dir, - &acpi_video_bus_ROM_fops, - acpi_driver_data(device)); - if (!entry) - goto err_remove_info; - - /* 'POST_info' [R] */ - entry = proc_create_data("POST_info", S_IRUGO, device_dir, - &acpi_video_bus_POST_info_fops, - acpi_driver_data(device)); - if (!entry) - goto err_remove_rom; - - /* 'POST' [R/W] */ - entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR, - device_dir, - &acpi_video_bus_POST_fops, - acpi_driver_data(device)); - if (!entry) - goto err_remove_post_info; - - /* 'DOS' [R/W] */ - entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR, - device_dir, - &acpi_video_bus_DOS_fops, - acpi_driver_data(device)); - if (!entry) - goto err_remove_post; - - video->dir = acpi_device_dir(device) = device_dir; - return 0; - - err_remove_post: - remove_proc_entry("POST", device_dir); - err_remove_post_info: - remove_proc_entry("POST_info", device_dir); - err_remove_rom: - remove_proc_entry("ROM", device_dir); - err_remove_info: - remove_proc_entry("info", device_dir); - err_remove_dir: - remove_proc_entry(acpi_device_bid(device), acpi_video_dir); - return -ENOMEM; -} - -static int acpi_video_bus_remove_fs(struct acpi_device *device) -{ - struct proc_dir_entry *device_dir = acpi_device_dir(device); - - if (device_dir) { - remove_proc_entry("info", device_dir); - remove_proc_entry("ROM", device_dir); - remove_proc_entry("POST_info", device_dir); - remove_proc_entry("POST", device_dir); - remove_proc_entry("DOS", device_dir); - remove_proc_entry(acpi_device_bid(device), acpi_video_dir); - acpi_device_dir(device) = NULL; - } - - return 0; -} -#else -static inline int acpi_video_device_add_fs(struct acpi_device *device) -{ - return 0; -} -static inline int acpi_video_device_remove_fs(struct acpi_device *device) -{ - return 0; -} -static inline int acpi_video_bus_add_fs(struct acpi_device *device) -{ - return 0; -} -static inline int acpi_video_bus_remove_fs(struct acpi_device *device) -{ - return 0; -} -#endif /* CONFIG_ACPI_PROCFS */ - -/* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -1877,8 +1130,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device, list_add_tail(&data->entry, &video->video_device_list); mutex_unlock(&video->device_list_lock); - acpi_video_device_add_fs(device); - return 0; } @@ -2181,8 +1432,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) if (!device || !device->video) return -ENOENT; - acpi_video_device_remove_fs(device->dev); - status = acpi_remove_notify_handler(device->dev->handle, ACPI_DEVICE_NOTIFY, acpi_video_device_notify); @@ -2466,10 +1715,6 @@ static int acpi_video_bus_add(struct acpi_device *device) if (error) goto err_free_video; - error = acpi_video_bus_add_fs(device); - if (error) - goto err_free_video; - mutex_init(&video->device_list_lock); INIT_LIST_HEAD(&video->video_device_list); @@ -2522,7 +1767,6 @@ static int acpi_video_bus_add(struct acpi_device *device) acpi_video_bus_stop_devices(video); acpi_video_bus_put_devices(video); kfree(video->attached_array); - acpi_video_bus_remove_fs(device); err_free_video: kfree(video); device->driver_data = NULL; @@ -2544,7 +1788,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) acpi_video_bus_stop_devices(video); acpi_video_bus_put_devices(video); - acpi_video_bus_remove_fs(device); input_unregister_device(video->input); kfree(video->attached_array); @@ -2584,17 +1827,9 @@ int acpi_video_register(void) return 0; } -#ifdef CONFIG_ACPI_PROCFS - acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); - if (!acpi_video_dir) - return -ENODEV; -#endif - result = acpi_bus_register_driver(&acpi_video_bus); - if (result < 0) { - remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); + if (result < 0) return -ENODEV; - } /* * When the acpi_video_bus is loaded successfully, increase @@ -2617,10 +1852,6 @@ void acpi_video_unregister(void) } acpi_bus_unregister_driver(&acpi_video_bus); -#ifdef CONFIG_ACPI_PROCFS - remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir); -#endif - register_count = 0; return; |