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