Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
0005  *                         Address Spaces.
0006  *
0007  * Copyright (C) 2000 - 2022, Intel Corp.
0008  *
0009  *****************************************************************************/
0010 
0011 #define EXPORT_ACPI_INTERFACES
0012 
0013 #include <acpi/acpi.h>
0014 #include "accommon.h"
0015 #include "acnamesp.h"
0016 #include "acevents.h"
0017 
0018 #define _COMPONENT          ACPI_EVENTS
0019 ACPI_MODULE_NAME("evxfregn")
0020 
0021 /*******************************************************************************
0022  *
0023  * FUNCTION:    acpi_install_address_space_handler
0024  *
0025  * PARAMETERS:  device          - Handle for the device
0026  *              space_id        - The address space ID
0027  *              handler         - Address of the handler
0028  *              setup           - Address of the setup function
0029  *              context         - Value passed to the handler on each access
0030  *
0031  * RETURN:      Status
0032  *
0033  * DESCRIPTION: Install a handler for all op_regions of a given space_id.
0034  *
0035  * NOTE: This function should only be called after acpi_enable_subsystem has
0036  * been called. This is because any _REG methods associated with the Space ID
0037  * are executed here, and these methods can only be safely executed after
0038  * the default handlers have been installed and the hardware has been
0039  * initialized (via acpi_enable_subsystem.)
0040  *
0041  ******************************************************************************/
0042 acpi_status
0043 acpi_install_address_space_handler(acpi_handle device,
0044                    acpi_adr_space_type space_id,
0045                    acpi_adr_space_handler handler,
0046                    acpi_adr_space_setup setup, void *context)
0047 {
0048     struct acpi_namespace_node *node;
0049     acpi_status status;
0050 
0051     ACPI_FUNCTION_TRACE(acpi_install_address_space_handler);
0052 
0053     /* Parameter validation */
0054 
0055     if (!device) {
0056         return_ACPI_STATUS(AE_BAD_PARAMETER);
0057     }
0058 
0059     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0060     if (ACPI_FAILURE(status)) {
0061         return_ACPI_STATUS(status);
0062     }
0063 
0064     /* Convert and validate the device handle */
0065 
0066     node = acpi_ns_validate_handle(device);
0067     if (!node) {
0068         status = AE_BAD_PARAMETER;
0069         goto unlock_and_exit;
0070     }
0071 
0072     /* Install the handler for all Regions for this Space ID */
0073 
0074     status =
0075         acpi_ev_install_space_handler(node, space_id, handler, setup,
0076                       context);
0077     if (ACPI_FAILURE(status)) {
0078         goto unlock_and_exit;
0079     }
0080 
0081     /* Run all _REG methods for this address space */
0082 
0083     acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
0084 
0085 unlock_and_exit:
0086     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0087     return_ACPI_STATUS(status);
0088 }
0089 
0090 ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
0091 
0092 /*******************************************************************************
0093  *
0094  * FUNCTION:    acpi_remove_address_space_handler
0095  *
0096  * PARAMETERS:  device          - Handle for the device
0097  *              space_id        - The address space ID
0098  *              handler         - Address of the handler
0099  *
0100  * RETURN:      Status
0101  *
0102  * DESCRIPTION: Remove a previously installed handler.
0103  *
0104  ******************************************************************************/
0105 acpi_status
0106 acpi_remove_address_space_handler(acpi_handle device,
0107                   acpi_adr_space_type space_id,
0108                   acpi_adr_space_handler handler)
0109 {
0110     union acpi_operand_object *obj_desc;
0111     union acpi_operand_object *handler_obj;
0112     union acpi_operand_object *region_obj;
0113     union acpi_operand_object **last_obj_ptr;
0114     struct acpi_namespace_node *node;
0115     acpi_status status;
0116 
0117     ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler);
0118 
0119     /* Parameter validation */
0120 
0121     if (!device) {
0122         return_ACPI_STATUS(AE_BAD_PARAMETER);
0123     }
0124 
0125     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0126     if (ACPI_FAILURE(status)) {
0127         return_ACPI_STATUS(status);
0128     }
0129 
0130     /* Convert and validate the device handle */
0131 
0132     node = acpi_ns_validate_handle(device);
0133     if (!node ||
0134         ((node->type != ACPI_TYPE_DEVICE) &&
0135          (node->type != ACPI_TYPE_PROCESSOR) &&
0136          (node->type != ACPI_TYPE_THERMAL) &&
0137          (node != acpi_gbl_root_node))) {
0138         status = AE_BAD_PARAMETER;
0139         goto unlock_and_exit;
0140     }
0141 
0142     /* Make sure the internal object exists */
0143 
0144     obj_desc = acpi_ns_get_attached_object(node);
0145     if (!obj_desc) {
0146         status = AE_NOT_EXIST;
0147         goto unlock_and_exit;
0148     }
0149 
0150     /* Find the address handler the user requested */
0151 
0152     handler_obj = obj_desc->common_notify.handler;
0153     last_obj_ptr = &obj_desc->common_notify.handler;
0154     while (handler_obj) {
0155 
0156         /* We have a handler, see if user requested this one */
0157 
0158         if (handler_obj->address_space.space_id == space_id) {
0159 
0160             /* Handler must be the same as the installed handler */
0161 
0162             if (handler_obj->address_space.handler != handler) {
0163                 status = AE_BAD_PARAMETER;
0164                 goto unlock_and_exit;
0165             }
0166 
0167             /* Matched space_id, first dereference this in the Regions */
0168 
0169             ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0170                       "Removing address handler %p(%p) for region %s "
0171                       "on Device %p(%p)\n",
0172                       handler_obj, handler,
0173                       acpi_ut_get_region_name(space_id),
0174                       node, obj_desc));
0175 
0176             region_obj = handler_obj->address_space.region_list;
0177 
0178             /* Walk the handler's region list */
0179 
0180             while (region_obj) {
0181                 /*
0182                  * First disassociate the handler from the region.
0183                  *
0184                  * NOTE: this doesn't mean that the region goes away
0185                  * The region is just inaccessible as indicated to
0186                  * the _REG method
0187                  */
0188                 acpi_ev_detach_region(region_obj, TRUE);
0189 
0190                 /*
0191                  * Walk the list: Just grab the head because the
0192                  * detach_region removed the previous head.
0193                  */
0194                 region_obj =
0195                     handler_obj->address_space.region_list;
0196             }
0197 
0198             /* Remove this Handler object from the list */
0199 
0200             *last_obj_ptr = handler_obj->address_space.next;
0201 
0202             /* Now we can delete the handler object */
0203 
0204             acpi_os_release_mutex(handler_obj->address_space.
0205                           context_mutex);
0206             acpi_ut_remove_reference(handler_obj);
0207             goto unlock_and_exit;
0208         }
0209 
0210         /* Walk the linked list of handlers */
0211 
0212         last_obj_ptr = &handler_obj->address_space.next;
0213         handler_obj = handler_obj->address_space.next;
0214     }
0215 
0216     /* The handler does not exist */
0217 
0218     ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0219               "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
0220               handler, acpi_ut_get_region_name(space_id), space_id,
0221               node, obj_desc));
0222 
0223     status = AE_NOT_EXIST;
0224 
0225 unlock_and_exit:
0226     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0227     return_ACPI_STATUS(status);
0228 }
0229 
0230 ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)