Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
evxface.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Module Name: evxface - External interfaces for ACPI events
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 <linux/export.h>
45 #include <acpi/acpi.h>
46 #include "accommon.h"
47 #include "acnamesp.h"
48 #include "acevents.h"
49 #include "acinterp.h"
50 
51 #define _COMPONENT ACPI_EVENTS
52 ACPI_MODULE_NAME("evxface")
53 
54 
55 /*******************************************************************************
56  *
57  * FUNCTION: acpi_install_notify_handler
58  *
59  * PARAMETERS: Device - The device for which notifies will be handled
60  * handler_type - The type of handler:
61  * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
62  * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
63  * ACPI_ALL_NOTIFY: Both System and Device
64  * Handler - Address of the handler
65  * Context - Value passed to the handler on each GPE
66  *
67  * RETURN: Status
68  *
69  * DESCRIPTION: Install a handler for notifications on an ACPI Device,
70  * thermal_zone, or Processor object.
71  *
72  * NOTES: The Root namespace object may have only one handler for each
73  * type of notify (System/Device). Device/Thermal/Processor objects
74  * may have one device notify handler, and multiple system notify
75  * handlers.
76  *
77  ******************************************************************************/
81  acpi_notify_handler handler, void *context)
82 {
83  struct acpi_namespace_node *node =
84  ACPI_CAST_PTR(struct acpi_namespace_node, device);
85  union acpi_operand_object *obj_desc;
86  union acpi_operand_object *handler_obj;
88  u32 i;
89 
91 
92  /* Parameter validation */
93 
94  if ((!device) || (!handler) || (!handler_type) ||
95  (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
97  }
98 
100  if (ACPI_FAILURE(status)) {
101  return_ACPI_STATUS(status);
102  }
103 
104  /*
105  * Root Object:
106  * Registering a notify handler on the root object indicates that the
107  * caller wishes to receive notifications for all objects. Note that
108  * only one global handler can be registered per notify type.
109  * Ensure that a handler is not already installed.
110  */
111  if (device == ACPI_ROOT_OBJECT) {
112  for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
113  if (handler_type & (i + 1)) {
114  if (acpi_gbl_global_notify[i].handler) {
115  status = AE_ALREADY_EXISTS;
116  goto unlock_and_exit;
117  }
118 
119  acpi_gbl_global_notify[i].handler = handler;
120  acpi_gbl_global_notify[i].context = context;
121  }
122  }
123 
124  goto unlock_and_exit; /* Global notify handler installed, all done */
125  }
126 
127  /*
128  * All Other Objects:
129  * Caller will only receive notifications specific to the target
130  * object. Note that only certain object types are allowed to
131  * receive notifications.
132  */
133 
134  /* Are Notifies allowed on this object? */
135 
136  if (!acpi_ev_is_notify_object(node)) {
137  status = AE_TYPE;
138  goto unlock_and_exit;
139  }
140 
141  /* Check for an existing internal object, might not exist */
142 
143  obj_desc = acpi_ns_get_attached_object(node);
144  if (!obj_desc) {
145 
146  /* Create a new object */
147 
148  obj_desc = acpi_ut_create_internal_object(node->type);
149  if (!obj_desc) {
150  status = AE_NO_MEMORY;
151  goto unlock_and_exit;
152  }
153 
154  /* Attach new object to the Node, remove local reference */
155 
156  status = acpi_ns_attach_object(device, obj_desc, node->type);
157  acpi_ut_remove_reference(obj_desc);
158  if (ACPI_FAILURE(status)) {
159  goto unlock_and_exit;
160  }
161  }
162 
163  /* Ensure that the handler is not already installed in the lists */
164 
165  for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
166  if (handler_type & (i + 1)) {
167  handler_obj = obj_desc->common_notify.notify_list[i];
168  while (handler_obj) {
169  if (handler_obj->notify.handler == handler) {
170  status = AE_ALREADY_EXISTS;
171  goto unlock_and_exit;
172  }
173 
174  handler_obj = handler_obj->notify.next[i];
175  }
176  }
177  }
178 
179  /* Create and populate a new notify handler object */
180 
182  if (!handler_obj) {
183  status = AE_NO_MEMORY;
184  goto unlock_and_exit;
185  }
186 
187  handler_obj->notify.node = node;
188  handler_obj->notify.handler_type = handler_type;
189  handler_obj->notify.handler = handler;
190  handler_obj->notify.context = context;
191 
192  /* Install the handler at the list head(s) */
193 
194  for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
195  if (handler_type & (i + 1)) {
196  handler_obj->notify.next[i] =
197  obj_desc->common_notify.notify_list[i];
198 
199  obj_desc->common_notify.notify_list[i] = handler_obj;
200  }
201  }
202 
203  /* Add an extra reference if handler was installed in both lists */
204 
205  if (handler_type == ACPI_ALL_NOTIFY) {
206  acpi_ut_add_reference(handler_obj);
207  }
208 
209 unlock_and_exit:
211  return_ACPI_STATUS(status);
212 }
213 
215 
216 /*******************************************************************************
217  *
218  * FUNCTION: acpi_remove_notify_handler
219  *
220  * PARAMETERS: Device - The device for which the handler is installed
221  * handler_type - The type of handler:
222  * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
223  * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
224  * ACPI_ALL_NOTIFY: Both System and Device
225  * Handler - Address of the handler
226  *
227  * RETURN: Status
228  *
229  * DESCRIPTION: Remove a handler for notifies on an ACPI device
230  *
231  ******************************************************************************/
235 {
236  struct acpi_namespace_node *node =
237  ACPI_CAST_PTR(struct acpi_namespace_node, device);
238  union acpi_operand_object *obj_desc;
239  union acpi_operand_object *handler_obj;
240  union acpi_operand_object *previous_handler_obj;
242  u32 i;
243 
245 
246  /* Parameter validation */
247 
248  if ((!device) || (!handler) || (!handler_type) ||
249  (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
251  }
252  /* Make sure all deferred tasks are completed */
253 
255 
257  if (ACPI_FAILURE(status)) {
258  return_ACPI_STATUS(status);
259  }
260 
261  /* Root Object. Global handlers are removed here */
262 
263  if (device == ACPI_ROOT_OBJECT) {
264  for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
265  if (handler_type & (i + 1)) {
266  if (!acpi_gbl_global_notify[i].handler ||
267  (acpi_gbl_global_notify[i].handler !=
268  handler)) {
269  status = AE_NOT_EXIST;
270  goto unlock_and_exit;
271  }
272 
274  "Removing global notify handler\n"));
275 
276  acpi_gbl_global_notify[i].handler = NULL;
277  acpi_gbl_global_notify[i].context = NULL;
278  }
279  }
280 
281  goto unlock_and_exit;
282  }
283 
284  /* All other objects: Are Notifies allowed on this object? */
285 
286  if (!acpi_ev_is_notify_object(node)) {
287  status = AE_TYPE;
288  goto unlock_and_exit;
289  }
290 
291  /* Must have an existing internal object */
292 
293  obj_desc = acpi_ns_get_attached_object(node);
294  if (!obj_desc) {
295  status = AE_NOT_EXIST;
296  goto unlock_and_exit;
297  }
298 
299  /* Internal object exists. Find the handler and remove it */
300 
301  for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
302  if (handler_type & (i + 1)) {
303  handler_obj = obj_desc->common_notify.notify_list[i];
304  previous_handler_obj = NULL;
305 
306  /* Attempt to find the handler in the handler list */
307 
308  while (handler_obj &&
309  (handler_obj->notify.handler != handler)) {
310  previous_handler_obj = handler_obj;
311  handler_obj = handler_obj->notify.next[i];
312  }
313 
314  if (!handler_obj) {
315  status = AE_NOT_EXIST;
316  goto unlock_and_exit;
317  }
318 
319  /* Remove the handler object from the list */
320 
321  if (previous_handler_obj) { /* Handler is not at the list head */
322  previous_handler_obj->notify.next[i] =
323  handler_obj->notify.next[i];
324  } else { /* Handler is at the list head */
325 
326  obj_desc->common_notify.notify_list[i] =
327  handler_obj->notify.next[i];
328  }
329 
330  acpi_ut_remove_reference(handler_obj);
331  }
332  }
333 
334 unlock_and_exit:
336  return_ACPI_STATUS(status);
337 }
338 
340 
341 /*******************************************************************************
342  *
343  * FUNCTION: acpi_install_exception_handler
344  *
345  * PARAMETERS: handler - Pointer to the handler function for the
346  * event
347  *
348  * RETURN: Status
349  *
350  * DESCRIPTION: Saves the pointer to the handler function
351  *
352  ******************************************************************************/
353 #ifdef ACPI_FUTURE_USAGE
354 acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
355 {
357 
358  ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
359 
361  if (ACPI_FAILURE(status)) {
362  return_ACPI_STATUS(status);
363  }
364 
365  /* Don't allow two handlers. */
366 
368  status = AE_ALREADY_EXISTS;
369  goto cleanup;
370  }
371 
372  /* Install the handler */
373 
374  acpi_gbl_exception_handler = handler;
375 
376  cleanup:
378  return_ACPI_STATUS(status);
379 }
380 
381 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
382 #endif /* ACPI_FUTURE_USAGE */
383 
384 #if (!ACPI_REDUCED_HARDWARE)
385 /*******************************************************************************
386  *
387  * FUNCTION: acpi_install_global_event_handler
388  *
389  * PARAMETERS: handler - Pointer to the global event handler function
390  * context - Value passed to the handler on each event
391  *
392  * RETURN: Status
393  *
394  * DESCRIPTION: Saves the pointer to the handler function. The global handler
395  * is invoked upon each incoming GPE and Fixed Event. It is
396  * invoked at interrupt level at the time of the event dispatch.
397  * Can be used to update event counters, etc.
398  *
399  ******************************************************************************/
402 {
404 
406 
407  /* Parameter validation */
408 
409  if (!handler) {
411  }
412 
414  if (ACPI_FAILURE(status)) {
415  return_ACPI_STATUS(status);
416  }
417 
418  /* Don't allow two handlers. */
419 
421  status = AE_ALREADY_EXISTS;
422  goto cleanup;
423  }
424 
427 
428  cleanup:
430  return_ACPI_STATUS(status);
431 }
432 
434 
435 /*******************************************************************************
436  *
437  * FUNCTION: acpi_install_fixed_event_handler
438  *
439  * PARAMETERS: event - Event type to enable.
440  * handler - Pointer to the handler function for the
441  * event
442  * context - Value passed to the handler on each GPE
443  *
444  * RETURN: Status
445  *
446  * DESCRIPTION: Saves the pointer to the handler function and then enables the
447  * event.
448  *
449  ******************************************************************************/
452  acpi_event_handler handler, void *context)
453 {
455 
457 
458  /* Parameter validation */
459 
460  if (event > ACPI_EVENT_MAX) {
462  }
463 
465  if (ACPI_FAILURE(status)) {
466  return_ACPI_STATUS(status);
467  }
468 
469  /* Don't allow two handlers. */
470 
471  if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
472  status = AE_ALREADY_EXISTS;
473  goto cleanup;
474  }
475 
476  /* Install the handler before enabling the event */
477 
478  acpi_gbl_fixed_event_handlers[event].handler = handler;
480 
481  status = acpi_clear_event(event);
482  if (ACPI_SUCCESS(status))
483  status = acpi_enable_event(event, 0);
484  if (ACPI_FAILURE(status)) {
485  ACPI_WARNING((AE_INFO, "Could not enable fixed event 0x%X",
486  event));
487 
488  /* Remove the handler */
489 
492  } else {
494  "Enabled fixed event %X, Handler=%p\n", event,
495  handler));
496  }
497 
498  cleanup:
500  return_ACPI_STATUS(status);
501 }
502 
504 
505 /*******************************************************************************
506  *
507  * FUNCTION: acpi_remove_fixed_event_handler
508  *
509  * PARAMETERS: event - Event type to disable.
510  * handler - Address of the handler
511  *
512  * RETURN: Status
513  *
514  * DESCRIPTION: Disables the event and unregisters the event handler.
515  *
516  ******************************************************************************/
519 {
520  acpi_status status = AE_OK;
521 
523 
524  /* Parameter validation */
525 
526  if (event > ACPI_EVENT_MAX) {
528  }
529 
531  if (ACPI_FAILURE(status)) {
532  return_ACPI_STATUS(status);
533  }
534 
535  /* Disable the event before removing the handler */
536 
537  status = acpi_disable_event(event, 0);
538 
539  /* Always Remove the handler */
540 
543 
544  if (ACPI_FAILURE(status)) {
546  "Could not write to fixed event enable register 0x%X",
547  event));
548  } else {
549  ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
550  event));
551  }
552 
554  return_ACPI_STATUS(status);
555 }
556 
558 
559 /*******************************************************************************
560  *
561  * FUNCTION: acpi_install_gpe_handler
562  *
563  * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
564  * defined GPEs)
565  * gpe_number - The GPE number within the GPE block
566  * type - Whether this GPE should be treated as an
567  * edge- or level-triggered interrupt.
568  * address - Address of the handler
569  * context - Value passed to the handler on each GPE
570  *
571  * RETURN: Status
572  *
573  * DESCRIPTION: Install a handler for a General Purpose Event.
574  *
575  ******************************************************************************/
578  u32 gpe_number,
580 {
582  struct acpi_gpe_handler_info *handler;
585 
587 
588  /* Parameter validation */
589 
590  if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {
592  }
593 
595  if (ACPI_FAILURE(status)) {
596  return_ACPI_STATUS(status);
597  }
598 
599  /* Allocate memory for the handler object */
600 
601  handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));
602  if (!handler) {
603  status = AE_NO_MEMORY;
604  goto unlock_and_exit;
605  }
606 
608 
609  /* Ensure that we have a valid GPE number */
610 
611  gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
612  if (!gpe_event_info) {
613  status = AE_BAD_PARAMETER;
614  goto free_and_exit;
615  }
616 
617  /* Make sure that there isn't a handler there already */
618 
619  if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
621  status = AE_ALREADY_EXISTS;
622  goto free_and_exit;
623  }
624 
625  /* Allocate and init handler object */
626 
627  handler->address = address;
628  handler->context = context;
629  handler->method_node = gpe_event_info->dispatch.method_node;
630  handler->original_flags = gpe_event_info->flags &
632 
633  /*
634  * If the GPE is associated with a method, it might have been enabled
635  * automatically during initialization, in which case it has to be
636  * disabled now to avoid spurious execution of the handler.
637  */
638 
640  && gpe_event_info->runtime_count) {
641  handler->originally_enabled = 1;
642  (void)acpi_ev_remove_gpe_reference(gpe_event_info);
643  }
644 
645  /* Install the handler */
646 
647  gpe_event_info->dispatch.handler = handler;
648 
649  /* Setup up dispatch flags to indicate handler (vs. method) */
650 
651  gpe_event_info->flags &=
653  gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
654 
656 
657 unlock_and_exit:
659  return_ACPI_STATUS(status);
660 
661 free_and_exit:
663  ACPI_FREE(handler);
664  goto unlock_and_exit;
665 }
666 
668 
669 /*******************************************************************************
670  *
671  * FUNCTION: acpi_remove_gpe_handler
672  *
673  * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
674  * defined GPEs)
675  * gpe_number - The event to remove a handler
676  * address - Address of the handler
677  *
678  * RETURN: Status
679  *
680  * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
681  *
682  ******************************************************************************/
686 {
688  struct acpi_gpe_handler_info *handler;
691 
693 
694  /* Parameter validation */
695 
696  if (!address) {
698  }
699 
700  /* Make sure all deferred tasks are completed */
701 
703 
705  if (ACPI_FAILURE(status)) {
706  return_ACPI_STATUS(status);
707  }
708 
710 
711  /* Ensure that we have a valid GPE number */
712 
713  gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
714  if (!gpe_event_info) {
715  status = AE_BAD_PARAMETER;
716  goto unlock_and_exit;
717  }
718 
719  /* Make sure that a handler is indeed installed */
720 
721  if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
723  status = AE_NOT_EXIST;
724  goto unlock_and_exit;
725  }
726 
727  /* Make sure that the installed handler is the same */
728 
729  if (gpe_event_info->dispatch.handler->address != address) {
730  status = AE_BAD_PARAMETER;
731  goto unlock_and_exit;
732  }
733 
734  /* Remove the handler */
735 
736  handler = gpe_event_info->dispatch.handler;
737 
738  /* Restore Method node (if any), set dispatch flags */
739 
740  gpe_event_info->dispatch.method_node = handler->method_node;
741  gpe_event_info->flags &=
743  gpe_event_info->flags |= handler->original_flags;
744 
745  /*
746  * If the GPE was previously associated with a method and it was
747  * enabled, it should be enabled at this point to restore the
748  * post-initialization configuration.
749  */
750 
752  && handler->originally_enabled)
753  (void)acpi_ev_add_gpe_reference(gpe_event_info);
754 
755  /* Now we can free the handler object */
756 
757  ACPI_FREE(handler);
758 
759 unlock_and_exit:
761 
763  return_ACPI_STATUS(status);
764 }
765 
767 
768 /*******************************************************************************
769  *
770  * FUNCTION: acpi_acquire_global_lock
771  *
772  * PARAMETERS: timeout - How long the caller is willing to wait
773  * handle - Where the handle to the lock is returned
774  * (if acquired)
775  *
776  * RETURN: Status
777  *
778  * DESCRIPTION: Acquire the ACPI Global Lock
779  *
780  * Note: Allows callers with the same thread ID to acquire the global lock
781  * multiple times. In other words, externally, the behavior of the global lock
782  * is identical to an AML mutex. On the first acquire, a new handle is
783  * returned. On any subsequent calls to acquire by the same thread, the same
784  * handle is returned.
785  *
786  ******************************************************************************/
788 {
790 
791  if (!handle) {
792  return (AE_BAD_PARAMETER);
793  }
794 
795  /* Must lock interpreter to prevent race conditions */
796 
798 
799  status = acpi_ex_acquire_mutex_object(timeout,
802 
803  if (ACPI_SUCCESS(status)) {
804 
805  /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
806 
807  *handle = acpi_gbl_global_lock_handle;
808  }
809 
811  return (status);
812 }
813 
815 
816 /*******************************************************************************
817  *
818  * FUNCTION: acpi_release_global_lock
819  *
820  * PARAMETERS: handle - Returned from acpi_acquire_global_lock
821  *
822  * RETURN: Status
823  *
824  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
825  *
826  ******************************************************************************/
828 {
830 
831  if (!handle || (handle != acpi_gbl_global_lock_handle)) {
832  return (AE_NOT_ACQUIRED);
833  }
834 
836  return (status);
837 }
838 
840 #endif /* !ACPI_REDUCED_HARDWARE */