Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 : : /****************************************************************************** 3 : : * 4 : : * Module Name: evmisc - Miscellaneous event manager support functions 5 : : * 6 : : * Copyright (C) 2000 - 2020, Intel Corp. 7 : : * 8 : : *****************************************************************************/ 9 : : 10 : : #include <acpi/acpi.h> 11 : : #include "accommon.h" 12 : : #include "acevents.h" 13 : : #include "acnamesp.h" 14 : : 15 : : #define _COMPONENT ACPI_EVENTS 16 : : ACPI_MODULE_NAME("evmisc") 17 : : 18 : : /* Local prototypes */ 19 : : static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); 20 : : 21 : : /******************************************************************************* 22 : : * 23 : : * FUNCTION: acpi_ev_is_notify_object 24 : : * 25 : : * PARAMETERS: node - Node to check 26 : : * 27 : : * RETURN: TRUE if notifies allowed on this object 28 : : * 29 : : * DESCRIPTION: Check type of node for a object that supports notifies. 30 : : * 31 : : * TBD: This could be replaced by a flag bit in the node. 32 : : * 33 : : ******************************************************************************/ 34 : : 35 : 270 : u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) 36 : : { 37 : : 38 [ - + ]: 270 : switch (node->type) { 39 : : case ACPI_TYPE_DEVICE: 40 : : case ACPI_TYPE_PROCESSOR: 41 : : case ACPI_TYPE_THERMAL: 42 : : /* 43 : : * These are the ONLY objects that can receive ACPI notifications 44 : : */ 45 : : return (TRUE); 46 : : 47 : 0 : default: 48 : : 49 : 0 : return (FALSE); 50 : : } 51 : : } 52 : : 53 : : /******************************************************************************* 54 : : * 55 : : * FUNCTION: acpi_ev_queue_notify_request 56 : : * 57 : : * PARAMETERS: node - NS node for the notified object 58 : : * notify_value - Value from the Notify() request 59 : : * 60 : : * RETURN: Status 61 : : * 62 : : * DESCRIPTION: Dispatch a device notification event to a previously 63 : : * installed handler. 64 : : * 65 : : ******************************************************************************/ 66 : : 67 : : acpi_status 68 : 0 : acpi_ev_queue_notify_request(struct acpi_namespace_node *node, u32 notify_value) 69 : : { 70 : 0 : union acpi_operand_object *obj_desc; 71 : 0 : union acpi_operand_object *handler_list_head = NULL; 72 : 0 : union acpi_generic_state *info; 73 : 0 : u8 handler_list_id = 0; 74 : 0 : acpi_status status = AE_OK; 75 : : 76 : 0 : ACPI_FUNCTION_NAME(ev_queue_notify_request); 77 : : 78 : : /* Are Notifies allowed on this object? */ 79 : : 80 [ # # ]: 0 : if (!acpi_ev_is_notify_object(node)) { 81 : : return (AE_TYPE); 82 : : } 83 : : 84 : : /* Get the correct notify list type (System or Device) */ 85 : : 86 [ # # ]: 0 : if (notify_value <= ACPI_MAX_SYS_NOTIFY) { 87 : : handler_list_id = ACPI_SYSTEM_HANDLER_LIST; 88 : : } else { 89 : 0 : handler_list_id = ACPI_DEVICE_HANDLER_LIST; 90 : : } 91 : : 92 : : /* Get the notify object attached to the namespace Node */ 93 : : 94 : 0 : obj_desc = acpi_ns_get_attached_object(node); 95 [ # # ]: 0 : if (obj_desc) { 96 : : 97 : : /* We have an attached object, Get the correct handler list */ 98 : : 99 : 0 : handler_list_head = 100 : 0 : obj_desc->common_notify.notify_list[handler_list_id]; 101 : : } 102 : : 103 : : /* 104 : : * If there is no notify handler (Global or Local) 105 : : * for this object, just ignore the notify 106 : : */ 107 [ # # ]: 0 : if (!acpi_gbl_global_notify[handler_list_id].handler 108 [ # # ]: 0 : && !handler_list_head) { 109 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, 110 : : "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", 111 : : acpi_ut_get_node_name(node), notify_value, 112 : : node)); 113 : : 114 : : return (AE_OK); 115 : : } 116 : : 117 : : /* Setup notify info and schedule the notify dispatcher */ 118 : : 119 : 0 : info = acpi_ut_create_generic_state(); 120 [ # # ]: 0 : if (!info) { 121 : : return (AE_NO_MEMORY); 122 : : } 123 : : 124 : 0 : info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY; 125 : : 126 : 0 : info->notify.node = node; 127 : 0 : info->notify.value = (u16)notify_value; 128 : 0 : info->notify.handler_list_id = handler_list_id; 129 : 0 : info->notify.handler_list_head = handler_list_head; 130 : 0 : info->notify.global = &acpi_gbl_global_notify[handler_list_id]; 131 : : 132 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, 133 : : "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", 134 : : acpi_ut_get_node_name(node), 135 : : acpi_ut_get_type_name(node->type), notify_value, 136 : : acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY), 137 : 0 : node)); 138 : : 139 : 0 : status = acpi_os_execute(OSL_NOTIFY_HANDLER, 140 : : acpi_ev_notify_dispatch, info); 141 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 142 : 0 : acpi_ut_delete_generic_state(info); 143 : : } 144 : : 145 : : return (status); 146 : : } 147 : : 148 : : /******************************************************************************* 149 : : * 150 : : * FUNCTION: acpi_ev_notify_dispatch 151 : : * 152 : : * PARAMETERS: context - To be passed to the notify handler 153 : : * 154 : : * RETURN: None. 155 : : * 156 : : * DESCRIPTION: Dispatch a device notification event to a previously 157 : : * installed handler. 158 : : * 159 : : ******************************************************************************/ 160 : : 161 : 0 : static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) 162 : : { 163 : 0 : union acpi_generic_state *info = (union acpi_generic_state *)context; 164 : 0 : union acpi_operand_object *handler_obj; 165 : : 166 : 0 : ACPI_FUNCTION_ENTRY(); 167 : : 168 : : /* Invoke a global notify handler if installed */ 169 : : 170 [ # # ]: 0 : if (info->notify.global->handler) { 171 : 0 : info->notify.global->handler(info->notify.node, 172 : 0 : info->notify.value, 173 : : info->notify.global->context); 174 : : } 175 : : 176 : : /* Now invoke the local notify handler(s) if any are installed */ 177 : : 178 : 0 : handler_obj = info->notify.handler_list_head; 179 [ # # ]: 0 : while (handler_obj) { 180 : 0 : handler_obj->notify.handler(info->notify.node, 181 : 0 : info->notify.value, 182 : : handler_obj->notify.context); 183 : : 184 : 0 : handler_obj = 185 : 0 : handler_obj->notify.next[info->notify.handler_list_id]; 186 : : } 187 : : 188 : : /* All done with the info object */ 189 : : 190 : 0 : acpi_ut_delete_generic_state(info); 191 : 0 : } 192 : : 193 : : #if (!ACPI_REDUCED_HARDWARE) 194 : : /****************************************************************************** 195 : : * 196 : : * FUNCTION: acpi_ev_terminate 197 : : * 198 : : * PARAMETERS: none 199 : : * 200 : : * RETURN: none 201 : : * 202 : : * DESCRIPTION: Disable events and free memory allocated for table storage. 203 : : * 204 : : ******************************************************************************/ 205 : : 206 : 0 : void acpi_ev_terminate(void) 207 : : { 208 : 0 : u32 i; 209 : 0 : acpi_status status; 210 : : 211 : 0 : ACPI_FUNCTION_TRACE(ev_terminate); 212 : : 213 [ # # ]: 0 : if (acpi_gbl_events_initialized) { 214 : : /* 215 : : * Disable all event-related functionality. In all cases, on error, 216 : : * print a message but obviously we don't abort. 217 : : */ 218 : : 219 : : /* Disable all fixed events */ 220 : : 221 [ # # ]: 0 : for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { 222 : 0 : status = acpi_disable_event(i, 0); 223 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 224 : 0 : ACPI_ERROR((AE_INFO, 225 : : "Could not disable fixed event %u", 226 : : (u32) i)); 227 : : } 228 : : } 229 : : 230 : : /* Disable all GPEs in all GPE blocks */ 231 : : 232 : 0 : status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL); 233 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 234 : 0 : ACPI_EXCEPTION((AE_INFO, status, 235 : : "Could not disable GPEs in GPE block")); 236 : : } 237 : : 238 : 0 : status = acpi_ev_remove_global_lock_handler(); 239 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 240 : 0 : ACPI_EXCEPTION((AE_INFO, status, 241 : : "Could not remove Global Lock handler")); 242 : : } 243 : : 244 : 0 : acpi_gbl_events_initialized = FALSE; 245 : : } 246 : : 247 : : /* Remove SCI handlers */ 248 : : 249 : 0 : status = acpi_ev_remove_all_sci_handlers(); 250 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 251 : 0 : ACPI_ERROR((AE_INFO, "Could not remove SCI handler")); 252 : : } 253 : : 254 : : /* Deallocate all handler objects installed within GPE info structs */ 255 : : 256 : 0 : status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL); 257 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 258 : 0 : ACPI_EXCEPTION((AE_INFO, status, 259 : : "Could not delete GPE handlers")); 260 : : } 261 : : 262 : : /* Return to original mode if necessary */ 263 : : 264 [ # # ]: 0 : if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) { 265 : 0 : status = acpi_disable(); 266 [ # # ]: 0 : if (ACPI_FAILURE(status)) { 267 : 0 : ACPI_WARNING((AE_INFO, "AcpiDisable failed")); 268 : : } 269 : : } 270 : 0 : return_VOID; 271 : : } 272 : : 273 : : #endif /* !ACPI_REDUCED_HARDWARE */