diff options
Diffstat (limited to 'drivers/acpi/events/evregion.c')
-rw-r--r-- | drivers/acpi/events/evregion.c | 278 |
1 files changed, 60 insertions, 218 deletions
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index d544b1bbc..53cae6392 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c @@ -1,7 +1,7 @@ /****************************************************************************** * - * Module Name: evregion - ACPI Address_space / Op_region handler dispatch - * $Revision: 76 $ + * Module Name: evregion - ACPI Address_space (Op_region) handler dispatch + * $Revision: 93 $ * *****************************************************************************/ @@ -34,202 +34,6 @@ MODULE_NAME ("evregion") -#define PCI_ROOT_HID_STRING "PNP0A03" -#define PCI_ROOT_HID_VALUE 0x030AD041 /* EISAID("PNP0A03") */ - - -/****************************************************************************** - * - * FUNCTION: Acpi_ev_find_one_pci_root_bus - * - * PARAMETERS: - * - * RETURN: None - * - * DESCRIPTION: - * - *****************************************************************************/ - -ACPI_STATUS -acpi_ev_find_one_pci_root_bus ( - ACPI_HANDLE obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - ACPI_NAMESPACE_NODE *node; - ACPI_OPERAND_OBJECT *obj_desc; - ACPI_STATUS status; - - - node = (ACPI_NAMESPACE_NODE *) obj_handle; - obj_desc = ((ACPI_NAMESPACE_NODE *) obj_handle)->object; - - - /* - * We are looking for all valid _HID objects. - */ - - if (STRNCMP ((NATIVE_CHAR *) &node->name, METHOD_NAME__HID, ACPI_NAME_SIZE) || - (!obj_desc)) - { - return (AE_OK); - } - - - /* - * Found an _HID object. - * Now we need a HID with the value EISAID("PNP0A03") - * HID can be either a number or a string. - */ - - switch (obj_desc->common.type) - { - case ACPI_TYPE_NUMBER: - - if (obj_desc->number.value != PCI_ROOT_HID_VALUE) { - return (AE_OK); - } - - break; - - case ACPI_TYPE_STRING: - - if (STRNCMP (obj_desc->string.pointer, PCI_ROOT_HID_STRING, - sizeof (PCI_ROOT_HID_STRING))) - { - return (AE_OK); - } - - break; - - default: - - return (AE_OK); - } - - - /* - * We found a valid PCI_ROOT_HID. - * The parent of the HID entry is the PCI device; Install the default PCI - * handler for this PCI device. - */ - - status = acpi_install_address_space_handler (acpi_ns_get_parent_object (node), - ADDRESS_SPACE_PCI_CONFIG, - ACPI_DEFAULT_HANDLER, NULL, NULL); - - return (AE_OK); -} - - -/****************************************************************************** - * - * FUNCTION: Acpi_ev_find_pci_root_buses - * - * PARAMETERS: - * - * RETURN: None - * - * DESCRIPTION: - * - *****************************************************************************/ - -ACPI_STATUS -acpi_ev_find_pci_root_buses ( - void) -{ - - acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - FALSE, acpi_ev_find_one_pci_root_bus, NULL, NULL); - - return (AE_OK); -} - -/****************************************************************************** - * - * FUNCTION: Acpi_ev_init_one_device - * - * PARAMETERS: The usual "I'm a namespace callback" stuff - * - * RETURN: ACPI_STATUS - * - * DESCRIPTION: This is called once per device soon after ACPI is enabled - * to initialize each device. It determines if the device is - * present, and if so, calls _INI. - * - *****************************************************************************/ - -ACPI_STATUS -acpi_ev_init_one_device ( - ACPI_HANDLE obj_handle, - u32 nesting_level, - void *context, - void **return_value) -{ - ACPI_STATUS status; - ACPI_OPERAND_OBJECT *ret_obj; - - - /* - * Run _STA to determine if we can run _INI on the device. - */ - status = acpi_ns_evaluate_relative(obj_handle, "_STA", NULL, &ret_obj); - if (AE_NOT_FOUND == status) { - /* No _STA means device is present */ - } - else if (ACPI_FAILURE (status)) { - return (status); - } - else if (ret_obj) { - if (ACPI_TYPE_NUMBER != ret_obj->common.type) { - status = AE_AML_OPERAND_TYPE; - goto cleanup; - } - - /* - * if _STA "present" bit not set, we're done. - */ - if (!(ret_obj->number.value & 1)) { - goto cleanup; - } - } - - /* - * The device is present. Run _INI. - */ - - status = acpi_ns_evaluate_relative(obj_handle, "_INI", NULL, NULL); - -cleanup: - - acpi_cm_remove_reference (ret_obj); - return (status); -} - -/****************************************************************************** - * - * FUNCTION: Acpi_ev_init_devices - * - * PARAMETERS: None - * - * RETURN: ACPI_STATUS - * - * DESCRIPTION: This initializes all ACPI devices. - * - *****************************************************************************/ - -ACPI_STATUS -acpi_ev_init_devices ( - void) -{ - acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - FALSE, acpi_ev_init_one_device, NULL, NULL); - - return (AE_OK); -} - - /************************************************************************** * * FUNCTION: Acpi_ev_install_default_address_space_handlers @@ -250,23 +54,45 @@ acpi_ev_install_default_address_space_handlers ( /* - * NOTE: All address spaces (PCI Config, EC, SMBus) are scope dependent - * and registration must occur for a specific device. In the case - * system memory and IO address spaces there is currently no device - * associated with the address space. For these we use the root. + * All address spaces (PCI Config, EC, SMBus) are scope dependent + * and registration must occur for a specific device. In the case + * system memory and IO address spaces there is currently no device + * associated with the address space. For these we use the root. + * We install the default PCI config space handler at the root so + * that this space is immediately available even though the we have + * not enumerated all the PCI Root Buses yet. This is to conform + * to the ACPI specification which states that the PCI config + * space must be always available -- even though we are nowhere + * near ready to find the PCI root buses at this point. + * + * NOTE: We ignore AE_EXIST because this means that a handler has + * already been installed (via Acpi_install_address_space_handler) */ status = acpi_install_address_space_handler (acpi_gbl_root_node, ADDRESS_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL); - if (ACPI_FAILURE (status)) { + if ((ACPI_FAILURE (status)) && + (status != AE_EXIST)) + { return (status); } status = acpi_install_address_space_handler (acpi_gbl_root_node, ADDRESS_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL); - if (ACPI_FAILURE (status)) { + if ((ACPI_FAILURE (status)) && + (status != AE_EXIST)) + { + return (status); + } + + status = acpi_install_address_space_handler (acpi_gbl_root_node, + ADDRESS_SPACE_PCI_CONFIG, + ACPI_DEFAULT_HANDLER, NULL, NULL); + if ((ACPI_FAILURE (status)) && + (status != AE_EXIST)) + { return (status); } @@ -275,7 +101,7 @@ acpi_ev_install_default_address_space_handlers ( } -/* TBD: [Restructure] Move to the methods directory */ +/* TBD: [Restructure] Move elsewhere */ /************************************************************************** * @@ -290,7 +116,7 @@ acpi_ev_install_default_address_space_handlers ( * *************************************************************************/ -ACPI_STATUS +static ACPI_STATUS acpi_ev_execute_reg_method ( ACPI_OPERAND_OBJECT *region_obj, u32 function) @@ -301,7 +127,7 @@ acpi_ev_execute_reg_method ( ACPI_STATUS status; - if (region_obj->region.REGmethod == NULL) { + if (region_obj->region.extra->extra.method_REG == NULL) { return (AE_OK); } @@ -337,7 +163,7 @@ acpi_ev_execute_reg_method ( /* * Execute the method, no return value */ - status = acpi_ns_evaluate_by_handle (region_obj->region.REGmethod, params, NULL); + status = acpi_ns_evaluate_by_handle (region_obj->region.extra->extra.method_REG, params, NULL); return (status); } @@ -364,7 +190,7 @@ ACPI_STATUS acpi_ev_address_space_dispatch ( ACPI_OPERAND_OBJECT *region_obj, u32 function, - u32 address, + ACPI_PHYSICAL_ADDRESS address, u32 bit_width, u32 *value) { @@ -381,7 +207,7 @@ acpi_ev_address_space_dispatch ( handler_desc = region_obj->region.addr_handler; if (!handler_desc) { - return(AE_EXIST); + return(AE_NOT_EXIST); } /* @@ -421,11 +247,13 @@ acpi_ev_address_space_dispatch ( return(status); } + region_obj->region.flags |= AOPOBJ_INITIALIZED; + /* * Save the returned context for use in all accesses to * this particular region. */ - region_obj->region.region_context = region_context; + region_obj->region.extra->extra.region_context = region_context; } /* @@ -447,7 +275,7 @@ acpi_ev_address_space_dispatch ( */ status = handler (function, address, bit_width, value, handler_desc->addr_handler.context, - region_obj->region.region_context); + region_obj->region.extra->extra.region_context); if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) { @@ -462,10 +290,10 @@ acpi_ev_address_space_dispatch ( /****************************************************************************** * - * FUNCTION: Acpi_ev_disassociate_region_and_handler + * FUNCTION: Acpi_ev_disassociate_region_from_handler * - * PARAMETERS: Handler_obj - Handler Object - * Region_obj - Region Object + * PARAMETERS: Region_obj - Region Object + * Acpi_ns_is_locked - Namespace Region Already Locked? * * RETURN: None * @@ -476,16 +304,19 @@ acpi_ev_address_space_dispatch ( void acpi_ev_disassociate_region_from_handler( - ACPI_OPERAND_OBJECT *region_obj) + ACPI_OPERAND_OBJECT *region_obj, + u8 acpi_ns_is_locked) { ACPI_OPERAND_OBJECT *handler_obj; ACPI_OPERAND_OBJECT *obj_desc; ACPI_OPERAND_OBJECT **last_obj_ptr; ADDRESS_SPACE_SETUP region_setup; - void *region_context = region_obj->region.region_context; + void *region_context; ACPI_STATUS status; + region_context = region_obj->region.extra->extra.region_context; + /* * Get the address handler from the region object */ @@ -517,11 +348,19 @@ acpi_ev_disassociate_region_from_handler( *last_obj_ptr = obj_desc->region.next; obj_desc->region.next = NULL; /* Must clear field */ + if (acpi_ns_is_locked) { + acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); + } + /* * Now stop region accesses by executing the _REG method */ acpi_ev_execute_reg_method (region_obj, 0); + if (acpi_ns_is_locked) { + acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE); + } + /* * Call the setup handler with the deactivate notification */ @@ -534,6 +373,8 @@ acpi_ev_disassociate_region_from_handler( * Init routine may fail, Just ignore errors */ + region_obj->region.flags &= ~(AOPOBJ_INITIALIZED); + /* * Remove handler reference in the region * @@ -572,6 +413,7 @@ acpi_ev_disassociate_region_from_handler( * * PARAMETERS: Handler_obj - Handler Object * Region_obj - Region Object + * Acpi_ns_is_locked - Namespace Region Already Locked? * * RETURN: None * @@ -757,7 +599,7 @@ acpi_ev_addr_handler_helper ( * * First disconnect region for any previous handler (if any) */ - acpi_ev_disassociate_region_from_handler (obj_desc); + acpi_ev_disassociate_region_from_handler (obj_desc, FALSE); /* * Then connect the region to the new handler |