CTC++ Coverage Report - Execution Profile    #171/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/acpi/events/evgpeblk.c
Instrumentation mode: function-decision-multicondition
TER: 33 % ( 73/224)

Start/ End/    
True False - Line Source

  1 /******************************************************************************
  2  *
  3  * Module Name: evgpeblk - GPE block creation and initialization.
  4  *
  5  *****************************************************************************/
  6 
  7 /*
  8  * Copyright (C) 2000 - 2006, R. Byron Moore
  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 <acpi/acevents.h>
  46 #include <acpi/acnamesp.h>
  47 
  48 #define _COMPONENT          ACPI_EVENTS
  49 ACPI_MODULE_NAME("evgpeblk")
  50 
  51 /* Local prototypes */
  52 static acpi_status
  53 acpi_ev_save_method_info(acpi_handle obj_handle,
  54           u32 level, void *obj_desc, void **return_value);
  55 
  56 static acpi_status
  57 acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
  58            u32 level, void *info, void **return_value);
  59 
  60 static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
  61                             interrupt_number);
  62 
  63 static acpi_status
  64 acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt);
  65 
  66 static acpi_status
  67 acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
  68            u32 interrupt_number);
  69 
  70 static acpi_status
  71 acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
  72 
  73 /*******************************************************************************
  74  *
  75  * FUNCTION:    acpi_ev_valid_gpe_event
  76  *
  77  * PARAMETERS:  gpe_event_info              - Info for this GPE
  78  *
  79  * RETURN:      TRUE if the gpe_event is valid
  80  *
  81  * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
  82  *              Should be called only when the GPE lists are semaphore locked
  83  *              and not subject to change.
  84  *
  85  ******************************************************************************/
  86 
 
- 87 u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
  88 {
  89    struct acpi_gpe_xrupt_info *gpe_xrupt_block;
  90    struct acpi_gpe_block_info *gpe_block;
  91 
  92    ACPI_FUNCTION_ENTRY();
  93 
  94    /* No need for spin lock since we are not changing any list elements */
  95 
  96    /* Walk the GPE interrupt levels */
  97 
  98    gpe_xrupt_block = acpi_gbl_gpe_xrupt_list_head;
- 99    while (gpe_xrupt_block) {
  100       gpe_block = gpe_xrupt_block->gpe_block_list_head;
  101 
  102       /* Walk the GPE blocks on this interrupt level */
  103 
- 104       while (gpe_block) {
  105          if ((&gpe_block->event_info[0] <= gpe_event_info) &&
  106              (&gpe_block->
  107               event_info[((acpi_size) gpe_block->
  108                 register_count) * 8] >
- 109               gpe_event_info)) {
 - 109       (T) && (T)
 - 109       (T) && (F)
 - 109       (F) && (_)
 - 110             return (TRUE);
  111          }
  112 
  113          gpe_block = gpe_block->next;
  114       }
  115 
  116       gpe_xrupt_block = gpe_xrupt_block->next;
  117    }
  118 
 - 119    return (FALSE);
  120 }
  121 
  122 /*******************************************************************************
  123  *
  124  * FUNCTION:    acpi_ev_walk_gpe_list
  125  *
  126  * PARAMETERS:  gpe_walk_callback   - Routine called for each GPE block
  127  *
  128  * RETURN:      Status
  129  *
  130  * DESCRIPTION: Walk the GPE lists.
  131  *
  132  ******************************************************************************/
  133 
 
- 134 acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback)
  135 {
  136    struct acpi_gpe_block_info *gpe_block;
  137    struct acpi_gpe_xrupt_info *gpe_xrupt_info;
  138    acpi_status status = AE_OK;
  139    acpi_cpu_flags flags;
  140 
  141    ACPI_FUNCTION_TRACE("ev_walk_gpe_list");
  142 
  143    flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  144 
  145    /* Walk the interrupt level descriptor list */
  146 
  147    gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
- 148    while (gpe_xrupt_info) {
  149       /* Walk all Gpe Blocks attached to this interrupt level */
  150 
  151       gpe_block = gpe_xrupt_info->gpe_block_list_head;
- 152       while (gpe_block) {
  153          /* One callback per GPE block */
  154 
  155          status = gpe_walk_callback(gpe_xrupt_info, gpe_block);
- 156          if (ACPI_FAILURE(status)) {
 - 157             goto unlock_and_exit;
  158          }
  159 
  160          gpe_block = gpe_block->next;
  161       }
  162 
  163       gpe_xrupt_info = gpe_xrupt_info->next;
  164    }
  165 
  166       unlock_and_exit:
  167    acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 - 168    return_ACPI_STATUS(status);
  169 }
  170 
  171 /*******************************************************************************
  172  *
  173  * FUNCTION:    acpi_ev_delete_gpe_handlers
  174  *
  175  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  176  *              gpe_block           - Gpe Block info
  177  *
  178  * RETURN:      Status
  179  *
  180  * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
  181  *              Used only prior to termination.
  182  *
  183  ******************************************************************************/
  184 
  185 acpi_status
 
