Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: evrgnini- ACPI address_space (op_region) init
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acevents.h"
0013 #include "acnamesp.h"
0014 #include "acinterp.h"
0015 
0016 #define _COMPONENT          ACPI_EVENTS
0017 ACPI_MODULE_NAME("evrgnini")
0018 
0019 /*******************************************************************************
0020  *
0021  * FUNCTION:    acpi_ev_system_memory_region_setup
0022  *
0023  * PARAMETERS:  handle              - Region we are interested in
0024  *              function            - Start or stop
0025  *              handler_context     - Address space handler context
0026  *              region_context      - Region specific context
0027  *
0028  * RETURN:      Status
0029  *
0030  * DESCRIPTION: Setup a system_memory operation region
0031  *
0032  ******************************************************************************/
0033 acpi_status
0034 acpi_ev_system_memory_region_setup(acpi_handle handle,
0035                    u32 function,
0036                    void *handler_context, void **region_context)
0037 {
0038     union acpi_operand_object *region_desc =
0039         (union acpi_operand_object *)handle;
0040     struct acpi_mem_space_context *local_region_context;
0041     struct acpi_mem_mapping *mm;
0042 
0043     ACPI_FUNCTION_TRACE(ev_system_memory_region_setup);
0044 
0045     if (function == ACPI_REGION_DEACTIVATE) {
0046         if (*region_context) {
0047             local_region_context =
0048                 (struct acpi_mem_space_context *)*region_context;
0049 
0050             /* Delete memory mappings if present */
0051 
0052             while (local_region_context->first_mm) {
0053                 mm = local_region_context->first_mm;
0054                 local_region_context->first_mm = mm->next_mm;
0055                 acpi_os_unmap_memory(mm->logical_address,
0056                              mm->length);
0057                 ACPI_FREE(mm);
0058             }
0059             ACPI_FREE(local_region_context);
0060             *region_context = NULL;
0061         }
0062         return_ACPI_STATUS(AE_OK);
0063     }
0064 
0065     /* Create a new context */
0066 
0067     local_region_context =
0068         ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context));
0069     if (!(local_region_context)) {
0070         return_ACPI_STATUS(AE_NO_MEMORY);
0071     }
0072 
0073     /* Save the region length and address for use in the handler */
0074 
0075     local_region_context->length = region_desc->region.length;
0076     local_region_context->address = region_desc->region.address;
0077 
0078     *region_context = local_region_context;
0079     return_ACPI_STATUS(AE_OK);
0080 }
0081 
0082 /*******************************************************************************
0083  *
0084  * FUNCTION:    acpi_ev_io_space_region_setup
0085  *
0086  * PARAMETERS:  handle              - Region we are interested in
0087  *              function            - Start or stop
0088  *              handler_context     - Address space handler context
0089  *              region_context      - Region specific context
0090  *
0091  * RETURN:      Status
0092  *
0093  * DESCRIPTION: Setup a IO operation region
0094  *
0095  ******************************************************************************/
0096 
0097 acpi_status
0098 acpi_ev_io_space_region_setup(acpi_handle handle,
0099                   u32 function,
0100                   void *handler_context, void **region_context)
0101 {
0102     ACPI_FUNCTION_TRACE(ev_io_space_region_setup);
0103 
0104     if (function == ACPI_REGION_DEACTIVATE) {
0105         *region_context = NULL;
0106     } else {
0107         *region_context = handler_context;
0108     }
0109 
0110     return_ACPI_STATUS(AE_OK);
0111 }
0112 
0113 /*******************************************************************************
0114  *
0115  * FUNCTION:    acpi_ev_pci_config_region_setup
0116  *
0117  * PARAMETERS:  handle              - Region we are interested in
0118  *              function            - Start or stop
0119  *              handler_context     - Address space handler context
0120  *              region_context      - Region specific context
0121  *
0122  * RETURN:      Status
0123  *
0124  * DESCRIPTION: Setup a PCI_Config operation region
0125  *
0126  * MUTEX:       Assumes namespace is not locked
0127  *
0128  ******************************************************************************/
0129 
0130 acpi_status
0131 acpi_ev_pci_config_region_setup(acpi_handle handle,
0132                 u32 function,
0133                 void *handler_context, void **region_context)
0134 {
0135     acpi_status status = AE_OK;
0136     u64 pci_value;
0137     struct acpi_pci_id *pci_id = *region_context;
0138     union acpi_operand_object *handler_obj;
0139     struct acpi_namespace_node *parent_node;
0140     struct acpi_namespace_node *pci_root_node;
0141     struct acpi_namespace_node *pci_device_node;
0142     union acpi_operand_object *region_obj =
0143         (union acpi_operand_object *)handle;
0144 
0145     ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);
0146 
0147     handler_obj = region_obj->region.handler;
0148     if (!handler_obj) {
0149         /*
0150          * No installed handler. This shouldn't happen because the dispatch
0151          * routine checks before we get here, but we check again just in case.
0152          */
0153         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0154                   "Attempting to init a region %p, with no handler\n",
0155                   region_obj));
0156         return_ACPI_STATUS(AE_NOT_EXIST);
0157     }
0158 
0159     *region_context = NULL;
0160     if (function == ACPI_REGION_DEACTIVATE) {
0161         if (pci_id) {
0162             ACPI_FREE(pci_id);
0163         }
0164         return_ACPI_STATUS(status);
0165     }
0166 
0167     parent_node = region_obj->region.node->parent;
0168 
0169     /*
0170      * Get the _SEG and _BBN values from the device upon which the handler
0171      * is installed.
0172      *
0173      * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
0174      * This is the device the handler has been registered to handle.
0175      */
0176 
0177     /*
0178      * If the address_space.Node is still pointing to the root, we need
0179      * to scan upward for a PCI Root bridge and re-associate the op_region
0180      * handlers with that device.
0181      */
0182     if (handler_obj->address_space.node == acpi_gbl_root_node) {
0183 
0184         /* Start search from the parent object */
0185 
0186         pci_root_node = parent_node;
0187         while (pci_root_node != acpi_gbl_root_node) {
0188 
0189             /* Get the _HID/_CID in order to detect a root_bridge */
0190 
0191             if (acpi_ev_is_pci_root_bridge(pci_root_node)) {
0192 
0193                 /* Install a handler for this PCI root bridge */
0194 
0195                 status = acpi_install_address_space_handler((acpi_handle)pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
0196                 if (ACPI_FAILURE(status)) {
0197                     if (status == AE_SAME_HANDLER) {
0198                         /*
0199                          * It is OK if the handler is already installed on the
0200                          * root bridge. Still need to return a context object
0201                          * for the new PCI_Config operation region, however.
0202                          */
0203                     } else {
0204                         ACPI_EXCEPTION((AE_INFO, status,
0205                                 "Could not install PciConfig handler "
0206                                 "for Root Bridge %4.4s",
0207                                 acpi_ut_get_node_name
0208                                 (pci_root_node)));
0209                     }
0210                 }
0211                 break;
0212             }
0213 
0214             pci_root_node = pci_root_node->parent;
0215         }
0216 
0217         /* PCI root bridge not found, use namespace root node */
0218     } else {
0219         pci_root_node = handler_obj->address_space.node;
0220     }
0221 
0222     /*
0223      * If this region is now initialized, we are done.
0224      * (install_address_space_handler could have initialized it)
0225      */
0226     if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
0227         return_ACPI_STATUS(AE_OK);
0228     }
0229 
0230     /* Region is still not initialized. Create a new context */
0231 
0232     pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id));
0233     if (!pci_id) {
0234         return_ACPI_STATUS(AE_NO_MEMORY);
0235     }
0236 
0237     /*
0238      * For PCI_Config space access, we need the segment, bus, device and
0239      * function numbers. Acquire them here.
0240      *
0241      * Find the parent device object. (This allows the operation region to be
0242      * within a subscope under the device, such as a control method.)
0243      */
0244     pci_device_node = region_obj->region.node;
0245     while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) {
0246         pci_device_node = pci_device_node->parent;
0247     }
0248 
0249     if (!pci_device_node) {
0250         ACPI_FREE(pci_id);
0251         return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
0252     }
0253 
0254     /*
0255      * Get the PCI device and function numbers from the _ADR object
0256      * contained in the parent's scope.
0257      */
0258     status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
0259                          pci_device_node, &pci_value);
0260 
0261     /*
0262      * The default is zero, and since the allocation above zeroed the data,
0263      * just do nothing on failure.
0264      */
0265     if (ACPI_SUCCESS(status)) {
0266         pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value));
0267         pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value));
0268     }
0269 
0270     /* The PCI segment number comes from the _SEG method */
0271 
0272     status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG,
0273                          pci_root_node, &pci_value);
0274     if (ACPI_SUCCESS(status)) {
0275         pci_id->segment = ACPI_LOWORD(pci_value);
0276     }
0277 
0278     /* The PCI bus number comes from the _BBN method */
0279 
0280     status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN,
0281                          pci_root_node, &pci_value);
0282     if (ACPI_SUCCESS(status)) {
0283         pci_id->bus = ACPI_LOWORD(pci_value);
0284     }
0285 
0286     /* Complete/update the PCI ID for this device */
0287 
0288     status =
0289         acpi_hw_derive_pci_id(pci_id, pci_root_node,
0290                   region_obj->region.node);
0291     if (ACPI_FAILURE(status)) {
0292         ACPI_FREE(pci_id);
0293         return_ACPI_STATUS(status);
0294     }
0295 
0296     *region_context = pci_id;
0297     return_ACPI_STATUS(AE_OK);
0298 }
0299 
0300 /*******************************************************************************
0301  *
0302  * FUNCTION:    acpi_ev_is_pci_root_bridge
0303  *
0304  * PARAMETERS:  node            - Device node being examined
0305  *
0306  * RETURN:      TRUE if device is a PCI/PCI-Express Root Bridge
0307  *
0308  * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by
0309  *              examining the _HID and _CID for the device.
0310  *
0311  ******************************************************************************/
0312 
0313 u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
0314 {
0315     acpi_status status;
0316     struct acpi_pnp_device_id *hid;
0317     struct acpi_pnp_device_id_list *cid;
0318     u32 i;
0319     u8 match;
0320 
0321     /* Get the _HID and check for a PCI Root Bridge */
0322 
0323     status = acpi_ut_execute_HID(node, &hid);
0324     if (ACPI_FAILURE(status)) {
0325         return (FALSE);
0326     }
0327 
0328     match = acpi_ut_is_pci_root_bridge(hid->string);
0329     ACPI_FREE(hid);
0330 
0331     if (match) {
0332         return (TRUE);
0333     }
0334 
0335     /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */
0336 
0337     status = acpi_ut_execute_CID(node, &cid);
0338     if (ACPI_FAILURE(status)) {
0339         return (FALSE);
0340     }
0341 
0342     /* Check all _CIDs in the returned list */
0343 
0344     for (i = 0; i < cid->count; i++) {
0345         if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) {
0346             ACPI_FREE(cid);
0347             return (TRUE);
0348         }
0349     }
0350 
0351     ACPI_FREE(cid);
0352     return (FALSE);
0353 }
0354 
0355 /*******************************************************************************
0356  *
0357  * FUNCTION:    acpi_ev_pci_bar_region_setup
0358  *
0359  * PARAMETERS:  handle              - Region we are interested in
0360  *              function            - Start or stop
0361  *              handler_context     - Address space handler context
0362  *              region_context      - Region specific context
0363  *
0364  * RETURN:      Status
0365  *
0366  * DESCRIPTION: Setup a pci_BAR operation region
0367  *
0368  * MUTEX:       Assumes namespace is not locked
0369  *
0370  ******************************************************************************/
0371 
0372 acpi_status
0373 acpi_ev_pci_bar_region_setup(acpi_handle handle,
0374                  u32 function,
0375                  void *handler_context, void **region_context)
0376 {
0377     ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup);
0378 
0379     return_ACPI_STATUS(AE_OK);
0380 }
0381 
0382 /*******************************************************************************
0383  *
0384  * FUNCTION:    acpi_ev_cmos_region_setup
0385  *
0386  * PARAMETERS:  handle              - Region we are interested in
0387  *              function            - Start or stop
0388  *              handler_context     - Address space handler context
0389  *              region_context      - Region specific context
0390  *
0391  * RETURN:      Status
0392  *
0393  * DESCRIPTION: Setup a CMOS operation region
0394  *
0395  * MUTEX:       Assumes namespace is not locked
0396  *
0397  ******************************************************************************/
0398 
0399 acpi_status
0400 acpi_ev_cmos_region_setup(acpi_handle handle,
0401               u32 function,
0402               void *handler_context, void **region_context)
0403 {
0404     ACPI_FUNCTION_TRACE(ev_cmos_region_setup);
0405 
0406     return_ACPI_STATUS(AE_OK);
0407 }
0408 
0409 /*******************************************************************************
0410  *
0411  * FUNCTION:    acpi_ev_data_table_region_setup
0412  *
0413  * PARAMETERS:  handle              - Region we are interested in
0414  *              function            - Start or stop
0415  *              handler_context     - Address space handler context
0416  *              region_context      - Region specific context
0417  *
0418  * RETURN:      Status
0419  *
0420  * DESCRIPTION: Setup a data_table_region
0421  *
0422  * MUTEX:       Assumes namespace is not locked
0423  *
0424  ******************************************************************************/
0425 
0426 acpi_status
0427 acpi_ev_data_table_region_setup(acpi_handle handle,
0428                 u32 function,
0429                 void *handler_context, void **region_context)
0430 {
0431     union acpi_operand_object *region_desc =
0432         (union acpi_operand_object *)handle;
0433     struct acpi_data_table_space_context *local_region_context;
0434 
0435     ACPI_FUNCTION_TRACE(ev_data_table_region_setup);
0436 
0437     if (function == ACPI_REGION_DEACTIVATE) {
0438         if (*region_context) {
0439             ACPI_FREE(*region_context);
0440             *region_context = NULL;
0441         }
0442         return_ACPI_STATUS(AE_OK);
0443     }
0444 
0445     /* Create a new context */
0446 
0447     local_region_context =
0448         ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_data_table_space_context));
0449     if (!(local_region_context)) {
0450         return_ACPI_STATUS(AE_NO_MEMORY);
0451     }
0452 
0453     /* Save the data table pointer for use in the handler */
0454 
0455     local_region_context->pointer = region_desc->region.pointer;
0456 
0457     *region_context = local_region_context;
0458     return_ACPI_STATUS(AE_OK);
0459 }
0460 
0461 /*******************************************************************************
0462  *
0463  * FUNCTION:    acpi_ev_default_region_setup
0464  *
0465  * PARAMETERS:  handle              - Region we are interested in
0466  *              function            - Start or stop
0467  *              handler_context     - Address space handler context
0468  *              region_context      - Region specific context
0469  *
0470  * RETURN:      Status
0471  *
0472  * DESCRIPTION: Default region initialization
0473  *
0474  ******************************************************************************/
0475 
0476 acpi_status
0477 acpi_ev_default_region_setup(acpi_handle handle,
0478                  u32 function,
0479                  void *handler_context, void **region_context)
0480 {
0481     ACPI_FUNCTION_TRACE(ev_default_region_setup);
0482 
0483     if (function == ACPI_REGION_DEACTIVATE) {
0484         *region_context = NULL;
0485     } else {
0486         *region_context = handler_context;
0487     }
0488 
0489     return_ACPI_STATUS(AE_OK);
0490 }
0491 
0492 /*******************************************************************************
0493  *
0494  * FUNCTION:    acpi_ev_initialize_region
0495  *
0496  * PARAMETERS:  region_obj      - Region we are initializing
0497  *
0498  * RETURN:      Status
0499  *
0500  * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
0501  *              for execution at a later time
0502  *
0503  *              Get the appropriate address space handler for a newly
0504  *              created region.
0505  *
0506  *              This also performs address space specific initialization. For
0507  *              example, PCI regions must have an _ADR object that contains
0508  *              a PCI address in the scope of the definition. This address is
0509  *              required to perform an access to PCI config space.
0510  *
0511  * MUTEX:       Interpreter should be unlocked, because we may run the _REG
0512  *              method for this region.
0513  *
0514  * NOTE:        Possible incompliance:
0515  *              There is a behavior conflict in automatic _REG execution:
0516  *              1. When the interpreter is evaluating a method, we can only
0517  *                 automatically run _REG for the following case:
0518  *                   operation_region (OPR1, 0x80, 0x1000010, 0x4)
0519  *              2. When the interpreter is loading a table, we can also
0520  *                 automatically run _REG for the following case:
0521  *                   operation_region (OPR1, 0x80, 0x1000010, 0x4)
0522  *              Though this may not be compliant to the de-facto standard, the
0523  *              logic is kept in order not to trigger regressions. And keeping
0524  *              this logic should be taken care by the caller of this function.
0525  *
0526  ******************************************************************************/
0527 
0528 acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj)
0529 {
0530     union acpi_operand_object *handler_obj;
0531     union acpi_operand_object *obj_desc;
0532     acpi_adr_space_type space_id;
0533     struct acpi_namespace_node *node;
0534 
0535     ACPI_FUNCTION_TRACE(ev_initialize_region);
0536 
0537     if (!region_obj) {
0538         return_ACPI_STATUS(AE_BAD_PARAMETER);
0539     }
0540 
0541     if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) {
0542         return_ACPI_STATUS(AE_OK);
0543     }
0544 
0545     region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
0546 
0547     node = region_obj->region.node->parent;
0548     space_id = region_obj->region.space_id;
0549 
0550     /*
0551      * The following loop depends upon the root Node having no parent
0552      * ie: acpi_gbl_root_node->Parent being set to NULL
0553      */
0554     while (node) {
0555 
0556         /* Check to see if a handler exists */
0557 
0558         handler_obj = NULL;
0559         obj_desc = acpi_ns_get_attached_object(node);
0560         if (obj_desc) {
0561 
0562             /* Can only be a handler if the object exists */
0563 
0564             switch (node->type) {
0565             case ACPI_TYPE_DEVICE:
0566             case ACPI_TYPE_PROCESSOR:
0567             case ACPI_TYPE_THERMAL:
0568 
0569                 handler_obj = obj_desc->common_notify.handler;
0570                 break;
0571 
0572             default:
0573 
0574                 /* Ignore other objects */
0575 
0576                 break;
0577             }
0578 
0579             handler_obj =
0580                 acpi_ev_find_region_handler(space_id, handler_obj);
0581             if (handler_obj) {
0582 
0583                 /* Found correct handler */
0584 
0585                 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0586                           "Found handler %p for region %p in obj %p\n",
0587                           handler_obj, region_obj,
0588                           obj_desc));
0589 
0590                 (void)acpi_ev_attach_region(handler_obj,
0591                                 region_obj, FALSE);
0592 
0593                 /*
0594                  * Tell all users that this region is usable by
0595                  * running the _REG method
0596                  */
0597                 acpi_ex_exit_interpreter();
0598                 (void)acpi_ev_execute_reg_method(region_obj,
0599                                  ACPI_REG_CONNECT);
0600                 acpi_ex_enter_interpreter();
0601                 return_ACPI_STATUS(AE_OK);
0602             }
0603         }
0604 
0605         /* This node does not have the handler we need; Pop up one level */
0606 
0607         node = node->parent;
0608     }
0609 
0610     /*
0611      * If we get here, there is no handler for this region. This is not
0612      * fatal because many regions get created before a handler is installed
0613      * for said region.
0614      */
0615     ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
0616               "No handler for RegionType %s(%X) (RegionObj %p)\n",
0617               acpi_ut_get_region_name(space_id), space_id,
0618               region_obj));
0619 
0620     return_ACPI_STATUS(AE_OK);
0621 }