linux/drivers/acpi/acpica/evsci.c
<<
>>
Prefs
   1/*******************************************************************************
   2 *
   3 * Module Name: evsci - System Control Interrupt configuration and
   4 *                      legacy to ACPI mode state transition functions
   5 *
   6 ******************************************************************************/
   7
   8/*
   9 * Copyright (C) 2000 - 2016, Intel Corp.
  10 * All rights reserved.
  11 *
  12 * Redistribution and use in source and binary forms, with or without
  13 * modification, are permitted provided that the following conditions
  14 * are met:
  15 * 1. Redistributions of source code must retain the above copyright
  16 *    notice, this list of conditions, and the following disclaimer,
  17 *    without modification.
  18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  19 *    substantially similar to the "NO WARRANTY" disclaimer below
  20 *    ("Disclaimer") and any redistribution must be conditioned upon
  21 *    including a substantially similar Disclaimer requirement for further
  22 *    binary redistribution.
  23 * 3. Neither the names of the above-listed copyright holders nor the names
  24 *    of any contributors may be used to endorse or promote products derived
  25 *    from this software without specific prior written permission.
  26 *
  27 * Alternatively, this software may be distributed under the terms of the
  28 * GNU General Public License ("GPL") version 2 as published by the Free
  29 * Software Foundation.
  30 *
  31 * NO WARRANTY
  32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42 * POSSIBILITY OF SUCH DAMAGES.
  43 */
  44
  45#include <acpi/acpi.h>
  46#include "accommon.h"
  47#include "acevents.h"
  48
  49#define _COMPONENT          ACPI_EVENTS
  50ACPI_MODULE_NAME("evsci")
  51#if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
  52/* Local prototypes */
  53static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
  54
  55/*******************************************************************************
  56 *
  57 * FUNCTION:    acpi_ev_sci_dispatch
  58 *
  59 * PARAMETERS:  None
  60 *
  61 * RETURN:      Status code indicates whether interrupt was handled.
  62 *
  63 * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
  64 *
  65 ******************************************************************************/
  66
  67u32 acpi_ev_sci_dispatch(void)
  68{
  69        struct acpi_sci_handler_info *sci_handler;
  70        acpi_cpu_flags flags;
  71        u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
  72
  73        ACPI_FUNCTION_NAME(ev_sci_dispatch);
  74
  75        /* Are there any host-installed SCI handlers? */
  76
  77        if (!acpi_gbl_sci_handler_list) {
  78                return (int_status);
  79        }
  80
  81        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  82
  83        /* Invoke all host-installed SCI handlers */
  84
  85        sci_handler = acpi_gbl_sci_handler_list;
  86        while (sci_handler) {
  87
  88                /* Invoke the installed handler (at interrupt level) */
  89
  90                int_status |= sci_handler->address(sci_handler->context);
  91
  92                sci_handler = sci_handler->next;
  93        }
  94
  95        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  96        return (int_status);
  97}
  98
  99/*******************************************************************************
 100 *
 101 * FUNCTION:    acpi_ev_sci_xrupt_handler
 102 *
 103 * PARAMETERS:  context   - Calling Context
 104 *
 105 * RETURN:      Status code indicates whether interrupt was handled.
 106 *
 107 * DESCRIPTION: Interrupt handler that will figure out what function or
 108 *              control method to call to deal with a SCI.
 109 *
 110 ******************************************************************************/
 111
 112static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
 113{
 114        struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
 115        u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
 116
 117        ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
 118
 119        /*
 120         * We are guaranteed by the ACPICA initialization/shutdown code that
 121         * if this interrupt handler is installed, ACPI is enabled.
 122         */
 123
 124        /*
 125         * Fixed Events:
 126         * Check for and dispatch any Fixed Events that have occurred
 127         */
 128        interrupt_handled |= acpi_ev_fixed_event_detect();
 129
 130        /*
 131         * General Purpose Events:
 132         * Check for and dispatch any GPEs that have occurred
 133         */
 134        interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
 135
 136        /* Invoke all host-installed SCI handlers */
 137
 138        interrupt_handled |= acpi_ev_sci_dispatch();
 139
 140        acpi_sci_count++;
 141        return_UINT32(interrupt_handled);
 142}
 143
 144/*******************************************************************************
 145 *
 146 * FUNCTION:    acpi_ev_gpe_xrupt_handler
 147 *
 148 * PARAMETERS:  context   - Calling Context
 149 *
 150 * RETURN:      Status code indicates whether interrupt was handled.
 151 *
 152 * DESCRIPTION: Handler for GPE Block Device interrupts
 153 *
 154 ******************************************************************************/
 155
 156u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
 157{
 158        struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
 159        u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
 160
 161        ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
 162
 163        /*
 164         * We are guaranteed by the ACPICA initialization/shutdown code that
 165         * if this interrupt handler is installed, ACPI is enabled.
 166         */
 167
 168        /* GPEs: Check for and dispatch any GPEs that have occurred */
 169
 170        interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
 171        return_UINT32(interrupt_handled);
 172}
 173
 174/******************************************************************************
 175 *
 176 * FUNCTION:    acpi_ev_install_sci_handler
 177 *
 178 * PARAMETERS:  none
 179 *
 180 * RETURN:      Status
 181 *
 182 * DESCRIPTION: Installs SCI handler.
 183 *
 184 ******************************************************************************/
 185
 186u32 acpi_ev_install_sci_handler(void)
 187{
 188        u32 status = AE_OK;
 189
 190        ACPI_FUNCTION_TRACE(ev_install_sci_handler);
 191
 192        status =
 193            acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
 194                                              acpi_ev_sci_xrupt_handler,
 195                                              acpi_gbl_gpe_xrupt_list_head);
 196        return_ACPI_STATUS(status);
 197}
 198
 199/******************************************************************************
 200 *
 201 * FUNCTION:    acpi_ev_remove_all_sci_handlers
 202 *
 203 * PARAMETERS:  none
 204 *
 205 * RETURN:      AE_OK if handler uninstalled, AE_ERROR if handler was not
 206 *              installed to begin with
 207 *
 208 * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
 209 *              taken. Remove all host-installed SCI handlers.
 210 *
 211 * Note:  It doesn't seem important to disable all events or set the event
 212 *        enable registers to their original values. The OS should disable
 213 *        the SCI interrupt level when the handler is removed, so no more
 214 *        events will come in.
 215 *
 216 ******************************************************************************/
 217
 218acpi_status acpi_ev_remove_all_sci_handlers(void)
 219{
 220        struct acpi_sci_handler_info *sci_handler;
 221        acpi_cpu_flags flags;
 222        acpi_status status;
 223
 224        ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
 225
 226        /* Just let the OS remove the handler and disable the level */
 227
 228        status =
 229            acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
 230                                             acpi_ev_sci_xrupt_handler);
 231
 232        if (!acpi_gbl_sci_handler_list) {
 233                return (status);
 234        }
 235
 236        flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 237
 238        /* Free all host-installed SCI handlers */
 239
 240        while (acpi_gbl_sci_handler_list) {
 241                sci_handler = acpi_gbl_sci_handler_list;
 242                acpi_gbl_sci_handler_list = sci_handler->next;
 243                ACPI_FREE(sci_handler);
 244        }
 245
 246        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
 247        return_ACPI_STATUS(status);
 248}
 249
 250#endif                          /* !ACPI_REDUCED_HARDWARE */
 251