root/drivers/acpi/acpica/evxfregn.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. ACPI_EXPORT_SYMBOL

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
   5  *                         Address Spaces.
   6  *
   7  * Copyright (C) 2000 - 2019, Intel Corp.
   8  *
   9  *****************************************************************************/
  10 
  11 #define EXPORT_ACPI_INTERFACES
  12 
  13 #include <acpi/acpi.h>
  14 #include "accommon.h"
  15 #include "acnamesp.h"
  16 #include "acevents.h"
  17 
  18 #define _COMPONENT          ACPI_EVENTS
  19 ACPI_MODULE_NAME("evxfregn")
  20 
  21 /*******************************************************************************
  22  *
  23  * FUNCTION:    acpi_install_address_space_handler
  24  *
  25  * PARAMETERS:  device          - Handle for the device
  26  *              space_id        - The address space ID
  27  *              handler         - Address of the handler
  28  *              setup           - Address of the setup function
  29  *              context         - Value passed to the handler on each access
  30  *
  31  * RETURN:      Status
  32  *
  33  * DESCRIPTION: Install a handler for all op_regions of a given space_id.
  34  *
  35  * NOTE: This function should only be called after acpi_enable_subsystem has
  36  * been called. This is because any _REG methods associated with the Space ID
  37  * are executed here, and these methods can only be safely executed after
  38  * the default handlers have been installed and the hardware has been
  39  * initialized (via acpi_enable_subsystem.)
  40  *
  41  ******************************************************************************/
  42 acpi_status
  43 acpi_install_address_space_handler(acpi_handle device,
  44                                    acpi_adr_space_type space_id,
  45                                    acpi_adr_space_handler handler,
  46                                    acpi_adr_space_setup setup, void *context)
  47 {
  48         struct acpi_namespace_node *node;
  49         acpi_status status;
  50 
  51         ACPI_FUNCTION_TRACE(acpi_install_address_space_handler);
  52 
  53         /* Parameter validation */
  54 
  55         if (!device) {
  56                 return_ACPI_STATUS(AE_BAD_PARAMETER);
  57         }
  58 
  59         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  60         if (ACPI_FAILURE(status)) {
  61                 return_ACPI_STATUS(status);
  62         }
  63 
  64         /* Convert and validate the device handle */
  65 
  66         node = acpi_ns_validate_handle(device);
  67         if (!node) {
  68                 status = AE_BAD_PARAMETER;
  69                 goto unlock_and_exit;
  70         }
  71 
  72         /* Install the handler for all Regions for this Space ID */
  73 
  74         status =
  75             acpi_ev_install_space_handler(node, space_id, handler, setup,
  76                                           context);
  77         if (ACPI_FAILURE(status)) {
  78                 goto unlock_and_exit;
  79         }
  80 
  81         /* Run all _REG methods for this address space */
  82 
  83         acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
  84 
  85 unlock_and_exit:
  86         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  87         return_ACPI_STATUS(status);
  88 }
  89 
  90 ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
  91 
  92 /*******************************************************************************
  93  *
  94  * FUNCTION:    acpi_remove_address_space_handler
  95  *
  96  * PARAMETERS:  device          - Handle for the device
  97  *              space_id        - The address space ID
  98  *              handler         - Address of the handler
  99  *
 100  * RETURN:      Status
 101  *
 102  * DESCRIPTION: Remove a previously installed handler.
 103  *
 104  ******************************************************************************/
 105 acpi_status
 106 acpi_remove_address_space_handler(acpi_handle device,
 107                                   acpi_adr_space_type space_id,
 108                                   acpi_adr_space_handler handler)
 109 {
 110         union acpi_operand_object *obj_desc;
 111         union acpi_operand_object *handler_obj;
 112         union acpi_operand_object *region_obj;
 113         union acpi_operand_object **last_obj_ptr;
 114         struct acpi_namespace_node *node;
 115         acpi_status status;
 116 
 117         ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler);
 118 
 119         /* Parameter validation */
 120 
 121         if (!device) {
 122                 return_ACPI_STATUS(AE_BAD_PARAMETER);
 123         }
 124 
 125         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 126         if (ACPI_FAILURE(status)) {
 127                 return_ACPI_STATUS(status);
 128         }
 129 
 130         /* Convert and validate the device handle */
 131 
 132         node = acpi_ns_validate_handle(device);
 133         if (!node ||
 134             ((node->type != ACPI_TYPE_DEVICE) &&
 135              (node->type != ACPI_TYPE_PROCESSOR) &&
 136              (node->type != ACPI_TYPE_THERMAL) &&
 137              (node != acpi_gbl_root_node))) {
 138                 status = AE_BAD_PARAMETER;
 139                 goto unlock_and_exit;
 140         }
 141 
 142         /* Make sure the internal object exists */
 143 
 144         obj_desc = acpi_ns_get_attached_object(node);
 145         if (!obj_desc) {
 146                 status = AE_NOT_EXIST;
 147                 goto unlock_and_exit;
 148         }
 149 
 150         /* Find the address handler the user requested */
 151 
 152         handler_obj = obj_desc->common_notify.handler;
 153         last_obj_ptr = &obj_desc->common_notify.handler;
 154         while (handler_obj) {
 155 
 156                 /* We have a handler, see if user requested this one */
 157 
 158                 if (handler_obj->address_space.space_id == space_id) {
 159 
 160                         /* Handler must be the same as the installed handler */
 161 
 162                         if (handler_obj->address_space.handler != handler) {
 163                                 status = AE_BAD_PARAMETER;
 164                                 goto unlock_and_exit;
 165                         }
 166 
 167                         /* Matched space_id, first dereference this in the Regions */
 168 
 169                         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 170                                           "Removing address handler %p(%p) for region %s "
 171                                           "on Device %p(%p)\n",
 172                                           handler_obj, handler,
 173                                           acpi_ut_get_region_name(space_id),
 174                                           node, obj_desc));
 175 
 176                         region_obj = handler_obj->address_space.region_list;
 177 
 178                         /* Walk the handler's region list */
 179 
 180                         while (region_obj) {
 181                                 /*
 182                                  * First disassociate the handler from the region.
 183                                  *
 184                                  * NOTE: this doesn't mean that the region goes away
 185                                  * The region is just inaccessible as indicated to
 186                                  * the _REG method
 187                                  */
 188                                 acpi_ev_detach_region(region_obj, TRUE);
 189 
 190                                 /*
 191                                  * Walk the list: Just grab the head because the
 192                                  * detach_region removed the previous head.
 193                                  */
 194                                 region_obj =
 195                                     handler_obj->address_space.region_list;
 196                         }
 197 
 198                         /* Remove this Handler object from the list */
 199 
 200                         *last_obj_ptr = handler_obj->address_space.next;
 201 
 202                         /* Now we can delete the handler object */
 203 
 204                         acpi_ut_remove_reference(handler_obj);
 205                         goto unlock_and_exit;
 206                 }
 207 
 208                 /* Walk the linked list of handlers */
 209 
 210                 last_obj_ptr = &handler_obj->address_space.next;
 211                 handler_obj = handler_obj->address_space.next;
 212         }
 213 
 214         /* The handler does not exist */
 215 
 216         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 217                           "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
 218                           handler, acpi_ut_get_region_name(space_id), space_id,
 219                           node, obj_desc));
 220 
 221         status = AE_NOT_EXIST;
 222 
 223 unlock_and_exit:
 224         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 225         return_ACPI_STATUS(status);
 226 }
 227 
 228 ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)

/* [<][>][^][v][top][bottom][index][help] */