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 - 2023, 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_internal 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 * Run_reg - Run _REG methods for this address space? 31 * 32 * RETURN: Status 33 * 34 * DESCRIPTION: Install a handler for all op_regions of a given space_id. 35 * 36 * NOTE: This function should only be called after acpi_enable_subsystem has 37 * been called. This is because any _REG methods associated with the Space ID 38 * are executed here, and these methods can only be safely executed after 39 * the default handlers have been installed and the hardware has been 40 * initialized (via acpi_enable_subsystem.) 41 * To avoid this problem pass FALSE for Run_Reg and later on call 42 * acpi_execute_reg_methods() to execute _REG. 43 * 44 ******************************************************************************/ 45 static acpi_status 46 acpi_install_address_space_handler_internal(acpi_handle device, 47 acpi_adr_space_type space_id, 48 acpi_adr_space_handler handler, 49 acpi_adr_space_setup setup, 50 void *context, u8 run_reg) 51 { 52 struct acpi_namespace_node *node; 53 acpi_status status; 54 55 ACPI_FUNCTION_TRACE(acpi_install_address_space_handler); 56 57 /* Parameter validation */ 58 59 if (!device) { 60 return_ACPI_STATUS(AE_BAD_PARAMETER); 61 } 62 63 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 64 if (ACPI_FAILURE(status)) { 65 return_ACPI_STATUS(status); 66 } 67 68 /* Convert and validate the device handle */ 69 70 node = acpi_ns_validate_handle(device); 71 if (!node) { 72 status = AE_BAD_PARAMETER; 73 goto unlock_and_exit; 74 } 75 76 /* Install the handler for all Regions for this Space ID */ 77 78 status = 79 acpi_ev_install_space_handler(node, space_id, handler, setup, 80 context); 81 if (ACPI_FAILURE(status)) { 82 goto unlock_and_exit; 83 } 84 85 /* Run all _REG methods for this address space */ 86 87 if (run_reg) { 88 acpi_ev_execute_reg_methods(node, ACPI_UINT32_MAX, space_id, 89 ACPI_REG_CONNECT); 90 } 91 92 unlock_and_exit: 93 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 94 return_ACPI_STATUS(status); 95 } 96 97 acpi_status 98 acpi_install_address_space_handler(acpi_handle device, 99 acpi_adr_space_type space_id, 100 acpi_adr_space_handler handler, 101 acpi_adr_space_setup setup, void *context) 102 { 103 return acpi_install_address_space_handler_internal(device, space_id, 104 handler, setup, 105 context, TRUE); 106 } 107 108 ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler) 109 acpi_status 110 acpi_install_address_space_handler_no_reg(acpi_handle device, 111 acpi_adr_space_type space_id, 112 acpi_adr_space_handler handler, 113 acpi_adr_space_setup setup, 114 void *context) 115 { 116 return acpi_install_address_space_handler_internal(device, space_id, 117 handler, setup, 118 context, FALSE); 119 } 120 121 ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler_no_reg) 122 123 /******************************************************************************* 124 * 125 * FUNCTION: acpi_remove_address_space_handler 126 * 127 * PARAMETERS: device - Handle for the device 128 * space_id - The address space ID 129 * handler - Address of the handler 130 * 131 * RETURN: Status 132 * 133 * DESCRIPTION: Remove a previously installed handler. 134 * 135 ******************************************************************************/ 136 acpi_status 137 acpi_remove_address_space_handler(acpi_handle device, 138 acpi_adr_space_type space_id, 139 acpi_adr_space_handler handler) 140 { 141 union acpi_operand_object *obj_desc; 142 union acpi_operand_object *handler_obj; 143 union acpi_operand_object *region_obj; 144 union acpi_operand_object **last_obj_ptr; 145 struct acpi_namespace_node *node; 146 acpi_status status; 147 148 ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler); 149 150 /* Parameter validation */ 151 152 if (!device) { 153 return_ACPI_STATUS(AE_BAD_PARAMETER); 154 } 155 156 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 157 if (ACPI_FAILURE(status)) { 158 return_ACPI_STATUS(status); 159 } 160 161 /* Convert and validate the device handle */ 162 163 node = acpi_ns_validate_handle(device); 164 if (!node || 165 ((node->type != ACPI_TYPE_DEVICE) && 166 (node->type != ACPI_TYPE_PROCESSOR) && 167 (node->type != ACPI_TYPE_THERMAL) && 168 (node != acpi_gbl_root_node))) { 169 status = AE_BAD_PARAMETER; 170 goto unlock_and_exit; 171 } 172 173 /* Make sure the internal object exists */ 174 175 obj_desc = acpi_ns_get_attached_object(node); 176 if (!obj_desc) { 177 status = AE_NOT_EXIST; 178 goto unlock_and_exit; 179 } 180 181 /* Find the address handler the user requested */ 182 183 handler_obj = obj_desc->common_notify.handler; 184 last_obj_ptr = &obj_desc->common_notify.handler; 185 while (handler_obj) { 186 187 /* We have a handler, see if user requested this one */ 188 189 if (handler_obj->address_space.space_id == space_id) { 190 191 /* Handler must be the same as the installed handler */ 192 193 if (handler_obj->address_space.handler != handler) { 194 status = AE_BAD_PARAMETER; 195 goto unlock_and_exit; 196 } 197 198 /* Matched space_id, first dereference this in the Regions */ 199 200 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 201 "Removing address handler %p(%p) for region %s " 202 "on Device %p(%p)\n", 203 handler_obj, handler, 204 acpi_ut_get_region_name(space_id), 205 node, obj_desc)); 206 207 region_obj = handler_obj->address_space.region_list; 208 209 /* Walk the handler's region list */ 210 211 while (region_obj) { 212 /* 213 * First disassociate the handler from the region. 214 * 215 * NOTE: this doesn't mean that the region goes away 216 * The region is just inaccessible as indicated to 217 * the _REG method 218 */ 219 acpi_ev_detach_region(region_obj, TRUE); 220 221 /* 222 * Walk the list: Just grab the head because the 223 * detach_region removed the previous head. 224 */ 225 region_obj = 226 handler_obj->address_space.region_list; 227 } 228 229 /* Remove this Handler object from the list */ 230 231 *last_obj_ptr = handler_obj->address_space.next; 232 233 /* Now we can delete the handler object */ 234 235 acpi_os_release_mutex(handler_obj->address_space. 236 context_mutex); 237 acpi_ut_remove_reference(handler_obj); 238 goto unlock_and_exit; 239 } 240 241 /* Walk the linked list of handlers */ 242 243 last_obj_ptr = &handler_obj->address_space.next; 244 handler_obj = handler_obj->address_space.next; 245 } 246 247 /* The handler does not exist */ 248 249 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 250 "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n", 251 handler, acpi_ut_get_region_name(space_id), space_id, 252 node, obj_desc)); 253 254 status = AE_NOT_EXIST; 255 256 unlock_and_exit: 257 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 258 return_ACPI_STATUS(status); 259 } 260 261 ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler) 262 /******************************************************************************* 263 * 264 * FUNCTION: acpi_execute_reg_methods 265 * 266 * PARAMETERS: device - Handle for the device 267 * max_depth - Depth to which search for _REG 268 * space_id - The address space ID 269 * 270 * RETURN: Status 271 * 272 * DESCRIPTION: Execute _REG for all op_regions of a given space_id. 273 * 274 ******************************************************************************/ 275 acpi_status 276 acpi_execute_reg_methods(acpi_handle device, u32 max_depth, 277 acpi_adr_space_type space_id) 278 { 279 struct acpi_namespace_node *node; 280 acpi_status status; 281 282 ACPI_FUNCTION_TRACE(acpi_execute_reg_methods); 283 284 /* Parameter validation */ 285 286 if (!device) { 287 return_ACPI_STATUS(AE_BAD_PARAMETER); 288 } 289 290 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 291 if (ACPI_FAILURE(status)) { 292 return_ACPI_STATUS(status); 293 } 294 295 /* Convert and validate the device handle */ 296 297 node = acpi_ns_validate_handle(device); 298 if (node) { 299 300 /* Run all _REG methods for this address space */ 301 302 acpi_ev_execute_reg_methods(node, max_depth, space_id, 303 ACPI_REG_CONNECT); 304 } else { 305 status = AE_BAD_PARAMETER; 306 } 307 308 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 309 return_ACPI_STATUS(status); 310 } 311 312 ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods) 313