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

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


File: drivers/acpi/events/evmisc.c
Instrumentation mode: function-decision-multicondition
TER: 37 % ( 39/105)

Start/ End/    
True False - Line Source

  1 /******************************************************************************
  2  *
  3  * Module Name: evmisc - Miscellaneous event manager support functions
  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 #include <acpi/acinterp.h>
  48 
  49 #define _COMPONENT          ACPI_EVENTS
  50 ACPI_MODULE_NAME("evmisc")
  51 
  52 #ifdef ACPI_DEBUG_OUTPUT
  53 static const char *acpi_notify_value_names[] = {
  54    "Bus Check",
  55    "Device Check",
  56    "Device Wake",
  57    "Eject request",
  58    "Device Check Light",
  59    "Frequency Mismatch",
  60    "Bus Mode Mismatch",
  61    "Power Fault"
  62 };
  63 #endif
  64 
  65 /* Local prototypes */
  66 
  67 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
  68 
  69 static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context);
  70 
  71 static u32 acpi_ev_global_lock_handler(void *context);
  72 
  73 /*******************************************************************************
  74  *
  75  * FUNCTION:    acpi_ev_is_notify_object
  76  *
  77  * PARAMETERS:  Node            - Node to check
  78  *
  79  * RETURN:      TRUE if notifies allowed on this object
  80  *
  81  * DESCRIPTION: Check type of node for a object that supports notifies.
  82  *
  83  *              TBD: This could be replaced by a flag bit in the node.
  84  *
  85  ******************************************************************************/
  86 
 
574   87 u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
  88 {
    89    switch (node->type) {
562    90    case ACPI_TYPE_DEVICE:
   91    case ACPI_TYPE_PROCESSOR:
 - 92    case ACPI_TYPE_POWER:
   93    case ACPI_TYPE_THERMAL:
  94       /*
  95        * These are the ONLY objects that can receive ACPI notifications
  96        */
574    97       return (TRUE);
  98 
 - 99    default:
 - 100       return (FALSE);
  101    }
  102 }
  103 
  104 /*******************************************************************************
  105  *
  106  * FUNCTION:    acpi_ev_queue_notify_request
  107  *
  108  * PARAMETERS:  Node            - NS node for the notified object
  109  *              notify_value    - Value from the Notify() request
  110  *
  111  * RETURN:      Status
  112  *
  113  * DESCRIPTION: Dispatch a device notification event to a previously
  114  *              installed handler.
  115  *
  116  ******************************************************************************/
  117 
  118 acpi_status
 
508   119 acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
  120               u32 notify_value)
  121 {
  122    union acpi_operand_object *obj_desc;
  123    union acpi_operand_object *handler_obj = NULL;
  124    union acpi_generic_state *notify_info;
  125    acpi_status status = AE_OK;
  126 
  127    ACPI_FUNCTION_NAME("ev_queue_notify_request");
  128 
  129    /*
  130     * For value 3 (Ejection Request), some device method may need to be run.
  131     * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need
  132     *   to be run.
  133     * For value 0x80 (Status Change) on the power button or sleep button,
  134     *   initiate soft-off or sleep operation?
  135     */
  136    ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  137            "Dispatching Notify(%X) on node %p\n", notify_value,
  138            node));
  139 
508 - 140    if (notify_value <= 7) {
  141       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notify value: %s\n",
  142               acpi_notify_value_names[notify_value]));
    143    } else {
  144       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  145               "Notify value: 0x%2.2X **Device Specific**\n",
  146               notify_value));
  147    }
  148 
  149    /* Get the notify object attached to the NS Node */
  150 
  151    obj_desc = acpi_ns_get_attached_object(node);
