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