Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: evmisc - Miscellaneous event manager support functions
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acevents.h"
0013 #include "acnamesp.h"
0014 
0015 #define _COMPONENT          ACPI_EVENTS
0016 ACPI_MODULE_NAME("evmisc")
0017 
0018 /* Local prototypes */
0019 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
0020 
0021 /*******************************************************************************
0022  *
0023  * FUNCTION:    acpi_ev_is_notify_object
0024  *
0025  * PARAMETERS:  node            - Node to check
0026  *
0027  * RETURN:      TRUE if notifies allowed on this object
0028  *
0029  * DESCRIPTION: Check type of node for a object that supports notifies.
0030  *
0031  *              TBD: This could be replaced by a flag bit in the node.
0032  *
0033  ******************************************************************************/
0034 
0035 u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
0036 {
0037 
0038     switch (node->type) {
0039     case ACPI_TYPE_DEVICE:
0040     case ACPI_TYPE_PROCESSOR:
0041     case ACPI_TYPE_THERMAL:
0042         /*
0043          * These are the ONLY objects that can receive ACPI notifications
0044          */
0045         return (TRUE);
0046 
0047     default:
0048 
0049         return (FALSE);
0050     }
0051 }
0052 
0053 /*******************************************************************************
0054  *
0055  * FUNCTION:    acpi_ev_queue_notify_request
0056  *
0057  * PARAMETERS:  node            - NS node for the notified object
0058  *              notify_value    - Value from the Notify() request
0059  *
0060  * RETURN:      Status
0061  *
0062  * DESCRIPTION: Dispatch a device notification event to a previously
0063  *              installed handler.
0064  *
0065  ******************************************************************************/
0066 
0067 acpi_status
0068 acpi_ev_queue_notify_request(struct acpi_namespace_node *node, u32 notify_value)
0069 {
0070     union acpi_operand_object *obj_desc;
0071     union acpi_operand_object *handler_list_head = NULL;
0072     union acpi_generic_state *info;
0073     u8 handler_list_id = 0;
0074     acpi_status status = AE_OK;
0075 
0076     ACPI_FUNCTION_NAME(ev_queue_notify_request);
0077 
0078     /* Are Notifies allowed on this object? */
0079 
0080     if (!acpi_ev_is_notify_object(node)) {
0081         return (AE_TYPE);
0082     }
0083 
0084     /* Get the correct notify list type (System or Device) */
0085 
0086     if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
0087         handler_list_id = ACPI_SYSTEM_HANDLER_LIST;
0088     } else {
0089         handler_list_id = ACPI_DEVICE_HANDLER_LIST;
0090     }
0091 
0092     /* Get the notify object attached to the namespace Node */
0093 
0094     obj_desc = acpi_ns_get_attached_object(node);
0095     if (obj_desc) {
0096 
0097         /* We have an attached object, Get the correct handler list */
0098 
0099         handler_list_head =
0100             obj_desc->common_notify.notify_list[handler_list_id];
0101     }
0102 
0103     /*
0104      * If there is no notify handler (Global or Local)
0105      * for this object, just ignore the notify
0106      */
0107     if (!acpi_gbl_global_notify[handler_list_id].handler
0108         && !handler_list_head) {
0109         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0110                   "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n",
0111                   acpi_ut_get_node_name(node), notify_value,
0112                   node));
0113 
0114         return (AE_OK);
0115     }
0116 
0117     /* Setup notify info and schedule the notify dispatcher */
0118 
0119     info = acpi_ut_create_generic_state();
0120     if (!info) {
0121         return (AE_NO_MEMORY);
0122     }
0123 
0124     info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY;
0125 
0126     info->notify.node = node;
0127     info->notify.value = (u16)notify_value;
0128     info->notify.handler_list_id = handler_list_id;
0129     info->notify.handler_list_head = handler_list_head;
0130     info->notify.global = &acpi_gbl_global_notify[handler_list_id];
0131 
0132     ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0133               "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
0134               acpi_ut_get_node_name(node),
0135               acpi_ut_get_type_name(node->type), notify_value,
0136               acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY),
0137               node));
0138 
0139     status = acpi_os_execute(OSL_NOTIFY_HANDLER,
0140                  acpi_ev_notify_dispatch, info);
0141     if (ACPI_FAILURE(status)) {
0142         acpi_ut_delete_generic_state(info);
0143     }
0144 
0145     return (status);
0146 }
0147 
0148 /*******************************************************************************
0149  *
0150  * FUNCTION:    acpi_ev_notify_dispatch
0151  *
0152  * PARAMETERS:  context         - To be passed to the notify handler
0153  *
0154  * RETURN:      None.
0155  *
0156  * DESCRIPTION: Dispatch a device notification event to a previously
0157  *              installed handler.
0158  *
0159  ******************************************************************************/
0160 
0161 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
0162 {
0163     union acpi_generic_state *info = (union acpi_generic_state *)context;
0164     union acpi_operand_object *handler_obj;
0165 
0166     ACPI_FUNCTION_ENTRY();
0167 
0168     /* Invoke a global notify handler if installed */
0169 
0170     if (info->notify.global->handler) {
0171         info->notify.global->handler(info->notify.node,
0172                          info->notify.value,
0173                          info->notify.global->context);
0174     }
0175 
0176     /* Now invoke the local notify handler(s) if any are installed */
0177 
0178     handler_obj = info->notify.handler_list_head;
0179     while (handler_obj) {
0180         handler_obj->notify.handler(info->notify.node,
0181                         info->notify.value,
0182                         handler_obj->notify.context);
0183 
0184         handler_obj =
0185             handler_obj->notify.next[info->notify.handler_list_id];
0186     }
0187 
0188     /* All done with the info object */
0189 
0190     acpi_ut_delete_generic_state(info);
0191 }
0192 
0193 #if (!ACPI_REDUCED_HARDWARE)
0194 /******************************************************************************
0195  *
0196  * FUNCTION:    acpi_ev_terminate
0197  *
0198  * PARAMETERS:  none
0199  *
0200  * RETURN:      none
0201  *
0202  * DESCRIPTION: Disable events and free memory allocated for table storage.
0203  *
0204  ******************************************************************************/
0205 
0206 void acpi_ev_terminate(void)
0207 {
0208     u32 i;
0209     acpi_status status;
0210 
0211     ACPI_FUNCTION_TRACE(ev_terminate);
0212 
0213     if (acpi_gbl_events_initialized) {
0214         /*
0215          * Disable all event-related functionality. In all cases, on error,
0216          * print a message but obviously we don't abort.
0217          */
0218 
0219         /* Disable all fixed events */
0220 
0221         for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
0222             status = acpi_disable_event(i, 0);
0223             if (ACPI_FAILURE(status)) {
0224                 ACPI_ERROR((AE_INFO,
0225                         "Could not disable fixed event %u",
0226                         (u32) i));
0227             }
0228         }
0229 
0230         /* Disable all GPEs in all GPE blocks */
0231 
0232         status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
0233         if (ACPI_FAILURE(status)) {
0234             ACPI_EXCEPTION((AE_INFO, status,
0235                     "Could not disable GPEs in GPE block"));
0236         }
0237 
0238         status = acpi_ev_remove_global_lock_handler();
0239         if (ACPI_FAILURE(status)) {
0240             ACPI_EXCEPTION((AE_INFO, status,
0241                     "Could not remove Global Lock handler"));
0242         }
0243 
0244         acpi_gbl_events_initialized = FALSE;
0245     }
0246 
0247     /* Remove SCI handlers */
0248 
0249     status = acpi_ev_remove_all_sci_handlers();
0250     if (ACPI_FAILURE(status)) {
0251         ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
0252     }
0253 
0254     /* Deallocate all handler objects installed within GPE info structs */
0255 
0256     status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
0257     if (ACPI_FAILURE(status)) {
0258         ACPI_EXCEPTION((AE_INFO, status,
0259                 "Could not delete GPE handlers"));
0260     }
0261 
0262     /* Return to original mode if necessary */
0263 
0264     if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
0265         status = acpi_disable();
0266         if (ACPI_FAILURE(status)) {
0267             ACPI_WARNING((AE_INFO, "AcpiDisable failed"));
0268         }
0269     }
0270     return_VOID;
0271 }
0272 
0273 #endif              /* !ACPI_REDUCED_HARDWARE */