506   152    if (obj_desc) {
  153       /* We have the notify object, Get the right handler */
  154 
    155       switch (node->type) {
506    156       case ACPI_TYPE_DEVICE:
 - 157       case ACPI_TYPE_THERMAL:
 - 158       case ACPI_TYPE_PROCESSOR:
 - 159       case ACPI_TYPE_POWER:
  160 
506 - 161          if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
  162             handler_obj =
  163                 obj_desc->common_notify.system_notify;
    164          } else {
  165             handler_obj =
  166                 obj_desc->common_notify.device_notify;
  167          }
506    168          break;
  169 
 - 170       default:
  171          /* All other types are not supported */
 - 172          return (AE_TYPE);
  173       }
  174    }
  175 
  176    /* If there is any handler to run, schedule the dispatcher */
  177 
  178    if ((acpi_gbl_system_notify.handler
  179         && (notify_value <= ACPI_MAX_SYS_NOTIFY))
  180        || (acpi_gbl_device_notify.handler
506   181       && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) {
 - 181   (T && (T)) || (_ && (_)) || _
 - 181   (T && (F)) || (T && (T)) || _
 - 181   (T && (F)) || (T && (F)) || T
506    181   (T && (F)) || (F && (_)) || T
 - 181   (F && (_)) || (T && (T)) || _
 - 181   (F && (_)) || (T && (F)) || T
 - 181   (F && (_)) || (F && (_)) || T
 - 181   (T && (F)) || (T && (F)) || F
   181   (T && (F)) || (F && (_)) || F
 - 181   (F && (_)) || (T && (F)) || F
 - 181   (F && (_)) || (F && (_)) || F
  182       notify_info = acpi_ut_create_generic_state();
506 - 183       if (!notify_info) {
 - 184          return (AE_NO_MEMORY);
  185       }
  186 
  187       notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY;
  188       notify_info->notify.node = node;
  189       notify_info->notify.value = (u16) notify_value;
  190       notify_info->notify.handler_obj = handler_obj;
  191 
  192       status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
  193                        acpi_ev_notify_dispatch,
  194                        notify_info);
506 - 195       if (ACPI_FAILURE(status)) {
  196          acpi_ut_delete_generic_state(notify_info);
  197       }
  198    }
  199 
506   200    if (!handler_obj) {
  201       /*
  202        * There is no per-device notify handler for this device.
  203        * This may or may not be a problem.
  204        */
  205       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  206               "No notify handler for Notify(%4.4s, %X) node %p\n",
  207               acpi_ut_get_node_name(node), notify_value,
  208               node));
  209    }
  210 
508    211    return (status);
  212 }
  213 
  214 /*******************************************************************************
  215  *
  216  * FUNCTION:    acpi_ev_notify_dispatch
  217  *
  218  * PARAMETERS:  Context         - To be passed to the notify handler
  219  *
  220  * RETURN:      None.
  221  *
  222  * DESCRIPTION: Dispatch a device notification event to a previously
  223  *              installed handler.
  224  *
  225  ******************************************************************************/
  226 
 
506 506   227 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
  228 {
  229    union acpi_generic_state *notify_info =
  230        (union acpi_generic_state *)context;
  231    acpi_notify_handler global_handler = NULL;
  232    void *global_context = NULL;
  233    union acpi_operand_object *handler_obj;
  234 
  235    ACPI_FUNCTION_ENTRY();
  236 
  237    /*
  238     * We will invoke a global notify handler if installed.
  239     * This is done _before_ we invoke the per-device handler attached
  240     * to the device.
  241     */
506 - 242    if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) {
  243       /* Global system notification handler */
  244 
- 245       if (acpi_gbl_system_notify.handler) {
  246          global_handler = acpi_gbl_system_notify.handler;
  247          global_context = acpi_gbl_system_notify.context;
  248       }
    249    } else {
  250       /* Global driver notification handler */
  251 
506 - 252       if (acpi_gbl_device_notify.handler) {
  253          global_handler = acpi_gbl_device_notify.handler;
  254          global_context = acpi_gbl_device_notify.context;
  255       }
  256    }
  257 
  258    /* Invoke the system handler first, if present */
  259 
506 - 260    if (global_handler) {
  261       global_handler(notify_info->notify.node,
  262                 notify_info->notify.value, global_context);
  263    }
  264 
  265    /* Now invoke the per-device handler, if present */
  266 
  267    handler_obj = notify_info->notify.handler_obj;
506 - 268    if (handler_obj) {
  269       handler_obj->notify.handler(notify_info->notify.node,
  270                    notify_info->notify.value,
  271                    handler_obj->notify.context);
  272    }
  273 
  274    /* All done with the info object */
  275 
  276    acpi_ut_delete_generic_state(notify_info);
  277 }
  278 
  279 /*******************************************************************************
  280  *
  281  * FUNCTION:    acpi_ev_global_lock_thread
  282  *
  283  * PARAMETERS:  Context         - From thread interface, not used
  284  *
  285  * RETURN:      None
  286  *
  287  * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
  288  *              Global Lock.  Simply signal all threads that are waiting
  289  *              for the lock.
  290  *
  291  ******************************************************************************/
  292 
 
