Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
evmisc.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Module Name: evmisc - Miscellaneous event manager support functions
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, Intel Corp.
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 "accommon.h"
46 #include "acevents.h"
47 #include "acnamesp.h"
48 
49 #define _COMPONENT ACPI_EVENTS
50 ACPI_MODULE_NAME("evmisc")
51 
52 /* Local prototypes */
53 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
54 
55 /*******************************************************************************
56  *
57  * FUNCTION: acpi_ev_is_notify_object
58  *
59  * PARAMETERS: node - Node to check
60  *
61  * RETURN: TRUE if notifies allowed on this object
62  *
63  * DESCRIPTION: Check type of node for a object that supports notifies.
64  *
65  * TBD: This could be replaced by a flag bit in the node.
66  *
67  ******************************************************************************/
68 
70 {
71  switch (node->type) {
72  case ACPI_TYPE_DEVICE:
74  case ACPI_TYPE_THERMAL:
75  /*
76  * These are the ONLY objects that can receive ACPI notifications
77  */
78  return (TRUE);
79 
80  default:
81  return (FALSE);
82  }
83 }
84 
85 /*******************************************************************************
86  *
87  * FUNCTION: acpi_ev_queue_notify_request
88  *
89  * PARAMETERS: node - NS node for the notified object
90  * notify_value - Value from the Notify() request
91  *
92  * RETURN: Status
93  *
94  * DESCRIPTION: Dispatch a device notification event to a previously
95  * installed handler.
96  *
97  ******************************************************************************/
98 
101  u32 notify_value)
102 {
103  union acpi_operand_object *obj_desc;
104  union acpi_operand_object *handler_list_head = NULL;
105  union acpi_generic_state *info;
106  u8 handler_list_id = 0;
108 
109  ACPI_FUNCTION_NAME(ev_queue_notify_request);
110 
111  /* Are Notifies allowed on this object? */
112 
113  if (!acpi_ev_is_notify_object(node)) {
114  return (AE_TYPE);
115  }
116 
117  /* Get the correct notify list type (System or Device) */
118 
119  if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
120  handler_list_id = ACPI_SYSTEM_HANDLER_LIST;
121  } else {
122  handler_list_id = ACPI_DEVICE_HANDLER_LIST;
123  }
124 
125  /* Get the notify object attached to the namespace Node */
126 
127  obj_desc = acpi_ns_get_attached_object(node);
128  if (obj_desc) {
129 
130  /* We have an attached object, Get the correct handler list */
131 
132  handler_list_head =
133  obj_desc->common_notify.notify_list[handler_list_id];
134  }
135 
136  /*
137  * If there is no notify handler (Global or Local)
138  * for this object, just ignore the notify
139  */
140  if (!acpi_gbl_global_notify[handler_list_id].handler
141  && !handler_list_head) {
143  "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n",
144  acpi_ut_get_node_name(node), notify_value,
145  node));
146 
147  return (AE_OK);
148  }
149 
150  /* Setup notify info and schedule the notify dispatcher */
151 
153  if (!info) {
154  return (AE_NO_MEMORY);
155  }
156 
157  info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY;
158 
159  info->notify.node = node;
160  info->notify.value = (u16)notify_value;
161  info->notify.handler_list_id = handler_list_id;
162  info->notify.handler_list_head = handler_list_head;
163  info->notify.global = &acpi_gbl_global_notify[handler_list_id];
164 
166  "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
167  acpi_ut_get_node_name(node),
168  acpi_ut_get_type_name(node->type), notify_value,
169  acpi_ut_get_notify_name(notify_value), node));
170 
171  status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
172  info);
173  if (ACPI_FAILURE(status)) {
175  }
176 
177  return (status);
178 }
179 
180 /*******************************************************************************
181  *
182  * FUNCTION: acpi_ev_notify_dispatch
183  *
184  * PARAMETERS: context - To be passed to the notify handler
185  *
186  * RETURN: None.
187  *
188  * DESCRIPTION: Dispatch a device notification event to a previously
189  * installed handler.
190  *
191  ******************************************************************************/
192 
193 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
194 {
195  union acpi_generic_state *info = (union acpi_generic_state *)context;
196  union acpi_operand_object *handler_obj;
197 
199 
200  /* Invoke a global notify handler if installed */
201 
202  if (info->notify.global->handler) {
203  info->notify.global->handler(info->notify.node,
204  info->notify.value,
205  info->notify.global->context);
206  }
207 
208  /* Now invoke the local notify handler(s) if any are installed */
209 
210  handler_obj = info->notify.handler_list_head;
211  while (handler_obj) {
212  handler_obj->notify.handler(info->notify.node,
213  info->notify.value,
214  handler_obj->notify.context);
215 
216  handler_obj =
217  handler_obj->notify.next[info->notify.handler_list_id];
218  }
219 
220  /* All done with the info object */
221 
223 }
224 
225 #if (!ACPI_REDUCED_HARDWARE)
226 /******************************************************************************
227  *
228  * FUNCTION: acpi_ev_terminate
229  *
230  * PARAMETERS: none
231  *
232  * RETURN: none
233  *
234  * DESCRIPTION: Disable events and free memory allocated for table storage.
235  *
236  ******************************************************************************/
237 
239 {
240  u32 i;
242 
243  ACPI_FUNCTION_TRACE(ev_terminate);
244 
246  /*
247  * Disable all event-related functionality. In all cases, on error,
248  * print a message but obviously we don't abort.
249  */
250 
251  /* Disable all fixed events */
252 
253  for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
254  status = acpi_disable_event(i, 0);
255  if (ACPI_FAILURE(status)) {
257  "Could not disable fixed event %u",
258  (u32) i));
259  }
260  }
261 
262  /* Disable all GPEs in all GPE blocks */
263 
265 
266  /* Remove SCI handler */
267 
268  status = acpi_ev_remove_sci_handler();
269  if (ACPI_FAILURE(status)) {
270  ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
271  }
272 
274  if (ACPI_FAILURE(status)) {
276  "Could not remove Global Lock handler"));
277  }
278  }
279 
280  /* Deallocate all handler objects installed within GPE info structs */
281 
283 
284  /* Return to original mode if necessary */
285 
287  status = acpi_disable();
288  if (ACPI_FAILURE(status)) {
289  ACPI_WARNING((AE_INFO, "AcpiDisable failed"));
290  }
291  }
292  return_VOID;
293 }
294 
295 #endif /* !ACPI_REDUCED_HARDWARE */