- 186 acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  187              struct acpi_gpe_block_info *gpe_block)
  188 {
  189    struct acpi_gpe_event_info *gpe_event_info;
  190    acpi_native_uint i;
  191    acpi_native_uint j;
  192 
  193    ACPI_FUNCTION_TRACE("ev_delete_gpe_handlers");
  194 
  195    /* Examine each GPE Register within the block */
  196 
- 197    for (i = 0; i < gpe_block->register_count; i++) {
  198       /* Now look at the individual GPEs in this byte register */
  199 
- 200       for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
  201          gpe_event_info =
  202              &gpe_block->
  203              event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
  204 
  205          if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
- 206              ACPI_GPE_DISPATCH_HANDLER) {
  207             ACPI_MEM_FREE(gpe_event_info->dispatch.handler);
  208             gpe_event_info->dispatch.handler = NULL;
  209             gpe_event_info->flags &=
  210                 ~ACPI_GPE_DISPATCH_MASK;
  211          }
  212       }
  213    }
  214 
 - 215    return_ACPI_STATUS(AE_OK);
  216 }
  217 
  218 /*******************************************************************************
  219  *
  220  * FUNCTION:    acpi_ev_save_method_info
  221  *
  222  * PARAMETERS:  Callback from walk_namespace
  223  *
  224  * RETURN:      Status
  225  *
  226  * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
  227  *              control method under the _GPE portion of the namespace.
  228  *              Extract the name and GPE type from the object, saving this
  229  *              information for quick lookup during GPE dispatch
  230  *
  231  *              The name of each GPE control method is of the form:
  232  *              "_Lxx" or "_Exx"
  233  *              Where:
  234  *                  L      - means that the GPE is level triggered
  235  *                  E      - means that the GPE is edge triggered
  236  *                  xx     - is the GPE number [in HEX]
  237  *
  238  ******************************************************************************/
  239 
  240 static acpi_status
 
24   241 acpi_ev_save_method_info(acpi_handle obj_handle,
  242           u32 level, void *obj_desc, void **return_value)
  243 {
  244    struct acpi_gpe_block_info *gpe_block = (void *)obj_desc;
  245    struct acpi_gpe_event_info *gpe_event_info;
  246    u32 gpe_number;
  247    char name[ACPI_NAME_SIZE + 1];
  248    u8 type;
  249    acpi_status status;
  250 
  251    ACPI_FUNCTION_TRACE("ev_save_method_info");
  252 
  253    /*
  254     * _Lxx and _Exx GPE method support
  255     *
  256     * 1) Extract the name from the object and convert to a string
  257     */
  258    ACPI_MOVE_32_TO_32(name,
  259             &((struct acpi_namespace_node *)obj_handle)->name.
  260             integer);
  261    name[ACPI_NAME_SIZE] = 0;
  262 
  263    /*
  264     * 2) Edge/Level determination is based on the 2nd character
  265     *    of the method name
  266     *
  267     * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
  268     * if a _PRW object is found that points to this GPE.
  269     */
    270    switch (name[1]) {
24    271    case 'L':
  272       type = ACPI_GPE_LEVEL_TRIGGERED;
24    273       break;
  274 
 - 275    case 'E':
  276       type = ACPI_GPE_EDGE_TRIGGERED;
 - 277       break;
  278 
 - 279    default:
  280       /* Unknown method type, just ignore it! */
  281 
  282       ACPI_ERROR((AE_INFO,
  283              "Unknown GPE method type: %s (name not of form _Lxx or _Exx)",
  284              name));
 - 285       return_ACPI_STATUS(AE_OK);
  286    }
  287 
  288    /* Convert the last two characters of the name to the GPE Number */
  289 
  290    gpe_number = ACPI_STRTOUL(&name[2], NULL, 16);
24 - 291    if (gpe_number == ACPI_UINT32_MAX) {
  292       /* Conversion failed; invalid method, just ignore it */
  293 
  294       ACPI_ERROR((AE_INFO,
  295              "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)",
  296              name));
 - 297       return_ACPI_STATUS(AE_OK);
  298    }
  299 
  300    /* Ensure that we have a valid GPE number for this GPE block */
  301 
  302    if ((gpe_number < gpe_block->block_base_number) ||
  303        (gpe_number >=
  304         (gpe_block->block_base_number +
24 - 305          (gpe_block->register_count * 8)))) {
 - 305   (T) || (_)
 - 305   (F) || (T)
 24   305   (F) || (F)
  306       /*
  307        * Not valid for this GPE block, just ignore it
  308        * However, it may be valid for a different GPE block, since GPE0 and GPE1
  309        * methods both appear under \_GPE.
  310        */
 - 311       return_ACPI_STATUS(AE_OK);
  312    }
  313 
  314    /*
  315     * Now we can add this information to the gpe_event_info block
  316     * for use during dispatch of this GPE. Default type is RUNTIME, although
  317     * this may change when the _PRW methods are executed later.
  318     */
  319    gpe_event_info =
  320        &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
  321 
  322    gpe_event_info->flags = (u8)
  323        (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
  324 
  325    gpe_event_info->dispatch.method_node =
  326        (struct acpi_namespace_node *)obj_handle;
  327 
  328    /* Update enable mask, but don't enable the HW GPE as of yet */
  329 
  330    status = acpi_ev_enable_gpe(gpe_event_info, FALSE);
  331 
  332    ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
  333            "Registered GPE method %s as GPE number 0x%.2X\n",
  334            name, gpe_number));
