622 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: evrgnini- ACPI address_space (op_region) init5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acevents.h"13#include "acnamesp.h"14#include "acinterp.h"15 16#define _COMPONENT ACPI_EVENTS17ACPI_MODULE_NAME("evrgnini")18 19/*******************************************************************************20 *21 * FUNCTION: acpi_ev_system_memory_region_setup22 *23 * PARAMETERS: handle - Region we are interested in24 * function - Start or stop25 * handler_context - Address space handler context26 * region_context - Region specific context27 *28 * RETURN: Status29 *30 * DESCRIPTION: Setup a system_memory operation region31 *32 ******************************************************************************/33acpi_status34acpi_ev_system_memory_region_setup(acpi_handle handle,35 u32 function,36 void *handler_context, void **region_context)37{38 union acpi_operand_object *region_desc =39 (union acpi_operand_object *)handle;40 struct acpi_mem_space_context *local_region_context;41 struct acpi_mem_mapping *mm;42 43 ACPI_FUNCTION_TRACE(ev_system_memory_region_setup);44 45 if (function == ACPI_REGION_DEACTIVATE) {46 if (*region_context) {47 local_region_context =48 (struct acpi_mem_space_context *)*region_context;49 50 /* Delete memory mappings if present */51 52 while (local_region_context->first_mm) {53 mm = local_region_context->first_mm;54 local_region_context->first_mm = mm->next_mm;55 acpi_os_unmap_memory(mm->logical_address,56 mm->length);57 ACPI_FREE(mm);58 }59 ACPI_FREE(local_region_context);60 *region_context = NULL;61 }62 return_ACPI_STATUS(AE_OK);63 }64 65 /* Create a new context */66 67 local_region_context =68 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context));69 if (!(local_region_context)) {70 return_ACPI_STATUS(AE_NO_MEMORY);71 }72 73 /* Save the region length and address for use in the handler */74 75 local_region_context->length = region_desc->region.length;76 local_region_context->address = region_desc->region.address;77 78 *region_context = local_region_context;79 return_ACPI_STATUS(AE_OK);80}81 82/*******************************************************************************83 *84 * FUNCTION: acpi_ev_io_space_region_setup85 *86 * PARAMETERS: handle - Region we are interested in87 * function - Start or stop88 * handler_context - Address space handler context89 * region_context - Region specific context90 *91 * RETURN: Status92 *93 * DESCRIPTION: Setup a IO operation region94 *95 ******************************************************************************/96 97acpi_status98acpi_ev_io_space_region_setup(acpi_handle handle,99 u32 function,100 void *handler_context, void **region_context)101{102 ACPI_FUNCTION_TRACE(ev_io_space_region_setup);103 104 if (function == ACPI_REGION_DEACTIVATE) {105 *region_context = NULL;106 } else {107 *region_context = handler_context;108 }109 110 return_ACPI_STATUS(AE_OK);111}112 113/*******************************************************************************114 *115 * FUNCTION: acpi_ev_pci_config_region_setup116 *117 * PARAMETERS: handle - Region we are interested in118 * function - Start or stop119 * handler_context - Address space handler context120 * region_context - Region specific context121 *122 * RETURN: Status123 *124 * DESCRIPTION: Setup a PCI_Config operation region125 *126 * MUTEX: Assumes namespace is not locked127 *128 ******************************************************************************/129 130acpi_status131acpi_ev_pci_config_region_setup(acpi_handle handle,132 u32 function,133 void *handler_context, void **region_context)134{135 acpi_status status = AE_OK;136 u64 pci_value;137 struct acpi_pci_id *pci_id = *region_context;138 union acpi_operand_object *handler_obj;139 struct acpi_namespace_node *parent_node;140 struct acpi_namespace_node *pci_root_node;141 struct acpi_namespace_node *pci_device_node;142 union acpi_operand_object *region_obj =143 (union acpi_operand_object *)handle;144 145 ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);146 147 handler_obj = region_obj->region.handler;148 if (!handler_obj) {149 /*150 * No installed handler. This shouldn't happen because the dispatch151 * routine checks before we get here, but we check again just in case.152 */153 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,154 "Attempting to init a region %p, with no handler\n",155 region_obj));156 return_ACPI_STATUS(AE_NOT_EXIST);157 }158 159 *region_context = NULL;160 if (function == ACPI_REGION_DEACTIVATE) {161 if (pci_id) {162 ACPI_FREE(pci_id);163 }164 return_ACPI_STATUS(status);165 }166 167 parent_node = region_obj->region.node->parent;168 169 /*170 * Get the _SEG and _BBN values from the device upon which the handler171 * is installed.172 *173 * We need to get the _SEG and _BBN objects relative to the PCI BUS device.174 * This is the device the handler has been registered to handle.175 */176 177 /*178 * If the address_space.Node is still pointing to the root, we need179 * to scan upward for a PCI Root bridge and re-associate the op_region180 * handlers with that device.181 */182 if (handler_obj->address_space.node == acpi_gbl_root_node) {183 184 /* Start search from the parent object */185 186 pci_root_node = parent_node;187 while (pci_root_node != acpi_gbl_root_node) {188 189 /* Get the _HID/_CID in order to detect a root_bridge */190 191 if (acpi_ev_is_pci_root_bridge(pci_root_node)) {192 193 /* Install a handler for this PCI root bridge */194 195 status = acpi_install_address_space_handler((acpi_handle)pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);196 if (ACPI_FAILURE(status)) {197 if (status == AE_SAME_HANDLER) {198 /*199 * It is OK if the handler is already installed on the200 * root bridge. Still need to return a context object201 * for the new PCI_Config operation region, however.202 */203 } else {204 ACPI_EXCEPTION((AE_INFO, status,205 "Could not install PciConfig handler "206 "for Root Bridge %4.4s",207 acpi_ut_get_node_name208 (pci_root_node)));209 }210 }211 break;212 }213 214 pci_root_node = pci_root_node->parent;215 }216 217 /* PCI root bridge not found, use namespace root node */218 } else {219 pci_root_node = handler_obj->address_space.node;220 }221 222 /*223 * If this region is now initialized, we are done.224 * (install_address_space_handler could have initialized it)225 */226 if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {227 return_ACPI_STATUS(AE_OK);228 }229 230 /* Region is still not initialized. Create a new context */231 232 pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id));233 if (!pci_id) {234 return_ACPI_STATUS(AE_NO_MEMORY);235 }236 237 /*238 * For PCI_Config space access, we need the segment, bus, device and239 * function numbers. Acquire them here.240 *241 * Find the parent device object. (This allows the operation region to be242 * within a subscope under the device, such as a control method.)243 */244 pci_device_node = region_obj->region.node;245 while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) {246 pci_device_node = pci_device_node->parent;247 }248 249 if (!pci_device_node) {250 ACPI_FREE(pci_id);251 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);252 }253 254 /*255 * Get the PCI device and function numbers from the _ADR object256 * contained in the parent's scope.257 */258 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,259 pci_device_node, &pci_value);260 261 /*262 * The default is zero, and since the allocation above zeroed the data,263 * just do nothing on failure.264 */265 if (ACPI_SUCCESS(status)) {266 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value));267 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value));268 }269 270 /* The PCI segment number comes from the _SEG method */271 272 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG,273 pci_root_node, &pci_value);274 if (ACPI_SUCCESS(status)) {275 pci_id->segment = ACPI_LOWORD(pci_value);276 }277 278 /* The PCI bus number comes from the _BBN method */279 280 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN,281 pci_root_node, &pci_value);282 if (ACPI_SUCCESS(status)) {283 pci_id->bus = ACPI_LOWORD(pci_value);284 }285 286 /* Complete/update the PCI ID for this device */287 288 status =289 acpi_hw_derive_pci_id(pci_id, pci_root_node,290 region_obj->region.node);291 if (ACPI_FAILURE(status)) {292 ACPI_FREE(pci_id);293 return_ACPI_STATUS(status);294 }295 296 *region_context = pci_id;297 return_ACPI_STATUS(AE_OK);298}299 300/*******************************************************************************301 *302 * FUNCTION: acpi_ev_is_pci_root_bridge303 *304 * PARAMETERS: node - Device node being examined305 *306 * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge307 *308 * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by309 * examining the _HID and _CID for the device.310 *311 ******************************************************************************/312 313u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)314{315 acpi_status status;316 struct acpi_pnp_device_id *hid;317 struct acpi_pnp_device_id_list *cid;318 u32 i;319 u8 match;320 321 /* Get the _HID and check for a PCI Root Bridge */322 323 status = acpi_ut_execute_HID(node, &hid);324 if (ACPI_FAILURE(status)) {325 return (FALSE);326 }327 328 match = acpi_ut_is_pci_root_bridge(hid->string);329 ACPI_FREE(hid);330 331 if (match) {332 return (TRUE);333 }334 335 /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */336 337 status = acpi_ut_execute_CID(node, &cid);338 if (ACPI_FAILURE(status)) {339 return (FALSE);340 }341 342 /* Check all _CIDs in the returned list */343 344 for (i = 0; i < cid->count; i++) {345 if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) {346 ACPI_FREE(cid);347 return (TRUE);348 }349 }350 351 ACPI_FREE(cid);352 return (FALSE);353}354 355/*******************************************************************************356 *357 * FUNCTION: acpi_ev_pci_bar_region_setup358 *359 * PARAMETERS: handle - Region we are interested in360 * function - Start or stop361 * handler_context - Address space handler context362 * region_context - Region specific context363 *364 * RETURN: Status365 *366 * DESCRIPTION: Setup a pci_BAR operation region367 *368 * MUTEX: Assumes namespace is not locked369 *370 ******************************************************************************/371 372acpi_status373acpi_ev_pci_bar_region_setup(acpi_handle handle,374 u32 function,375 void *handler_context, void **region_context)376{377 ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup);378 379 return_ACPI_STATUS(AE_OK);380}381 382/*******************************************************************************383 *384 * FUNCTION: acpi_ev_cmos_region_setup385 *386 * PARAMETERS: handle - Region we are interested in387 * function - Start or stop388 * handler_context - Address space handler context389 * region_context - Region specific context390 *391 * RETURN: Status392 *393 * DESCRIPTION: Setup a CMOS operation region394 *395 * MUTEX: Assumes namespace is not locked396 *397 ******************************************************************************/398 399acpi_status400acpi_ev_cmos_region_setup(acpi_handle handle,401 u32 function,402 void *handler_context, void **region_context)403{404 ACPI_FUNCTION_TRACE(ev_cmos_region_setup);405 406 return_ACPI_STATUS(AE_OK);407}408 409/*******************************************************************************410 *411 * FUNCTION: acpi_ev_data_table_region_setup412 *413 * PARAMETERS: handle - Region we are interested in414 * function - Start or stop415 * handler_context - Address space handler context416 * region_context - Region specific context417 *418 * RETURN: Status419 *420 * DESCRIPTION: Setup a data_table_region421 *422 * MUTEX: Assumes namespace is not locked423 *424 ******************************************************************************/425 426acpi_status427acpi_ev_data_table_region_setup(acpi_handle handle,428 u32 function,429 void *handler_context, void **region_context)430{431 union acpi_operand_object *region_desc =432 (union acpi_operand_object *)handle;433 struct acpi_data_table_mapping *local_region_context;434 435 ACPI_FUNCTION_TRACE(ev_data_table_region_setup);436 437 if (function == ACPI_REGION_DEACTIVATE) {438 if (*region_context) {439 ACPI_FREE(*region_context);440 *region_context = NULL;441 }442 return_ACPI_STATUS(AE_OK);443 }444 445 /* Create a new context */446 447 local_region_context =448 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_data_table_mapping));449 if (!(local_region_context)) {450 return_ACPI_STATUS(AE_NO_MEMORY);451 }452 453 /* Save the data table pointer for use in the handler */454 455 local_region_context->pointer = region_desc->region.pointer;456 457 *region_context = local_region_context;458 return_ACPI_STATUS(AE_OK);459}460 461/*******************************************************************************462 *463 * FUNCTION: acpi_ev_default_region_setup464 *465 * PARAMETERS: handle - Region we are interested in466 * function - Start or stop467 * handler_context - Address space handler context468 * region_context - Region specific context469 *470 * RETURN: Status471 *472 * DESCRIPTION: Default region initialization473 *474 ******************************************************************************/475 476acpi_status477acpi_ev_default_region_setup(acpi_handle handle,478 u32 function,479 void *handler_context, void **region_context)480{481 ACPI_FUNCTION_TRACE(ev_default_region_setup);482 483 if (function == ACPI_REGION_DEACTIVATE) {484 *region_context = NULL;485 } else {486 *region_context = handler_context;487 }488 489 return_ACPI_STATUS(AE_OK);490}491 492/*******************************************************************************493 *494 * FUNCTION: acpi_ev_initialize_region495 *496 * PARAMETERS: region_obj - Region we are initializing497 *498 * RETURN: Status499 *500 * DESCRIPTION: Initializes the region, finds any _REG methods and saves them501 * for execution at a later time502 *503 * Get the appropriate address space handler for a newly504 * created region.505 *506 * This also performs address space specific initialization. For507 * example, PCI regions must have an _ADR object that contains508 * a PCI address in the scope of the definition. This address is509 * required to perform an access to PCI config space.510 *511 * MUTEX: Interpreter should be unlocked, because we may run the _REG512 * method for this region.513 *514 * NOTE: Possible incompliance:515 * There is a behavior conflict in automatic _REG execution:516 * 1. When the interpreter is evaluating a method, we can only517 * automatically run _REG for the following case:518 * operation_region (OPR1, 0x80, 0x1000010, 0x4)519 * 2. When the interpreter is loading a table, we can also520 * automatically run _REG for the following case:521 * operation_region (OPR1, 0x80, 0x1000010, 0x4)522 * Though this may not be compliant to the de-facto standard, the523 * logic is kept in order not to trigger regressions. And keeping524 * this logic should be taken care by the caller of this function.525 *526 ******************************************************************************/527 528acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj)529{530 union acpi_operand_object *handler_obj;531 union acpi_operand_object *obj_desc;532 acpi_adr_space_type space_id;533 struct acpi_namespace_node *node;534 535 ACPI_FUNCTION_TRACE(ev_initialize_region);536 537 if (!region_obj) {538 return_ACPI_STATUS(AE_BAD_PARAMETER);539 }540 541 if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {542 return_ACPI_STATUS(AE_OK);543 }544 545 region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;546 547 node = region_obj->region.node->parent;548 space_id = region_obj->region.space_id;549 550 /*551 * The following loop depends upon the root Node having no parent552 * ie: acpi_gbl_root_node->Parent being set to NULL553 */554 while (node) {555 556 /* Check to see if a handler exists */557 558 handler_obj = NULL;559 obj_desc = acpi_ns_get_attached_object(node);560 if (obj_desc) {561 562 /* Can only be a handler if the object exists */563 564 switch (node->type) {565 case ACPI_TYPE_DEVICE:566 case ACPI_TYPE_PROCESSOR:567 case ACPI_TYPE_THERMAL:568 569 handler_obj = obj_desc->common_notify.handler;570 break;571 572 default:573 574 /* Ignore other objects */575 576 break;577 }578 579 handler_obj =580 acpi_ev_find_region_handler(space_id, handler_obj);581 if (handler_obj) {582 583 /* Found correct handler */584 585 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,586 "Found handler %p for region %p in obj %p\n",587 handler_obj, region_obj,588 obj_desc));589 590 (void)acpi_ev_attach_region(handler_obj,591 region_obj, FALSE);592 593 /*594 * Tell all users that this region is usable by595 * running the _REG method596 */597 acpi_ex_exit_interpreter();598 (void)acpi_ev_execute_reg_method(region_obj,599 ACPI_REG_CONNECT);600 acpi_ex_enter_interpreter();601 return_ACPI_STATUS(AE_OK);602 }603 }604 605 /* This node does not have the handler we need; Pop up one level */606 607 node = node->parent;608 }609 610 /*611 * If we get here, there is no handler for this region. This is not612 * fatal because many regions get created before a handler is installed613 * for said region.614 */615 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,616 "No handler for RegionType %s(%X) (RegionObj %p)\n",617 acpi_ut_get_region_name(space_id), space_id,618 region_obj));619 620 return_ACPI_STATUS(AE_OK);621}622