ia64/linux-2.6.18-xen.hg

view drivers/acpi/events/evxface.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /******************************************************************************
2 *
3 * Module Name: evxface - External interfaces for ACPI events
4 *
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2006, R. Byron Moore
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 */
44 #include <acpi/acpi.h>
45 #include <acpi/acnamesp.h>
46 #include <acpi/acevents.h>
47 #include <acpi/acinterp.h>
49 #define _COMPONENT ACPI_EVENTS
50 ACPI_MODULE_NAME("evxface")
52 /*******************************************************************************
53 *
54 * FUNCTION: acpi_install_exception_handler
55 *
56 * PARAMETERS: Handler - Pointer to the handler function for the
57 * event
58 *
59 * RETURN: Status
60 *
61 * DESCRIPTION: Saves the pointer to the handler function
62 *
63 ******************************************************************************/
64 #ifdef ACPI_FUTURE_USAGE
65 acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
66 {
67 acpi_status status;
69 ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
71 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
72 if (ACPI_FAILURE(status)) {
73 return_ACPI_STATUS(status);
74 }
76 /* Don't allow two handlers. */
78 if (acpi_gbl_exception_handler) {
79 status = AE_ALREADY_EXISTS;
80 goto cleanup;
81 }
83 /* Install the handler */
85 acpi_gbl_exception_handler = handler;
87 cleanup:
88 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
89 return_ACPI_STATUS(status);
90 }
92 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
93 #endif /* ACPI_FUTURE_USAGE */
95 /*******************************************************************************
96 *
97 * FUNCTION: acpi_install_fixed_event_handler
98 *
99 * PARAMETERS: Event - Event type to enable.
100 * Handler - Pointer to the handler function for the
101 * event
102 * Context - Value passed to the handler on each GPE
103 *
104 * RETURN: Status
105 *
106 * DESCRIPTION: Saves the pointer to the handler function and then enables the
107 * event.
108 *
109 ******************************************************************************/
110 acpi_status
111 acpi_install_fixed_event_handler(u32 event,
112 acpi_event_handler handler, void *context)
113 {
114 acpi_status status;
116 ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
118 /* Parameter validation */
120 if (event > ACPI_EVENT_MAX) {
121 return_ACPI_STATUS(AE_BAD_PARAMETER);
122 }
124 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
125 if (ACPI_FAILURE(status)) {
126 return_ACPI_STATUS(status);
127 }
129 /* Don't allow two handlers. */
131 if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
132 status = AE_ALREADY_EXISTS;
133 goto cleanup;
134 }
136 /* Install the handler before enabling the event */
138 acpi_gbl_fixed_event_handlers[event].handler = handler;
139 acpi_gbl_fixed_event_handlers[event].context = context;
141 status = acpi_clear_event(event);
142 if (ACPI_SUCCESS(status))
143 status = acpi_enable_event(event, 0);
144 if (ACPI_FAILURE(status)) {
145 ACPI_WARNING((AE_INFO, "Could not enable fixed event %X",
146 event));
148 /* Remove the handler */
150 acpi_gbl_fixed_event_handlers[event].handler = NULL;
151 acpi_gbl_fixed_event_handlers[event].context = NULL;
152 } else {
153 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
154 "Enabled fixed event %X, Handler=%p\n", event,
155 handler));
156 }
158 cleanup:
159 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
160 return_ACPI_STATUS(status);
161 }
163 ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
165 /*******************************************************************************
166 *
167 * FUNCTION: acpi_remove_fixed_event_handler
168 *
169 * PARAMETERS: Event - Event type to disable.
170 * Handler - Address of the handler
171 *
172 * RETURN: Status
173 *
174 * DESCRIPTION: Disables the event and unregisters the event handler.
175 *
176 ******************************************************************************/
177 acpi_status
178 acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
179 {
180 acpi_status status = AE_OK;
182 ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
184 /* Parameter validation */
186 if (event > ACPI_EVENT_MAX) {
187 return_ACPI_STATUS(AE_BAD_PARAMETER);
188 }
190 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
191 if (ACPI_FAILURE(status)) {
192 return_ACPI_STATUS(status);
193 }
195 /* Disable the event before removing the handler */
197 status = acpi_disable_event(event, 0);
199 /* Always Remove the handler */
201 acpi_gbl_fixed_event_handlers[event].handler = NULL;
202 acpi_gbl_fixed_event_handlers[event].context = NULL;
204 if (ACPI_FAILURE(status)) {
205 ACPI_WARNING((AE_INFO,
206 "Could not write to fixed event enable register %X",
207 event));
208 } else {
209 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabled fixed event %X\n",
210 event));
211 }
213 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
214 return_ACPI_STATUS(status);
215 }
217 ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
219 /*******************************************************************************
220 *
221 * FUNCTION: acpi_install_notify_handler
222 *
223 * PARAMETERS: Device - The device for which notifies will be handled
224 * handler_type - The type of handler:
225 * ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
226 * ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
227 * ACPI_ALL_NOTIFY: both system and device
228 * Handler - Address of the handler
229 * Context - Value passed to the handler on each GPE
230 *
231 * RETURN: Status
232 *
233 * DESCRIPTION: Install a handler for notifies on an ACPI device
234 *
235 ******************************************************************************/
236 acpi_status
237 acpi_install_notify_handler(acpi_handle device,
238 u32 handler_type,
239 acpi_notify_handler handler, void *context)
240 {
241 union acpi_operand_object *obj_desc;
242 union acpi_operand_object *notify_obj;
243 struct acpi_namespace_node *node;
244 acpi_status status;
246 ACPI_FUNCTION_TRACE(acpi_install_notify_handler);
248 /* Parameter validation */
250 if ((!device) ||
251 (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
252 return_ACPI_STATUS(AE_BAD_PARAMETER);
253 }
255 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
256 if (ACPI_FAILURE(status)) {
257 return_ACPI_STATUS(status);
258 }
260 /* Convert and validate the device handle */
262 node = acpi_ns_map_handle_to_node(device);
263 if (!node) {
264 status = AE_BAD_PARAMETER;
265 goto unlock_and_exit;
266 }
268 /*
269 * Root Object:
270 * Registering a notify handler on the root object indicates that the
271 * caller wishes to receive notifications for all objects. Note that
272 * only one <external> global handler can be regsitered (per notify type).
273 */
274 if (device == ACPI_ROOT_OBJECT) {
276 /* Make sure the handler is not already installed */
278 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
279 acpi_gbl_system_notify.handler) ||
280 ((handler_type & ACPI_DEVICE_NOTIFY) &&
281 acpi_gbl_device_notify.handler)) {
282 status = AE_ALREADY_EXISTS;
283 goto unlock_and_exit;
284 }
286 if (handler_type & ACPI_SYSTEM_NOTIFY) {
287 acpi_gbl_system_notify.node = node;
288 acpi_gbl_system_notify.handler = handler;
289 acpi_gbl_system_notify.context = context;
290 }
292 if (handler_type & ACPI_DEVICE_NOTIFY) {
293 acpi_gbl_device_notify.node = node;
294 acpi_gbl_device_notify.handler = handler;
295 acpi_gbl_device_notify.context = context;
296 }
298 /* Global notify handler installed */
299 }
301 /*
302 * All Other Objects:
303 * Caller will only receive notifications specific to the target object.
304 * Note that only certain object types can receive notifications.
305 */
306 else {
307 /* Notifies allowed on this object? */
309 if (!acpi_ev_is_notify_object(node)) {
310 status = AE_TYPE;
311 goto unlock_and_exit;
312 }
314 /* Check for an existing internal object */
316 obj_desc = acpi_ns_get_attached_object(node);
317 if (obj_desc) {
319 /* Object exists - make sure there's no handler */
321 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
322 obj_desc->common_notify.system_notify) ||
323 ((handler_type & ACPI_DEVICE_NOTIFY) &&
324 obj_desc->common_notify.device_notify)) {
325 status = AE_ALREADY_EXISTS;
326 goto unlock_and_exit;
327 }
328 } else {
329 /* Create a new object */
331 obj_desc = acpi_ut_create_internal_object(node->type);
332 if (!obj_desc) {
333 status = AE_NO_MEMORY;
334 goto unlock_and_exit;
335 }
337 /* Attach new object to the Node */
339 status =
340 acpi_ns_attach_object(device, obj_desc, node->type);
342 /* Remove local reference to the object */
344 acpi_ut_remove_reference(obj_desc);
345 if (ACPI_FAILURE(status)) {
346 goto unlock_and_exit;
347 }
348 }
350 /* Install the handler */
352 notify_obj =
353 acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
354 if (!notify_obj) {
355 status = AE_NO_MEMORY;
356 goto unlock_and_exit;
357 }
359 notify_obj->notify.node = node;
360 notify_obj->notify.handler = handler;
361 notify_obj->notify.context = context;
363 if (handler_type & ACPI_SYSTEM_NOTIFY) {
364 obj_desc->common_notify.system_notify = notify_obj;
365 }
367 if (handler_type & ACPI_DEVICE_NOTIFY) {
368 obj_desc->common_notify.device_notify = notify_obj;
369 }
371 if (handler_type == ACPI_ALL_NOTIFY) {
373 /* Extra ref if installed in both */
375 acpi_ut_add_reference(notify_obj);
376 }
377 }
379 unlock_and_exit:
380 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
381 return_ACPI_STATUS(status);
382 }
384 ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)
386 /*******************************************************************************
387 *
388 * FUNCTION: acpi_remove_notify_handler
389 *
390 * PARAMETERS: Device - The device for which notifies will be handled
391 * handler_type - The type of handler:
392 * ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
393 * ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
394 * ACPI_ALL_NOTIFY: both system and device
395 * Handler - Address of the handler
396 *
397 * RETURN: Status
398 *
399 * DESCRIPTION: Remove a handler for notifies on an ACPI device
400 *
401 ******************************************************************************/
402 acpi_status
403 acpi_remove_notify_handler(acpi_handle device,
404 u32 handler_type, acpi_notify_handler handler)
405 {
406 union acpi_operand_object *notify_obj;
407 union acpi_operand_object *obj_desc;
408 struct acpi_namespace_node *node;
409 acpi_status status;
411 ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
413 /* Parameter validation */
415 if ((!device) ||
416 (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
417 status = AE_BAD_PARAMETER;
418 goto exit;
419 }
421 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
422 if (ACPI_FAILURE(status)) {
423 goto exit;
424 }
426 /* Convert and validate the device handle */
428 node = acpi_ns_map_handle_to_node(device);
429 if (!node) {
430 status = AE_BAD_PARAMETER;
431 goto unlock_and_exit;
432 }
434 /* Root Object */
436 if (device == ACPI_ROOT_OBJECT) {
437 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
438 "Removing notify handler for namespace root object\n"));
440 if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
441 !acpi_gbl_system_notify.handler) ||
442 ((handler_type & ACPI_DEVICE_NOTIFY) &&
443 !acpi_gbl_device_notify.handler)) {
444 status = AE_NOT_EXIST;
445 goto unlock_and_exit;
446 }
448 /* Make sure all deferred tasks are completed */
450 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
451 acpi_os_wait_events_complete(NULL);
452 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
453 if (ACPI_FAILURE(status)) {
454 goto exit;
455 }
457 if (handler_type & ACPI_SYSTEM_NOTIFY) {
458 acpi_gbl_system_notify.node = NULL;
459 acpi_gbl_system_notify.handler = NULL;
460 acpi_gbl_system_notify.context = NULL;
461 }
463 if (handler_type & ACPI_DEVICE_NOTIFY) {
464 acpi_gbl_device_notify.node = NULL;
465 acpi_gbl_device_notify.handler = NULL;
466 acpi_gbl_device_notify.context = NULL;
467 }
468 }
470 /* All Other Objects */
472 else {
473 /* Notifies allowed on this object? */
475 if (!acpi_ev_is_notify_object(node)) {
476 status = AE_TYPE;
477 goto unlock_and_exit;
478 }
480 /* Check for an existing internal object */
482 obj_desc = acpi_ns_get_attached_object(node);
483 if (!obj_desc) {
484 status = AE_NOT_EXIST;
485 goto unlock_and_exit;
486 }
488 /* Object exists - make sure there's an existing handler */
490 if (handler_type & ACPI_SYSTEM_NOTIFY) {
491 notify_obj = obj_desc->common_notify.system_notify;
492 if (!notify_obj) {
493 status = AE_NOT_EXIST;
494 goto unlock_and_exit;
495 }
497 if (notify_obj->notify.handler != handler) {
498 status = AE_BAD_PARAMETER;
499 goto unlock_and_exit;
500 }
501 /* Make sure all deferred tasks are completed */
503 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
504 acpi_os_wait_events_complete(NULL);
505 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
506 if (ACPI_FAILURE(status)) {
507 goto exit;
508 }
510 /* Remove the handler */
511 obj_desc->common_notify.system_notify = NULL;
512 acpi_ut_remove_reference(notify_obj);
513 }
515 if (handler_type & ACPI_DEVICE_NOTIFY) {
516 notify_obj = obj_desc->common_notify.device_notify;
517 if (!notify_obj) {
518 status = AE_NOT_EXIST;
519 goto unlock_and_exit;
520 }
522 if (notify_obj->notify.handler != handler) {
523 status = AE_BAD_PARAMETER;
524 goto unlock_and_exit;
525 }
526 /* Make sure all deferred tasks are completed */
528 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
529 acpi_os_wait_events_complete(NULL);
530 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
531 if (ACPI_FAILURE(status)) {
532 goto exit;
533 }
535 /* Remove the handler */
536 obj_desc->common_notify.device_notify = NULL;
537 acpi_ut_remove_reference(notify_obj);
538 }
539 }
541 unlock_and_exit:
542 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
543 exit:
544 if (ACPI_FAILURE(status))
545 ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler"));
546 return_ACPI_STATUS(status);
547 }
549 ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)
551 /*******************************************************************************
552 *
553 * FUNCTION: acpi_install_gpe_handler
554 *
555 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
556 * defined GPEs)
557 * gpe_number - The GPE number within the GPE block
558 * Type - Whether this GPE should be treated as an
559 * edge- or level-triggered interrupt.
560 * Address - Address of the handler
561 * Context - Value passed to the handler on each GPE
562 *
563 * RETURN: Status
564 *
565 * DESCRIPTION: Install a handler for a General Purpose Event.
566 *
567 ******************************************************************************/
568 acpi_status
569 acpi_install_gpe_handler(acpi_handle gpe_device,
570 u32 gpe_number,
571 u32 type, acpi_event_handler address, void *context)
572 {
573 struct acpi_gpe_event_info *gpe_event_info;
574 struct acpi_handler_info *handler;
575 acpi_status status;
576 acpi_cpu_flags flags;
578 ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
580 /* Parameter validation */
582 if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
583 status = AE_BAD_PARAMETER;
584 goto exit;
585 }
587 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
588 if (ACPI_FAILURE(status)) {
589 goto exit;
590 }
592 /* Ensure that we have a valid GPE number */
594 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
595 if (!gpe_event_info) {
596 status = AE_BAD_PARAMETER;
597 goto unlock_and_exit;
598 }
600 /* Make sure that there isn't a handler there already */
602 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
603 ACPI_GPE_DISPATCH_HANDLER) {
604 status = AE_ALREADY_EXISTS;
605 goto unlock_and_exit;
606 }
608 /* Allocate and init handler object */
610 handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info));
611 if (!handler) {
612 status = AE_NO_MEMORY;
613 goto unlock_and_exit;
614 }
616 handler->address = address;
617 handler->context = context;
618 handler->method_node = gpe_event_info->dispatch.method_node;
620 /* Disable the GPE before installing the handler */
622 status = acpi_ev_disable_gpe(gpe_event_info);
623 if (ACPI_FAILURE(status)) {
624 goto unlock_and_exit;
625 }
627 /* Install the handler */
629 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
630 gpe_event_info->dispatch.handler = handler;
632 /* Setup up dispatch flags to indicate handler (vs. method) */
634 gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
635 gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
637 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
639 unlock_and_exit:
640 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
641 exit:
642 if (ACPI_FAILURE(status))
643 ACPI_EXCEPTION((AE_INFO, status,
644 "Installing notify handler failed"));
645 return_ACPI_STATUS(status);
646 }
648 ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
650 /*******************************************************************************
651 *
652 * FUNCTION: acpi_remove_gpe_handler
653 *
654 * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
655 * defined GPEs)
656 * gpe_number - The event to remove a handler
657 * Address - Address of the handler
658 *
659 * RETURN: Status
660 *
661 * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
662 *
663 ******************************************************************************/
664 acpi_status
665 acpi_remove_gpe_handler(acpi_handle gpe_device,
666 u32 gpe_number, acpi_event_handler address)
667 {
668 struct acpi_gpe_event_info *gpe_event_info;
669 struct acpi_handler_info *handler;
670 acpi_status status;
671 acpi_cpu_flags flags;
673 ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);
675 /* Parameter validation */
677 if (!address) {
678 return_ACPI_STATUS(AE_BAD_PARAMETER);
679 }
681 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
682 if (ACPI_FAILURE(status)) {
683 return_ACPI_STATUS(status);
684 }
686 /* Ensure that we have a valid GPE number */
688 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
689 if (!gpe_event_info) {
690 status = AE_BAD_PARAMETER;
691 goto unlock_and_exit;
692 }
694 /* Make sure that a handler is indeed installed */
696 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
697 ACPI_GPE_DISPATCH_HANDLER) {
698 status = AE_NOT_EXIST;
699 goto unlock_and_exit;
700 }
702 /* Make sure that the installed handler is the same */
704 if (gpe_event_info->dispatch.handler->address != address) {
705 status = AE_BAD_PARAMETER;
706 goto unlock_and_exit;
707 }
709 /* Disable the GPE before removing the handler */
711 status = acpi_ev_disable_gpe(gpe_event_info);
712 if (ACPI_FAILURE(status)) {
713 goto unlock_and_exit;
714 }
716 /* Make sure all deferred tasks are completed */
718 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
719 acpi_os_wait_events_complete(NULL);
720 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
721 if (ACPI_FAILURE(status)) {
722 return_ACPI_STATUS(status);
723 }
725 /* Remove the handler */
727 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
728 handler = gpe_event_info->dispatch.handler;
730 /* Restore Method node (if any), set dispatch flags */
732 gpe_event_info->dispatch.method_node = handler->method_node;
733 gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
734 if (handler->method_node) {
735 gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
736 }
737 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
739 /* Now we can free the handler object */
741 ACPI_FREE(handler);
743 unlock_and_exit:
744 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
745 return_ACPI_STATUS(status);
746 }
748 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
750 /*******************************************************************************
751 *
752 * FUNCTION: acpi_acquire_global_lock
753 *
754 * PARAMETERS: Timeout - How long the caller is willing to wait
755 * Handle - Where the handle to the lock is returned
756 * (if acquired)
757 *
758 * RETURN: Status
759 *
760 * DESCRIPTION: Acquire the ACPI Global Lock
761 *
762 ******************************************************************************/
763 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
764 {
765 acpi_status status;
767 if (!handle) {
768 return (AE_BAD_PARAMETER);
769 }
771 status = acpi_ex_enter_interpreter();
772 if (ACPI_FAILURE(status)) {
773 return (status);
774 }
776 status = acpi_ev_acquire_global_lock(timeout);
777 acpi_ex_exit_interpreter();
779 if (ACPI_SUCCESS(status)) {
780 acpi_gbl_global_lock_handle++;
781 *handle = acpi_gbl_global_lock_handle;
782 }
784 return (status);
785 }
787 ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)
789 /*******************************************************************************
790 *
791 * FUNCTION: acpi_release_global_lock
792 *
793 * PARAMETERS: Handle - Returned from acpi_acquire_global_lock
794 *
795 * RETURN: Status
796 *
797 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
798 *
799 ******************************************************************************/
800 acpi_status acpi_release_global_lock(u32 handle)
801 {
802 acpi_status status;
804 if (handle != acpi_gbl_global_lock_handle) {
805 return (AE_NOT_ACQUIRED);
806 }
808 status = acpi_ev_release_global_lock();
809 return (status);
810 }
812 ACPI_EXPORT_SYMBOL(acpi_release_global_lock)