24    335    return_ACPI_STATUS(status);
  336 }
  337 
  338 /*******************************************************************************
  339  *
  340  * FUNCTION:    acpi_ev_match_prw_and_gpe
  341  *
  342  * PARAMETERS:  Callback from walk_namespace
  343  *
  344  * RETURN:      Status. NOTE: We ignore errors so that the _PRW walk is
  345  *              not aborted on a single _PRW failure.
  346  *
  347  * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
  348  *              Device. Run the _PRW method. If present, extract the GPE
  349  *              number and mark the GPE as a WAKE GPE.
  350  *
  351  ******************************************************************************/
  352 
  353 static acpi_status
 
318   354 acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
  355            u32 level, void *info, void **return_value)
  356 {
  357    struct acpi_gpe_walk_info *gpe_info = (void *)info;
  358    struct acpi_namespace_node *gpe_device;
  359    struct acpi_gpe_block_info *gpe_block;
  360    struct acpi_namespace_node *target_gpe_device;
  361    struct acpi_gpe_event_info *gpe_event_info;
  362    union acpi_operand_object *pkg_desc;
  363    union acpi_operand_object *obj_desc;
  364    u32 gpe_number;
  365    acpi_status status;
  366 
  367    ACPI_FUNCTION_TRACE("ev_match_prw_and_gpe");
  368 
  369    /* Check for a _PRW method under this device */
  370 
  371    status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW,
  372                 ACPI_BTYPE_PACKAGE, &pkg_desc);
282 36   373    if (ACPI_FAILURE(status)) {
  374       /* Ignore all errors from _PRW, we don't want to abort the subsystem */
  375 
282    376       return_ACPI_STATUS(AE_OK);
  377    }
  378 
  379    /* The returned _PRW package must have at least two elements */
  380 
36 - 381    if (pkg_desc->package.count < 2) {
 - 382       goto cleanup;
  383    }
  384 
  385    /* Extract pointers from the input context */
  386 
  387    gpe_device = gpe_info->gpe_device;
  388    gpe_block = gpe_info->gpe_block;
  389 
  390    /*
  391     * The _PRW object must return a package, we are only interested
  392     * in the first element
  393     */
  394    obj_desc = pkg_desc->package.elements[0];
  395 
36 - 396    if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
  397       /* Use FADT-defined GPE device (from definition of _PRW) */
  398 
  399       target_gpe_device = acpi_gbl_fadt_gpe_device;
  400 
  401       /* Integer is the GPE number in the FADT described GPE blocks */
  402 
  403       gpe_number = (u32) obj_desc->integer.value;
- 404    } else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
  405       /* Package contains a GPE reference and GPE number within a GPE block */
  406 
  407       if ((obj_desc->package.count < 2) ||
  408           (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[0]) !=
  409            ACPI_TYPE_LOCAL_REFERENCE)
  410           || (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[1]) !=