- 293 static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
  294 {
  295    acpi_status status;
  296 
  297    /* Signal threads that are waiting for the lock */
  298 
- 299    if (acpi_gbl_global_lock_thread_count) {
  300       /* Send sufficient units to the semaphore */
  301 
  302       status =
  303           acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore,
  304                     acpi_gbl_global_lock_thread_count);
- 305       if (ACPI_FAILURE(status)) {
  306          ACPI_ERROR((AE_INFO,
  307                 "Could not signal Global Lock semaphore"));
  308       }
  309    }
  310 }
  311 
  312 /*******************************************************************************
  313  *
  314  * FUNCTION:    acpi_ev_global_lock_handler
  315  *
  316  * PARAMETERS:  Context         - From thread interface, not used
  317  *
  318  * RETURN:      ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED
  319  *
  320  * DESCRIPTION: Invoked directly from the SCI handler when a global lock
  321  *              release interrupt occurs.  Grab the global lock and queue
  322  *              the global lock thread for execution
  323  *
  324  ******************************************************************************/
  325 
 
- 326 static u32 acpi_ev_global_lock_handler(void *context)
  327 {
  328    u8 acquired = FALSE;
  329    acpi_status status;
  330 
  331    /*
  332     * Attempt to get the lock
  333     * If we don't get it now, it will be marked pending and we will
  334     * take another interrupt when it becomes free.
  335     */
  336    ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
- 337    if (acquired) {
  338       /* Got the lock, now wake all threads waiting for it */
  339 
  340       acpi_gbl_global_lock_acquired = TRUE;
  341 
  342       /* Run the Global Lock thread which will signal all waiting threads */
  343 
  344       status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
  345                        acpi_ev_global_lock_thread,
  346                        context);
- 347       if (ACPI_FAILURE(status)) {
  348          ACPI_EXCEPTION((AE_INFO, status,
  349                "Could not queue Global Lock thread"));
  350 
 - 351          return (ACPI_INTERRUPT_NOT_HANDLED);
  352       }
  353    }
  354 
 - 355    return (ACPI_INTERRUPT_HANDLED);
  356 }
  357 
  358 /*******************************************************************************
  359  *
  360  * FUNCTION:    acpi_ev_init_global_lock_handler
  361  *
  362  * PARAMETERS:  None
  363  *
  364  * RETURN:      Status
  365  *
  366  * DESCRIPTION: Install a handler for the global lock release event
  367  *
  368  ******************************************************************************/
  369 
 
  370 acpi_status acpi_ev_init_global_lock_handler(void)
  371 {
  372    acpi_status status;
  373 
  374    ACPI_FUNCTION_TRACE("ev_init_global_lock_handler");
  375 
  376    acpi_gbl_global_lock_present = TRUE;
  377    status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
  378                     acpi_ev_global_lock_handler,
  379                     NULL);
  380 
  381    /*
  382     * If the global lock does not exist on this platform, the attempt
  383     * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick)
  384     * Map to AE_OK, but mark global lock as not present.
  385     * Any attempt to actually use the global lock will be flagged
  386     * with an error.
  387     */
- 388    if (status == AE_NO_HARDWARE_RESPONSE) {
  389       ACPI_ERROR((AE_INFO,
  390              "No response from Global Lock hardware, disabling lock"));
  391 
  392       acpi_gbl_global_lock_present = FALSE;
  393       status = AE_OK;
  394    }
  395 
   396    return_ACPI_STATUS(status);
  397 }
  398 
  399 /******************************************************************************
  400  *
  401  * FUNCTION:    acpi_ev_acquire_global_lock
  402  *
  403  * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec.
  404  *
  405  * RETURN:      Status
  406  *
  407  * DESCRIPTION: Attempt to gain ownership of the Global Lock.
  408  *
  409  *****************************************************************************/
  410 
 
