LCOV - code coverage report
Current view: top level - drivers/acpi/acpica - evregion.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 137 239 57.3 %
Date: 2022-04-01 14:58:12 Functions: 7 8 87.5 %
Branches: 44 120 36.7 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
       2                 :            : /******************************************************************************
       3                 :            :  *
       4                 :            :  * Module Name: evregion - Operation Region support
       5                 :            :  *
       6                 :            :  * Copyright (C) 2000 - 2020, 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_EVENTS
      17                 :            : ACPI_MODULE_NAME("evregion")
      18                 :            : 
      19                 :            : extern u8 acpi_gbl_default_address_spaces[];
      20                 :            : 
      21                 :            : /* Local prototypes */
      22                 :            : 
      23                 :            : static void
      24                 :            : acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node);
      25                 :            : 
      26                 :            : static acpi_status
      27                 :            : acpi_ev_reg_run(acpi_handle obj_handle,
      28                 :            :                 u32 level, void *context, void **return_value);
      29                 :            : 
      30                 :            : /*******************************************************************************
      31                 :            :  *
      32                 :            :  * FUNCTION:    acpi_ev_initialize_op_regions
      33                 :            :  *
      34                 :            :  * PARAMETERS:  None
      35                 :            :  *
      36                 :            :  * RETURN:      Status
      37                 :            :  *
      38                 :            :  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
      39                 :            :  *              an installed default region handler.
      40                 :            :  *
      41                 :            :  ******************************************************************************/
      42                 :            : 
      43                 :          3 : acpi_status acpi_ev_initialize_op_regions(void)
      44                 :            : {
      45                 :          3 :         acpi_status status;
      46                 :          3 :         u32 i;
      47                 :            : 
      48                 :          3 :         ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
      49                 :            : 
      50                 :          3 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
      51         [ +  - ]:          3 :         if (ACPI_FAILURE(status)) {
      52                 :            :                 return_ACPI_STATUS(status);
      53                 :            :         }
      54                 :            : 
      55                 :            :         /* Run the _REG methods for op_regions in each default address space */
      56                 :            : 
      57         [ +  + ]:         15 :         for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
      58                 :            :                 /*
      59                 :            :                  * Make sure the installed handler is the DEFAULT handler. If not the
      60                 :            :                  * default, the _REG methods will have already been run (when the
      61                 :            :                  * handler was installed)
      62                 :            :                  */
      63         [ +  - ]:         12 :                 if (acpi_ev_has_default_handler(acpi_gbl_root_node,
      64                 :            :                                                 acpi_gbl_default_address_spaces
      65                 :         12 :                                                 [i])) {
      66                 :         12 :                         acpi_ev_execute_reg_methods(acpi_gbl_root_node,
      67                 :            :                                                     acpi_gbl_default_address_spaces
      68                 :         12 :                                                     [i], ACPI_REG_CONNECT);
      69                 :            :                 }
      70                 :            :         }
      71                 :            : 
      72                 :          3 :         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
      73                 :          3 :         return_ACPI_STATUS(status);
      74                 :            : }
      75                 :            : 
      76                 :            : /*******************************************************************************
      77                 :            :  *
      78                 :            :  * FUNCTION:    acpi_ev_address_space_dispatch
      79                 :            :  *
      80                 :            :  * PARAMETERS:  region_obj          - Internal region object
      81                 :            :  *              field_obj           - Corresponding field. Can be NULL.
      82                 :            :  *              function            - Read or Write operation
      83                 :            :  *              region_offset       - Where in the region to read or write
      84                 :            :  *              bit_width           - Field width in bits (8, 16, 32, or 64)
      85                 :            :  *              value               - Pointer to in or out value, must be
      86                 :            :  *                                    a full 64-bit integer
      87                 :            :  *
      88                 :            :  * RETURN:      Status
      89                 :            :  *
      90                 :            :  * DESCRIPTION: Dispatch an address space or operation region access to
      91                 :            :  *              a previously installed handler.
      92                 :            :  *
      93                 :            :  * NOTE: During early initialization, we always install the default region
      94                 :            :  * handlers for Memory, I/O and PCI_Config. This ensures that these operation
      95                 :            :  * region address spaces are always available as per the ACPI specification.
      96                 :            :  * This is especially needed in order to support the execution of
      97                 :            :  * module-level AML code during loading of the ACPI tables.
      98                 :            :  *
      99                 :            :  ******************************************************************************/
     100                 :            : 
     101                 :            : acpi_status
     102                 :        180 : acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
     103                 :            :                                union acpi_operand_object *field_obj,
     104                 :            :                                u32 function,
     105                 :            :                                u32 region_offset, u32 bit_width, u64 *value)
     106                 :            : {
     107                 :        180 :         acpi_status status;
     108                 :        180 :         acpi_adr_space_handler handler;
     109                 :        180 :         acpi_adr_space_setup region_setup;
     110                 :        180 :         union acpi_operand_object *handler_desc;
     111                 :        180 :         union acpi_operand_object *region_obj2;
     112                 :        180 :         void *region_context = NULL;
     113                 :        180 :         struct acpi_connection_info *context;
     114                 :        180 :         acpi_physical_address address;
     115                 :            : 
     116                 :        180 :         ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
     117                 :            : 
     118                 :        180 :         region_obj2 = acpi_ns_get_secondary_object(region_obj);
     119         [ +  - ]:        180 :         if (!region_obj2) {
     120                 :            :                 return_ACPI_STATUS(AE_NOT_EXIST);
     121                 :            :         }
     122                 :            : 
     123                 :            :         /* Ensure that there is a handler associated with this region */
     124                 :            : 
     125                 :        180 :         handler_desc = region_obj->region.handler;
     126         [ -  + ]:        180 :         if (!handler_desc) {
     127                 :          0 :                 ACPI_ERROR((AE_INFO,
     128                 :            :                             "No handler for Region [%4.4s] (%p) [%s]",
     129                 :            :                             acpi_ut_get_node_name(region_obj->region.node),
     130                 :            :                             region_obj,
     131                 :            :                             acpi_ut_get_region_name(region_obj->region.
     132                 :            :                                                     space_id)));
     133                 :            : 
     134                 :          0 :                 return_ACPI_STATUS(AE_NOT_EXIST);
     135                 :            :         }
     136                 :            : 
     137                 :        180 :         context = handler_desc->address_space.context;
     138                 :            : 
     139                 :            :         /*
     140                 :            :          * It may be the case that the region has never been initialized.
     141                 :            :          * Some types of regions require special init code
     142                 :            :          */
     143         [ +  + ]:        180 :         if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
     144                 :            : 
     145                 :            :                 /* This region has not been initialized yet, do it */
     146                 :            : 
     147                 :         12 :                 region_setup = handler_desc->address_space.setup;
     148         [ -  + ]:         12 :                 if (!region_setup) {
     149                 :            : 
     150                 :            :                         /* No initialization routine, exit with error */
     151                 :            : 
     152                 :          0 :                         ACPI_ERROR((AE_INFO,
     153                 :            :                                     "No init routine for region(%p) [%s]",
     154                 :            :                                     region_obj,
     155                 :            :                                     acpi_ut_get_region_name(region_obj->region.
     156                 :            :                                                             space_id)));
     157                 :          0 :                         return_ACPI_STATUS(AE_NOT_EXIST);
     158                 :            :                 }
     159                 :            : 
     160                 :            :                 /*
     161                 :            :                  * We must exit the interpreter because the region setup will
     162                 :            :                  * potentially execute control methods (for example, the _REG method
     163                 :            :                  * for this region)
     164                 :            :                  */
     165                 :         12 :                 acpi_ex_exit_interpreter();
     166                 :            : 
     167                 :         12 :                 status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
     168                 :            :                                       context, &region_context);
     169                 :            : 
     170                 :            :                 /* Re-enter the interpreter */
     171                 :            : 
     172                 :         12 :                 acpi_ex_enter_interpreter();
     173                 :            : 
     174                 :            :                 /* Check for failure of the Region Setup */
     175                 :            : 
     176         [ -  + ]:         12 :                 if (ACPI_FAILURE(status)) {
     177                 :          0 :                         ACPI_EXCEPTION((AE_INFO, status,
     178                 :            :                                         "During region initialization: [%s]",
     179                 :            :                                         acpi_ut_get_region_name(region_obj->
     180                 :            :                                                                 region.
     181                 :            :                                                                 space_id)));
     182                 :          0 :                         return_ACPI_STATUS(status);
     183                 :            :                 }
     184                 :            : 
     185                 :            :                 /* Region initialization may have been completed by region_setup */
     186                 :            : 
     187         [ +  - ]:         12 :                 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
     188                 :         12 :                         region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
     189                 :            : 
     190                 :            :                         /*
     191                 :            :                          * Save the returned context for use in all accesses to
     192                 :            :                          * the handler for this particular region
     193                 :            :                          */
     194         [ +  - ]:         12 :                         if (!(region_obj2->extra.region_context)) {
     195                 :         12 :                                 region_obj2->extra.region_context =
     196                 :            :                                     region_context;
     197                 :            :                         }
     198                 :            :                 }
     199                 :            :         }
     200                 :            : 
     201                 :            :         /* We have everything we need, we can invoke the address space handler */
     202                 :            : 
     203                 :        180 :         handler = handler_desc->address_space.handler;
     204                 :        180 :         address = (region_obj->region.address + region_offset);
     205                 :            : 
     206                 :            :         /*
     207                 :            :          * Special handling for generic_serial_bus and general_purpose_io:
     208                 :            :          * There are three extra parameters that must be passed to the
     209                 :            :          * handler via the context:
     210                 :            :          *   1) Connection buffer, a resource template from Connection() op
     211                 :            :          *   2) Length of the above buffer
     212                 :            :          *   3) Actual access length from the access_as() op
     213                 :            :          *
     214                 :            :          * In addition, for general_purpose_io, the Address and bit_width fields
     215                 :            :          * are defined as follows:
     216                 :            :          *   1) Address is the pin number index of the field (bit offset from
     217                 :            :          *      the previous Connection)
     218                 :            :          *   2) bit_width is the actual bit length of the field (number of pins)
     219                 :            :          */
     220         [ -  + ]:        180 :         if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
     221         [ #  # ]:          0 :             context && field_obj) {
     222                 :            : 
     223                 :            :                 /* Get the Connection (resource_template) buffer */
     224                 :            : 
     225                 :          0 :                 context->connection = field_obj->field.resource_buffer;
     226                 :          0 :                 context->length = field_obj->field.resource_length;
     227                 :          0 :                 context->access_length = field_obj->field.access_length;
     228                 :            :         }
     229         [ -  + ]:        180 :         if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
     230         [ #  # ]:          0 :             context && field_obj) {
     231                 :            : 
     232                 :            :                 /* Get the Connection (resource_template) buffer */
     233                 :            : 
     234                 :          0 :                 context->connection = field_obj->field.resource_buffer;
     235                 :          0 :                 context->length = field_obj->field.resource_length;
     236                 :          0 :                 context->access_length = field_obj->field.access_length;
     237                 :          0 :                 address = field_obj->field.pin_number_index;
     238                 :          0 :                 bit_width = field_obj->field.bit_length;
     239                 :            :         }
     240                 :            : 
     241                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
     242                 :            :                           "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
     243                 :            :                           &region_obj->region.handler->address_space, handler,
     244                 :            :                           ACPI_FORMAT_UINT64(address),
     245                 :            :                           acpi_ut_get_region_name(region_obj->region.
     246                 :        180 :                                                   space_id)));
     247                 :            : 
     248         [ -  + ]:        180 :         if (!(handler_desc->address_space.handler_flags &
     249                 :            :               ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
     250                 :            :                 /*
     251                 :            :                  * For handlers other than the default (supplied) handlers, we must
     252                 :            :                  * exit the interpreter because the handler *might* block -- we don't
     253                 :            :                  * know what it will do, so we can't hold the lock on the interpreter.
     254                 :            :                  */
     255                 :          0 :                 acpi_ex_exit_interpreter();
     256                 :            :         }
     257                 :            : 
     258                 :            :         /* Call the handler */
     259                 :            : 
     260                 :        180 :         status = handler(function, address, bit_width, value, context,
     261                 :            :                          region_obj2->extra.region_context);
     262                 :            : 
     263         [ -  + ]:        180 :         if (ACPI_FAILURE(status)) {
     264                 :          0 :                 ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
     265                 :            :                                 acpi_ut_get_region_name(region_obj->region.
     266                 :            :                                                         space_id)));
     267                 :            : 
     268                 :            :                 /*
     269                 :            :                  * Special case for an EC timeout. These are seen so frequently
     270                 :            :                  * that an additional error message is helpful
     271                 :            :                  */
     272   [ #  #  #  # ]:          0 :                 if ((region_obj->region.space_id == ACPI_ADR_SPACE_EC) &&
     273                 :            :                     (status == AE_TIME)) {
     274                 :          0 :                         ACPI_ERROR((AE_INFO,
     275                 :            :                                     "Timeout from EC hardware or EC device driver"));
     276                 :            :                 }
     277                 :            :         }
     278                 :            : 
     279         [ -  + ]:        180 :         if (!(handler_desc->address_space.handler_flags &
     280                 :            :               ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
     281                 :            :                 /*
     282                 :            :                  * We just returned from a non-default handler, we must re-enter the
     283                 :            :                  * interpreter
     284                 :            :                  */
     285                 :          0 :                 acpi_ex_enter_interpreter();
     286                 :            :         }
     287                 :            : 
     288                 :            :         return_ACPI_STATUS(status);
     289                 :            : }
     290                 :            : 
     291                 :            : /*******************************************************************************
     292                 :            :  *
     293                 :            :  * FUNCTION:    acpi_ev_detach_region
     294                 :            :  *
     295                 :            :  * PARAMETERS:  region_obj          - Region Object
     296                 :            :  *              acpi_ns_is_locked   - Namespace Region Already Locked?
     297                 :            :  *
     298                 :            :  * RETURN:      None
     299                 :            :  *
     300                 :            :  * DESCRIPTION: Break the association between the handler and the region
     301                 :            :  *              this is a two way association.
     302                 :            :  *
     303                 :            :  ******************************************************************************/
     304                 :            : 
     305                 :            : void
     306                 :          6 : acpi_ev_detach_region(union acpi_operand_object *region_obj,
     307                 :            :                       u8 acpi_ns_is_locked)
     308                 :            : {
     309                 :          6 :         union acpi_operand_object *handler_obj;
     310                 :          6 :         union acpi_operand_object *obj_desc;
     311                 :          6 :         union acpi_operand_object *start_desc;
     312                 :          6 :         union acpi_operand_object **last_obj_ptr;
     313                 :          6 :         acpi_adr_space_setup region_setup;
     314                 :          6 :         void **region_context;
     315                 :          6 :         union acpi_operand_object *region_obj2;
     316                 :          6 :         acpi_status status;
     317                 :            : 
     318                 :          6 :         ACPI_FUNCTION_TRACE(ev_detach_region);
     319                 :            : 
     320                 :          6 :         region_obj2 = acpi_ns_get_secondary_object(region_obj);
     321         [ +  - ]:          6 :         if (!region_obj2) {
     322                 :            :                 return_VOID;
     323                 :            :         }
     324                 :          6 :         region_context = &region_obj2->extra.region_context;
     325                 :            : 
     326                 :            :         /* Get the address handler from the region object */
     327                 :            : 
     328                 :          6 :         handler_obj = region_obj->region.handler;
     329         [ +  - ]:          6 :         if (!handler_obj) {
     330                 :            : 
     331                 :            :                 /* This region has no handler, all done */
     332                 :            : 
     333                 :            :                 return_VOID;
     334                 :            :         }
     335                 :            : 
     336                 :            :         /* Find this region in the handler's list */
     337                 :            : 
     338                 :          6 :         obj_desc = handler_obj->address_space.region_list;
     339                 :          6 :         start_desc = obj_desc;
     340                 :          6 :         last_obj_ptr = &handler_obj->address_space.region_list;
     341                 :            : 
     342         [ +  - ]:          9 :         while (obj_desc) {
     343                 :            : 
     344                 :            :                 /* Is this the correct Region? */
     345                 :            : 
     346         [ +  + ]:          9 :                 if (obj_desc == region_obj) {
     347                 :            :                         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
     348                 :            :                                           "Removing Region %p from address handler %p\n",
     349                 :          6 :                                           region_obj, handler_obj));
     350                 :            : 
     351                 :            :                         /* This is it, remove it from the handler's list */
     352                 :            : 
     353                 :          6 :                         *last_obj_ptr = obj_desc->region.next;
     354                 :          6 :                         obj_desc->region.next = NULL;        /* Must clear field */
     355                 :            : 
     356         [ -  + ]:          6 :                         if (acpi_ns_is_locked) {
     357                 :          0 :                                 status =
     358                 :          0 :                                     acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     359         [ #  # ]:          0 :                                 if (ACPI_FAILURE(status)) {
     360                 :            :                                         return_VOID;
     361                 :            :                                 }
     362                 :            :                         }
     363                 :            : 
     364                 :            :                         /* Now stop region accesses by executing the _REG method */
     365                 :            : 
     366                 :          6 :                         status =
     367                 :          6 :                             acpi_ev_execute_reg_method(region_obj,
     368                 :            :                                                        ACPI_REG_DISCONNECT);
     369         [ -  + ]:          6 :                         if (ACPI_FAILURE(status)) {
     370                 :          0 :                                 ACPI_EXCEPTION((AE_INFO, status,
     371                 :            :                                                 "from region _REG, [%s]",
     372                 :            :                                                 acpi_ut_get_region_name
     373                 :            :                                                 (region_obj->region.space_id)));
     374                 :            :                         }
     375                 :            : 
     376         [ -  + ]:          6 :                         if (acpi_ns_is_locked) {
     377                 :          0 :                                 status =
     378                 :          0 :                                     acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     379         [ #  # ]:          0 :                                 if (ACPI_FAILURE(status)) {
     380                 :            :                                         return_VOID;
     381                 :            :                                 }
     382                 :            :                         }
     383                 :            : 
     384                 :            :                         /*
     385                 :            :                          * If the region has been activated, call the setup handler with
     386                 :            :                          * the deactivate notification
     387                 :            :                          */
     388         [ -  + ]:          6 :                         if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
     389                 :          0 :                                 region_setup = handler_obj->address_space.setup;
     390                 :          0 :                                 status =
     391                 :          0 :                                     region_setup(region_obj,
     392                 :            :                                                  ACPI_REGION_DEACTIVATE,
     393                 :            :                                                  handler_obj->address_space.
     394                 :            :                                                  context, region_context);
     395                 :            : 
     396                 :            :                                 /*
     397                 :            :                                  * region_context should have been released by the deactivate
     398                 :            :                                  * operation. We don't need access to it anymore here.
     399                 :            :                                  */
     400         [ #  # ]:          0 :                                 if (region_context) {
     401                 :          0 :                                         *region_context = NULL;
     402                 :            :                                 }
     403                 :            : 
     404                 :            :                                 /* Init routine may fail, Just ignore errors */
     405                 :            : 
     406         [ #  # ]:          0 :                                 if (ACPI_FAILURE(status)) {
     407                 :          0 :                                         ACPI_EXCEPTION((AE_INFO, status,
     408                 :            :                                                         "from region handler - deactivate, [%s]",
     409                 :            :                                                         acpi_ut_get_region_name
     410                 :            :                                                         (region_obj->region.
     411                 :            :                                                          space_id)));
     412                 :            :                                 }
     413                 :            : 
     414                 :          0 :                                 region_obj->region.flags &=
     415                 :            :                                     ~(AOPOBJ_SETUP_COMPLETE);
     416                 :            :                         }
     417                 :            : 
     418                 :            :                         /*
     419                 :            :                          * Remove handler reference in the region
     420                 :            :                          *
     421                 :            :                          * NOTE: this doesn't mean that the region goes away, the region
     422                 :            :                          * is just inaccessible as indicated to the _REG method
     423                 :            :                          *
     424                 :            :                          * If the region is on the handler's list, this must be the
     425                 :            :                          * region's handler
     426                 :            :                          */
     427                 :          6 :                         region_obj->region.handler = NULL;
     428                 :          6 :                         acpi_ut_remove_reference(handler_obj);
     429                 :            : 
     430                 :          6 :                         return_VOID;
     431                 :            :                 }
     432                 :            : 
     433                 :            :                 /* Walk the linked list of handlers */
     434                 :            : 
     435                 :          3 :                 last_obj_ptr = &obj_desc->region.next;
     436                 :          3 :                 obj_desc = obj_desc->region.next;
     437                 :            : 
     438                 :            :                 /* Prevent infinite loop if list is corrupted */
     439                 :            : 
     440         [ -  + ]:          3 :                 if (obj_desc == start_desc) {
     441                 :          0 :                         ACPI_ERROR((AE_INFO,
     442                 :            :                                     "Circular handler list in region object %p",
     443                 :            :                                     region_obj));
     444                 :          0 :                         return_VOID;
     445                 :            :                 }
     446                 :            :         }
     447                 :            : 
     448                 :            :         /* If we get here, the region was not in the handler's region list */
     449                 :            : 
     450                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
     451                 :            :                           "Cannot remove region %p from address handler %p\n",
     452                 :            :                           region_obj, handler_obj));
     453                 :            : 
     454                 :            :         return_VOID;
     455                 :            : }
     456                 :            : 
     457                 :            : /*******************************************************************************
     458                 :            :  *
     459                 :            :  * FUNCTION:    acpi_ev_attach_region
     460                 :            :  *
     461                 :            :  * PARAMETERS:  handler_obj         - Handler Object
     462                 :            :  *              region_obj          - Region Object
     463                 :            :  *              acpi_ns_is_locked   - Namespace Region Already Locked?
     464                 :            :  *
     465                 :            :  * RETURN:      None
     466                 :            :  *
     467                 :            :  * DESCRIPTION: Create the association between the handler and the region
     468                 :            :  *              this is a two way association.
     469                 :            :  *
     470                 :            :  ******************************************************************************/
     471                 :            : 
     472                 :            : acpi_status
     473                 :         30 : acpi_ev_attach_region(union acpi_operand_object *handler_obj,
     474                 :            :                       union acpi_operand_object *region_obj,
     475                 :            :                       u8 acpi_ns_is_locked)
     476                 :            : {
     477                 :            : 
     478                 :         30 :         ACPI_FUNCTION_TRACE(ev_attach_region);
     479                 :            : 
     480                 :            :         /* Install the region's handler */
     481                 :            : 
     482         [ +  - ]:         30 :         if (region_obj->region.handler) {
     483                 :            :                 return_ACPI_STATUS(AE_ALREADY_EXISTS);
     484                 :            :         }
     485                 :            : 
     486                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
     487                 :            :                           "Adding Region [%4.4s] %p to address handler %p [%s]\n",
     488                 :            :                           acpi_ut_get_node_name(region_obj->region.node),
     489                 :            :                           region_obj, handler_obj,
     490                 :            :                           acpi_ut_get_region_name(region_obj->region.
     491                 :         30 :                                                   space_id)));
     492                 :            : 
     493                 :            :         /* Link this region to the front of the handler's list */
     494                 :            : 
     495                 :         30 :         region_obj->region.next = handler_obj->address_space.region_list;
     496                 :         30 :         handler_obj->address_space.region_list = region_obj;
     497                 :         30 :         region_obj->region.handler = handler_obj;
     498                 :         30 :         acpi_ut_add_reference(handler_obj);
     499                 :            : 
     500                 :         30 :         return_ACPI_STATUS(AE_OK);
     501                 :            : }
     502                 :            : 
     503                 :            : /*******************************************************************************
     504                 :            :  *
     505                 :            :  * FUNCTION:    acpi_ev_execute_reg_method
     506                 :            :  *
     507                 :            :  * PARAMETERS:  region_obj          - Region object
     508                 :            :  *              function            - Passed to _REG: On (1) or Off (0)
     509                 :            :  *
     510                 :            :  * RETURN:      Status
     511                 :            :  *
     512                 :            :  * DESCRIPTION: Execute _REG method for a region
     513                 :            :  *
     514                 :            :  ******************************************************************************/
     515                 :            : 
     516                 :            : acpi_status
     517                 :         42 : acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
     518                 :            : {
     519                 :         42 :         struct acpi_evaluate_info *info;
     520                 :         42 :         union acpi_operand_object *args[3];
     521                 :         42 :         union acpi_operand_object *region_obj2;
     522                 :         42 :         const acpi_name *reg_name_ptr =
     523                 :            :             ACPI_CAST_PTR(acpi_name, METHOD_NAME__REG);
     524                 :         42 :         struct acpi_namespace_node *method_node;
     525                 :         42 :         struct acpi_namespace_node *node;
     526                 :         42 :         acpi_status status;
     527                 :            : 
     528                 :         42 :         ACPI_FUNCTION_TRACE(ev_execute_reg_method);
     529                 :            : 
     530         [ +  + ]:         42 :         if (!acpi_gbl_namespace_initialized ||
     531         [ +  - ]:         18 :             region_obj->region.handler == NULL) {
     532                 :            :                 return_ACPI_STATUS(AE_OK);
     533                 :            :         }
     534                 :            : 
     535                 :         18 :         region_obj2 = acpi_ns_get_secondary_object(region_obj);
     536         [ +  - ]:         18 :         if (!region_obj2) {
     537                 :            :                 return_ACPI_STATUS(AE_NOT_EXIST);
     538                 :            :         }
     539                 :            : 
     540                 :            :         /*
     541                 :            :          * Find any "_REG" method associated with this region definition.
     542                 :            :          * The method should always be updated as this function may be
     543                 :            :          * invoked after a namespace change.
     544                 :            :          */
     545                 :         18 :         node = region_obj->region.node->parent;
     546                 :         18 :         status =
     547                 :         18 :             acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
     548                 :            :                                      &method_node);
     549         [ -  + ]:         18 :         if (ACPI_SUCCESS(status)) {
     550                 :            :                 /*
     551                 :            :                  * The _REG method is optional and there can be only one per
     552                 :            :                  * region definition. This will be executed when the handler is
     553                 :            :                  * attached or removed.
     554                 :            :                  */
     555                 :          0 :                 region_obj2->extra.method_REG = method_node;
     556                 :            :         }
     557         [ -  + ]:         18 :         if (region_obj2->extra.method_REG == NULL) {
     558                 :            :                 return_ACPI_STATUS(AE_OK);
     559                 :            :         }
     560                 :            : 
     561                 :            :         /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */
     562                 :            : 
     563         [ #  # ]:          0 :         if ((function == ACPI_REG_CONNECT &&
     564   [ #  #  #  # ]:          0 :              region_obj->common.flags & AOPOBJ_REG_CONNECTED) ||
     565                 :          0 :             (function == ACPI_REG_DISCONNECT &&
     566         [ #  # ]:          0 :              !(region_obj->common.flags & AOPOBJ_REG_CONNECTED))) {
     567                 :            :                 return_ACPI_STATUS(AE_OK);
     568                 :            :         }
     569                 :            : 
     570                 :            :         /* Allocate and initialize the evaluation information block */
     571                 :            : 
     572                 :          0 :         info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
     573         [ #  # ]:          0 :         if (!info) {
     574                 :            :                 return_ACPI_STATUS(AE_NO_MEMORY);
     575                 :            :         }
     576                 :            : 
     577                 :          0 :         info->prefix_node = region_obj2->extra.method_REG;
     578                 :          0 :         info->relative_pathname = NULL;
     579                 :          0 :         info->parameters = args;
     580                 :          0 :         info->flags = ACPI_IGNORE_RETURN_VALUE;
     581                 :            : 
     582                 :            :         /*
     583                 :            :          * The _REG method has two arguments:
     584                 :            :          *
     585                 :            :          * arg0 - Integer:
     586                 :            :          *  Operation region space ID Same value as region_obj->Region.space_id
     587                 :            :          *
     588                 :            :          * arg1 - Integer:
     589                 :            :          *  connection status 1 for connecting the handler, 0 for disconnecting
     590                 :            :          *  the handler (Passed as a parameter)
     591                 :            :          */
     592                 :          0 :         args[0] =
     593                 :          0 :             acpi_ut_create_integer_object((u64)region_obj->region.space_id);
     594         [ #  # ]:          0 :         if (!args[0]) {
     595                 :          0 :                 status = AE_NO_MEMORY;
     596                 :          0 :                 goto cleanup1;
     597                 :            :         }
     598                 :            : 
     599                 :          0 :         args[1] = acpi_ut_create_integer_object((u64)function);
     600         [ #  # ]:          0 :         if (!args[1]) {
     601                 :          0 :                 status = AE_NO_MEMORY;
     602                 :          0 :                 goto cleanup2;
     603                 :            :         }
     604                 :            : 
     605                 :          0 :         args[2] = NULL;         /* Terminate list */
     606                 :            : 
     607                 :            :         /* Execute the method, no return value */
     608                 :            : 
     609                 :            :         ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
     610                 :          0 :                         (ACPI_TYPE_METHOD, info->prefix_node, NULL));
     611                 :            : 
     612                 :          0 :         status = acpi_ns_evaluate(info);
     613                 :          0 :         acpi_ut_remove_reference(args[1]);
     614                 :            : 
     615         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {
     616                 :          0 :                 goto cleanup2;
     617                 :            :         }
     618                 :            : 
     619         [ #  # ]:          0 :         if (function == ACPI_REG_CONNECT) {
     620                 :          0 :                 region_obj->common.flags |= AOPOBJ_REG_CONNECTED;
     621                 :            :         } else {
     622                 :          0 :                 region_obj->common.flags &= ~AOPOBJ_REG_CONNECTED;
     623                 :            :         }
     624                 :            : 
     625                 :          0 : cleanup2:
     626                 :          0 :         acpi_ut_remove_reference(args[0]);
     627                 :            : 
     628                 :          0 : cleanup1:
     629                 :          0 :         ACPI_FREE(info);
     630                 :          0 :         return_ACPI_STATUS(status);
     631                 :            : }
     632                 :            : 
     633                 :            : /*******************************************************************************
     634                 :            :  *
     635                 :            :  * FUNCTION:    acpi_ev_execute_reg_methods
     636                 :            :  *
     637                 :            :  * PARAMETERS:  node            - Namespace node for the device
     638                 :            :  *              space_id        - The address space ID
     639                 :            :  *              function        - Passed to _REG: On (1) or Off (0)
     640                 :            :  *
     641                 :            :  * RETURN:      None
     642                 :            :  *
     643                 :            :  * DESCRIPTION: Run all _REG methods for the input Space ID;
     644                 :            :  *              Note: assumes namespace is locked, or system init time.
     645                 :            :  *
     646                 :            :  ******************************************************************************/
     647                 :            : 
     648                 :            : void
     649                 :         18 : acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
     650                 :            :                             acpi_adr_space_type space_id, u32 function)
     651                 :            : {
     652                 :         18 :         struct acpi_reg_walk_info info;
     653                 :            : 
     654                 :         18 :         ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
     655                 :            : 
     656                 :            :         /*
     657                 :            :          * These address spaces do not need a call to _REG, since the ACPI
     658                 :            :          * specification defines them as: "must always be accessible". Since
     659                 :            :          * they never change state (never become unavailable), no need to ever
     660                 :            :          * call _REG on them. Also, a data_table is not a "real" address space,
     661                 :            :          * so do not call _REG. September 2018.
     662                 :            :          */
     663                 :         18 :         if ((space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
     664                 :         18 :             (space_id == ACPI_ADR_SPACE_SYSTEM_IO) ||
     665         [ +  + ]:         18 :             (space_id == ACPI_ADR_SPACE_DATA_TABLE)) {
     666                 :            :                 return_VOID;
     667                 :            :         }
     668                 :            : 
     669                 :          9 :         info.space_id = space_id;
     670                 :          9 :         info.function = function;
     671                 :          9 :         info.reg_run_count = 0;
     672                 :            : 
     673                 :            :         ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
     674                 :            :                               "    Running _REG methods for SpaceId %s\n",
     675                 :          9 :                               acpi_ut_get_region_name(info.space_id)));
     676                 :            : 
     677                 :            :         /*
     678                 :            :          * Run all _REG methods for all Operation Regions for this space ID. This
     679                 :            :          * is a separate walk in order to handle any interdependencies between
     680                 :            :          * regions and _REG methods. (i.e. handlers must be installed for all
     681                 :            :          * regions of this Space ID before we can run any _REG methods)
     682                 :            :          */
     683                 :          9 :         (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
     684                 :            :                                      ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, NULL,
     685                 :            :                                      &info, NULL);
     686                 :            : 
     687                 :            :         /* Special case for EC: handle "orphan" _REG methods with no region */
     688                 :            : 
     689         [ -  + ]:          9 :         if (space_id == ACPI_ADR_SPACE_EC) {
     690                 :          0 :                 acpi_ev_orphan_ec_reg_method(node);
     691                 :            :         }
     692                 :            : 
     693                 :            :         ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
     694                 :            :                               "    Executed %u _REG methods for SpaceId %s\n",
     695                 :            :                               info.reg_run_count,
     696                 :            :                               acpi_ut_get_region_name(info.space_id)));
     697                 :            : 
     698                 :            :         return_VOID;
     699                 :            : }
     700                 :            : 
     701                 :            : /*******************************************************************************
     702                 :            :  *
     703                 :            :  * FUNCTION:    acpi_ev_reg_run
     704                 :            :  *
     705                 :            :  * PARAMETERS:  walk_namespace callback
     706                 :            :  *
     707                 :            :  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
     708                 :            :  *
     709                 :            :  ******************************************************************************/
     710                 :            : 
     711                 :            : static acpi_status
     712                 :       1518 : acpi_ev_reg_run(acpi_handle obj_handle,
     713                 :            :                 u32 level, void *context, void **return_value)
     714                 :            : {
     715                 :       1518 :         union acpi_operand_object *obj_desc;
     716                 :       1518 :         struct acpi_namespace_node *node;
     717                 :       1518 :         acpi_status status;
     718                 :       1518 :         struct acpi_reg_walk_info *info;
     719                 :            : 
     720                 :       1518 :         info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context);
     721                 :            : 
     722                 :            :         /* Convert and validate the device handle */
     723                 :            : 
     724                 :       1518 :         node = acpi_ns_validate_handle(obj_handle);
     725         [ +  - ]:       1518 :         if (!node) {
     726                 :            :                 return (AE_BAD_PARAMETER);
     727                 :            :         }
     728                 :            : 
     729                 :            :         /*
     730                 :            :          * We only care about regions and objects that are allowed to have
     731                 :            :          * address space handlers
     732                 :            :          */
     733   [ +  +  -  + ]:       1518 :         if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
     734                 :            :                 return (AE_OK);
     735                 :            :         }
     736                 :            : 
     737                 :            :         /* Check for an existing internal object */
     738                 :            : 
     739                 :         42 :         obj_desc = acpi_ns_get_attached_object(node);
     740         [ +  - ]:         42 :         if (!obj_desc) {
     741                 :            : 
     742                 :            :                 /* No object, just exit */
     743                 :            : 
     744                 :            :                 return (AE_OK);
     745                 :            :         }
     746                 :            : 
     747                 :            :         /* Object is a Region */
     748                 :            : 
     749         [ +  + ]:         42 :         if (obj_desc->region.space_id != info->space_id) {
     750                 :            : 
     751                 :            :                 /* This region is for a different address space, just ignore it */
     752                 :            : 
     753                 :            :                 return (AE_OK);
     754                 :            :         }
     755                 :            : 
     756                 :         12 :         info->reg_run_count++;
     757                 :         12 :         status = acpi_ev_execute_reg_method(obj_desc, info->function);
     758                 :         12 :         return (status);
     759                 :            : }
     760                 :            : 
     761                 :            : /*******************************************************************************
     762                 :            :  *
     763                 :            :  * FUNCTION:    acpi_ev_orphan_ec_reg_method
     764                 :            :  *
     765                 :            :  * PARAMETERS:  ec_device_node      - Namespace node for an EC device
     766                 :            :  *
     767                 :            :  * RETURN:      None
     768                 :            :  *
     769                 :            :  * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
     770                 :            :  *              device. This is a _REG method that has no corresponding region
     771                 :            :  *              within the EC device scope. The orphan _REG method appears to
     772                 :            :  *              have been enabled by the description of the ECDT in the ACPI
     773                 :            :  *              specification: "The availability of the region space can be
     774                 :            :  *              detected by providing a _REG method object underneath the
     775                 :            :  *              Embedded Controller device."
     776                 :            :  *
     777                 :            :  *              To quickly access the EC device, we use the ec_device_node used
     778                 :            :  *              during EC handler installation. Otherwise, we would need to
     779                 :            :  *              perform a time consuming namespace walk, executing _HID
     780                 :            :  *              methods to find the EC device.
     781                 :            :  *
     782                 :            :  *  MUTEX:      Assumes the namespace is locked
     783                 :            :  *
     784                 :            :  ******************************************************************************/
     785                 :            : 
     786                 :            : static void
     787                 :          0 : acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
     788                 :            : {
     789                 :          0 :         acpi_handle reg_method;
     790                 :          0 :         struct acpi_namespace_node *next_node;
     791                 :          0 :         acpi_status status;
     792                 :          0 :         struct acpi_object_list args;
     793                 :          0 :         union acpi_object objects[2];
     794                 :            : 
     795                 :          0 :         ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method);
     796                 :            : 
     797         [ #  # ]:          0 :         if (!ec_device_node) {
     798                 :            :                 return_VOID;
     799                 :            :         }
     800                 :            : 
     801                 :            :         /* Namespace is currently locked, must release */
     802                 :            : 
     803                 :          0 :         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     804                 :            : 
     805                 :            :         /* Get a handle to a _REG method immediately under the EC device */
     806                 :            : 
     807                 :          0 :         status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, &reg_method);
     808         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {
     809                 :          0 :                 goto exit;      /* There is no _REG method present */
     810                 :            :         }
     811                 :            : 
     812                 :            :         /*
     813                 :            :          * Execute the _REG method only if there is no Operation Region in
     814                 :            :          * this scope with the Embedded Controller space ID. Otherwise, it
     815                 :            :          * will already have been executed. Note, this allows for Regions
     816                 :            :          * with other space IDs to be present; but the code below will then
     817                 :            :          * execute the _REG method with the embedded_control space_ID argument.
     818                 :            :          */
     819                 :          0 :         next_node = acpi_ns_get_next_node(ec_device_node, NULL);
     820         [ #  # ]:          0 :         while (next_node) {
     821         [ #  # ]:          0 :                 if ((next_node->type == ACPI_TYPE_REGION) &&
     822         [ #  # ]:          0 :                     (next_node->object) &&
     823         [ #  # ]:          0 :                     (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) {
     824                 :          0 :                         goto exit;      /* Do not execute the _REG */
     825                 :            :                 }
     826                 :            : 
     827                 :          0 :                 next_node = acpi_ns_get_next_node(ec_device_node, next_node);
     828                 :            :         }
     829                 :            : 
     830                 :            :         /* Evaluate the _REG(embedded_control,Connect) method */
     831                 :            : 
     832                 :          0 :         args.count = 2;
     833                 :          0 :         args.pointer = objects;
     834                 :          0 :         objects[0].type = ACPI_TYPE_INTEGER;
     835                 :          0 :         objects[0].integer.value = ACPI_ADR_SPACE_EC;
     836                 :          0 :         objects[1].type = ACPI_TYPE_INTEGER;
     837                 :          0 :         objects[1].integer.value = ACPI_REG_CONNECT;
     838                 :            : 
     839                 :          0 :         (void)acpi_evaluate_object(reg_method, NULL, &args, NULL);
     840                 :            : 
     841                 :          0 : exit:
     842                 :            :         /* We ignore all errors from above, don't care */
     843                 :            : 
     844                 :          0 :         (void)acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     845                 :          0 :         return_VOID;
     846                 :            : }

Generated by: LCOV version 1.14