- 411          ACPI_TYPE_INTEGER)) {
 - 411     (T) || (_) || (_)
 - 411     (F) || (T) || (_)
 - 411     (F) || (F) || (T)
 - 411     (F) || (F) || (F)
 - 412          goto cleanup;
  413       }
  414 
  415       /* Get GPE block reference and decode */
  416 
  417       target_gpe_device =
  418           obj_desc->package.elements[0]->reference.node;
  419       gpe_number = (u32) obj_desc->package.elements[1]->integer.value;
    420    } else {
  421       /* Unknown type, just ignore it */
  422 
 - 423       goto cleanup;
  424    }
  425 
  426    /*
  427     * Is this GPE within this block?
  428     *
  429     * TRUE iff these conditions are true:
  430     *     1) The GPE devices match.
  431     *     2) The GPE index(number) is within the range of the Gpe Block
  432     *          associated with the GPE device.
  433     */
  434    if ((gpe_device == target_gpe_device) &&
  435        (gpe_number >= gpe_block->block_base_number) &&
  436        (gpe_number <
36 - 437         gpe_block->block_base_number + (gpe_block->register_count * 8))) {
36    437   (T) && (T) && (T)
 - 437   (T) && (T) && (F)
 - 437   (T) && (F) && (_)
 - 437   (F) && (_) && (_)
  438       gpe_event_info =
  439           &gpe_block->event_info[gpe_number -
  440                   gpe_block->block_base_number];
  441 
  442       /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
  443 
  444       gpe_event_info->flags &=
  445           ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
  446 
  447       status =
  448           acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
36 - 449       if (ACPI_FAILURE(status)) {
 - 450          goto cleanup;
  451       }
  452       status =
  453           acpi_ev_update_gpe_enable_masks(gpe_event_info,
  454                       ACPI_GPE_DISABLE);
  455    }
  456 
  457       cleanup:
  458    acpi_ut_remove_reference(pkg_desc);
36    459    return_ACPI_STATUS(AE_OK);
  460 }
  461 
  462 /*******************************************************************************
  463  *
  464  * FUNCTION:    acpi_ev_get_gpe_xrupt_block
  465  *
  466  * PARAMETERS:  interrupt_number     - Interrupt for a GPE block
  467  *
  468  * RETURN:      A GPE interrupt block
  469  *
  470  * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
  471  *              block per unique interrupt level used for GPEs.
  472  *              Should be called only when the GPE lists are semaphore locked
  473  *              and not subject to change.
  474  *
  475  ******************************************************************************/
  476 
 
  477 static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32
  478                             interrupt_number)
  479 {
  480    struct acpi_gpe_xrupt_info *next_gpe_xrupt;
  481    struct acpi_gpe_xrupt_info *gpe_xrupt;
  482    acpi_status status;
  483    acpi_cpu_flags flags;
  484 
  485    ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block");
  486 
  487    /* No need for lock since we are not changing any list elements here */
  488 
  489    next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
- 490    while (next_gpe_xrupt) {
- 491       if (next_gpe_xrupt->interrupt_number == interrupt_number) {
 - 492          return_PTR(next_gpe_xrupt);
  493       }
  494 
  495       next_gpe_xrupt = next_gpe_xrupt->next;
  496    }
  497 
  498    /* Not found, must allocate a new xrupt descriptor */
  499 
  500    gpe_xrupt = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_xrupt_info));
- 501    if (!gpe_xrupt) {
 - 502       return_PTR(NULL);
  503    }
  504 
  505    gpe_xrupt->interrupt_number = interrupt_number;
  506 
  507    /* Install new interrupt descriptor with spin lock */
  508 
  509    flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
- 510    if (acpi_gbl_gpe_xrupt_list_head) {
  511       next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head;
- 512       while (next_gpe_xrupt->next) {
  513          next_gpe_xrupt = next_gpe_xrupt->next;
  514       }
  515 
  516       next_gpe_xrupt->next = gpe_xrupt;
  517       gpe_xrupt->previous = next_gpe_xrupt;
    518    } else {
  519       acpi_gbl_gpe_xrupt_list_head = gpe_xrupt;
  520    }
  521    acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  522 
  523    /* Install new interrupt handler if not SCI_INT */
  524 
- 525    if (interrupt_number != acpi_gbl_FADT->sci_int) {
  526       status = acpi_os_install_interrupt_handler(interrupt_number,
  527                         acpi_ev_gpe_xrupt_handler,
  528                         gpe_xrupt);
- 529       if (ACPI_FAILURE(status)) {
  530          ACPI_ERROR((AE_INFO,
  531                 "Could not install GPE interrupt handler at level 0x%X",
  532                 interrupt_number));
 - 533          return_PTR(NULL);
  534       }
  535    }
  536 
   537    return_PTR(gpe_xrupt);
  538 }
  539 
  540 /*******************************************************************************
  541  *
  542  * FUNCTION:    acpi_ev_delete_gpe_xrupt
  543  *
  544 &n