63632   411 acpi_status acpi_ev_acquire_global_lock(u16 timeout)
  412 {
  413    acpi_status status = AE_OK;
  414    u8 acquired = FALSE;
  415 
  416    ACPI_FUNCTION_TRACE("ev_acquire_global_lock");
  417 
  418 #ifndef ACPI_APPLICATION
  419    /* Make sure that we actually have a global lock */
  420 
63632 - 421    if (!acpi_gbl_global_lock_present) {
 - 422       return_ACPI_STATUS(AE_NO_GLOBAL_LOCK);
  423    }
  424 #endif
  425 
  426    /* One more thread wants the global lock */
  427 
  428    acpi_gbl_global_lock_thread_count++;
  429 
  430    /*
  431     * If we (OS side vs. BIOS side) have the hardware lock already,
  432     * we are done
  433     */
63632 - 434    if (acpi_gbl_global_lock_acquired) {
 - 435       return_ACPI_STATUS(AE_OK);
  436    }
  437 
  438    /* We must acquire the actual hardware lock */
  439 
  440    ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
63632 - 441    if (acquired) {
  442       /* We got the lock */
  443 
  444       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
  445               "Acquired the HW Global Lock\n"));
  446 
  447       acpi_gbl_global_lock_acquired = TRUE;
63632    448       return_ACPI_STATUS(AE_OK);
  449    }
  450 
  451    /*
  452     * Did not get the lock.  The pending bit was set above, and we must now
  453     * wait until we get the global lock released interrupt.
  454     */
  455    ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
  456 
  457    /*
  458     * Acquire the global lock semaphore first.
  459     * Since this wait will block, we must release the interpreter
  460     */
  461    status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
  462                       timeout);
 - 463    return_ACPI_STATUS(status);
  464 }
  465 
  466 /*******************************************************************************
  467  *
  468  * FUNCTION:    acpi_ev_release_global_lock
  469  *
  470  * PARAMETERS:  None
  471  *
  472  * RETURN:      Status
  473  *
  474  * DESCRIPTION: Releases ownership of the Global Lock.
  475  *
  476  ******************************************************************************/
  477 
 
63632   478 acpi_status acpi_ev_release_global_lock(void)
  479 {
  480    u8 pending = FALSE;
  481    acpi_status status = AE_OK;
  482 
  483    ACPI_FUNCTION_TRACE("ev_release_global_lock");
  484 
63632 - 485    if (!acpi_gbl_global_lock_thread_count) {
  486       ACPI_WARNING((AE_INFO,
  487                "Cannot release HW Global Lock, it has not been acquired"));
 - 488       return_ACPI_STATUS(AE_NOT_ACQUIRED);
  489    }
  490 
  491    /* One fewer thread has the global lock */
  492 
  493    acpi_gbl_global_lock_thread_count--;
63632 - 494    if (acpi_gbl_global_lock_thread_count) {
  495       /* There are still some threads holding the lock, cannot release */
  496 
 - 497       return_ACPI_STATUS(AE_OK);
  498    }
  499 
  500    /*
  501     * No more threads holding lock, we can do the actual hardware
  502     * release
  503     */
  504    ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, pending);
  505    acpi_gbl_global_lock_acquired = FALSE;
  506 
  507    /*
  508     * If the pending bit was set, we must write GBL_RLS to the control
  509     * register
  510     */
63632 - 511    if (pending) {
  512       status = acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
  513                   1, ACPI_MTX_LOCK);
  514    }
  515 
63632    516    return_ACPI_STATUS(status);
  517 }
  518 
  519 /******************************************************************************
  520  *
  521  * FUNCTION:    acpi_ev_terminate
  522  *
  523  * PARAMETERS:  none
  524  *
  525  * RETURN:      none
  526  *
  527  * DESCRIPTION: Disable events and free memory allocated for table storage.
  528  *
  529  ******************************************************************************/
  530 
 
- 531 void acpi_ev_terminate(void)
  532 {
  533    acpi_native_uint i;
  534    acpi_status status;
  535 
  536    ACPI_FUNCTION_TRACE("ev_terminate");
  537 
- 538    if (acpi_gbl_events_initialized) {
  539       /*
  540        * Disable all event-related functionality.
  541        * In all cases, on error, print a message but obviously we don't abort.
  542        */
  543 
  544       /* Disable all fixed events */
  545 
- 546       for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
  547          status = acpi_disable_event((u32) i, 0);
- 548          if (ACPI_FAILURE(status)) {
  549             ACPI_ERROR((AE_INFO,
  550                    "Could not disable fixed event %d",
  551                    (u32) i));
  552          }
  553       }
  554 
  555       /* Disable all GPEs in&