ia64/linux-2.6.18-xen.hg

view drivers/acpi/events/evmisc.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: evmisc - Miscellaneous event manager support functions
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/acevents.h>
46 #include <acpi/acnamesp.h>
47 #include <acpi/acinterp.h>
49 #define _COMPONENT ACPI_EVENTS
50 ACPI_MODULE_NAME("evmisc")
52 /* Names for Notify() values, used for debug output */
53 #ifdef ACPI_DEBUG_OUTPUT
54 static const char *acpi_notify_value_names[] = {
55 "Bus Check",
56 "Device Check",
57 "Device Wake",
58 "Eject Request",
59 "Device Check Light",
60 "Frequency Mismatch",
61 "Bus Mode Mismatch",
62 "Power Fault"
63 };
64 #endif
66 /* Local prototypes */
68 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
70 static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context);
72 static u32 acpi_ev_global_lock_handler(void *context);
74 /*******************************************************************************
75 *
76 * FUNCTION: acpi_ev_is_notify_object
77 *
78 * PARAMETERS: Node - Node to check
79 *
80 * RETURN: TRUE if notifies allowed on this object
81 *
82 * DESCRIPTION: Check type of node for a object that supports notifies.
83 *
84 * TBD: This could be replaced by a flag bit in the node.
85 *
86 ******************************************************************************/
88 u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
89 {
90 switch (node->type) {
91 case ACPI_TYPE_DEVICE:
92 case ACPI_TYPE_PROCESSOR:
93 case ACPI_TYPE_POWER:
94 case ACPI_TYPE_THERMAL:
95 /*
96 * These are the ONLY objects that can receive ACPI notifications
97 */
98 return (TRUE);
100 default:
101 return (FALSE);
102 }
103 }
105 /*******************************************************************************
106 *
107 * FUNCTION: acpi_ev_queue_notify_request
108 *
109 * PARAMETERS: Node - NS node for the notified object
110 * notify_value - Value from the Notify() request
111 *
112 * RETURN: Status
113 *
114 * DESCRIPTION: Dispatch a device notification event to a previously
115 * installed handler.
116 *
117 ******************************************************************************/
119 acpi_status
120 acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
121 u32 notify_value)
122 {
123 union acpi_operand_object *obj_desc;
124 union acpi_operand_object *handler_obj = NULL;
125 union acpi_generic_state *notify_info;
126 acpi_status status = AE_OK;
128 ACPI_FUNCTION_NAME(ev_queue_notify_request);
130 /*
131 * For value 3 (Ejection Request), some device method may need to be run.
132 * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need
133 * to be run.
134 * For value 0x80 (Status Change) on the power button or sleep button,
135 * initiate soft-off or sleep operation?
136 */
137 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
138 "Dispatching Notify(%X) on node %p\n", notify_value,
139 node));
141 if (notify_value <= 7) {
142 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notify value: %s\n",
143 acpi_notify_value_names[notify_value]));
144 } else {
145 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
146 "Notify value: 0x%2.2X **Device Specific**\n",
147 notify_value));
148 }
150 /* Get the notify object attached to the NS Node */
152 obj_desc = acpi_ns_get_attached_object(node);
153 if (obj_desc) {
155 /* We have the notify object, Get the right handler */
157 switch (node->type) {
158 case ACPI_TYPE_DEVICE:
159 case ACPI_TYPE_THERMAL:
160 case ACPI_TYPE_PROCESSOR:
161 case ACPI_TYPE_POWER:
163 if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
164 handler_obj =
165 obj_desc->common_notify.system_notify;
166 } else {
167 handler_obj =
168 obj_desc->common_notify.device_notify;
169 }
170 break;
172 default:
173 /* All other types are not supported */
174 return (AE_TYPE);
175 }
176 }
178 /* If there is any handler to run, schedule the dispatcher */
180 if ((acpi_gbl_system_notify.handler
181 && (notify_value <= ACPI_MAX_SYS_NOTIFY))
182 || (acpi_gbl_device_notify.handler
183 && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) {
184 notify_info = acpi_ut_create_generic_state();
185 if (!notify_info) {
186 return (AE_NO_MEMORY);
187 }
189 notify_info->common.descriptor_type =
190 ACPI_DESC_TYPE_STATE_NOTIFY;
191 notify_info->notify.node = node;
192 notify_info->notify.value = (u16) notify_value;
193 notify_info->notify.handler_obj = handler_obj;
195 status =
196 acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
197 notify_info);
198 if (ACPI_FAILURE(status)) {
199 acpi_ut_delete_generic_state(notify_info);
200 }
201 }
203 if (!handler_obj) {
204 /*
205 * There is no per-device notify handler for this device.
206 * This may or may not be a problem.
207 */
208 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
209 "No notify handler for Notify(%4.4s, %X) node %p\n",
210 acpi_ut_get_node_name(node), notify_value,
211 node));
212 }
214 return (status);
215 }
217 /*******************************************************************************
218 *
219 * FUNCTION: acpi_ev_notify_dispatch
220 *
221 * PARAMETERS: Context - To be passed to the notify handler
222 *
223 * RETURN: None.
224 *
225 * DESCRIPTION: Dispatch a device notification event to a previously
226 * installed handler.
227 *
228 ******************************************************************************/
230 static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
231 {
232 union acpi_generic_state *notify_info =
233 (union acpi_generic_state *)context;
234 acpi_notify_handler global_handler = NULL;
235 void *global_context = NULL;
236 union acpi_operand_object *handler_obj;
238 ACPI_FUNCTION_ENTRY();
240 /*
241 * We will invoke a global notify handler if installed.
242 * This is done _before_ we invoke the per-device handler attached
243 * to the device.
244 */
245 if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) {
247 /* Global system notification handler */
249 if (acpi_gbl_system_notify.handler) {
250 global_handler = acpi_gbl_system_notify.handler;
251 global_context = acpi_gbl_system_notify.context;
252 }
253 } else {
254 /* Global driver notification handler */
256 if (acpi_gbl_device_notify.handler) {
257 global_handler = acpi_gbl_device_notify.handler;
258 global_context = acpi_gbl_device_notify.context;
259 }
260 }
262 /* Invoke the system handler first, if present */
264 if (global_handler) {
265 global_handler(notify_info->notify.node,
266 notify_info->notify.value, global_context);
267 }
269 /* Now invoke the per-device handler, if present */
271 handler_obj = notify_info->notify.handler_obj;
272 if (handler_obj) {
273 handler_obj->notify.handler(notify_info->notify.node,
274 notify_info->notify.value,
275 handler_obj->notify.context);
276 }
278 /* All done with the info object */
280 acpi_ut_delete_generic_state(notify_info);
281 }
283 /*******************************************************************************
284 *
285 * FUNCTION: acpi_ev_global_lock_thread
286 *
287 * PARAMETERS: Context - From thread interface, not used
288 *
289 * RETURN: None
290 *
291 * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
292 * Global Lock. Simply signal all threads that are waiting
293 * for the lock.
294 *
295 ******************************************************************************/
297 static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
298 {
299 acpi_status status;
301 /* Signal threads that are waiting for the lock */
303 if (acpi_gbl_global_lock_thread_count) {
305 /* Send sufficient units to the semaphore */
307 status =
308 acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore,
309 acpi_gbl_global_lock_thread_count);
310 if (ACPI_FAILURE(status)) {
311 ACPI_ERROR((AE_INFO,
312 "Could not signal Global Lock semaphore"));
313 }
314 }
315 }
317 /*******************************************************************************
318 *
319 * FUNCTION: acpi_ev_global_lock_handler
320 *
321 * PARAMETERS: Context - From thread interface, not used
322 *
323 * RETURN: ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED
324 *
325 * DESCRIPTION: Invoked directly from the SCI handler when a global lock
326 * release interrupt occurs. Grab the global lock and queue
327 * the global lock thread for execution
328 *
329 ******************************************************************************/
331 static u32 acpi_ev_global_lock_handler(void *context)
332 {
333 u8 acquired = FALSE;
334 acpi_status status;
336 /*
337 * Attempt to get the lock
338 * If we don't get it now, it will be marked pending and we will
339 * take another interrupt when it becomes free.
340 */
341 ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
342 if (acquired) {
344 /* Got the lock, now wake all threads waiting for it */
346 acpi_gbl_global_lock_acquired = TRUE;
348 /* Run the Global Lock thread which will signal all waiting threads */
350 status =
351 acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER,
352 acpi_ev_global_lock_thread, context);
353 if (ACPI_FAILURE(status)) {
354 ACPI_EXCEPTION((AE_INFO, status,
355 "Could not queue Global Lock thread"));
357 return (ACPI_INTERRUPT_NOT_HANDLED);
358 }
359 }
361 return (ACPI_INTERRUPT_HANDLED);
362 }
364 /*******************************************************************************
365 *
366 * FUNCTION: acpi_ev_init_global_lock_handler
367 *
368 * PARAMETERS: None
369 *
370 * RETURN: Status
371 *
372 * DESCRIPTION: Install a handler for the global lock release event
373 *
374 ******************************************************************************/
376 acpi_status acpi_ev_init_global_lock_handler(void)
377 {
378 acpi_status status;
380 ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
382 acpi_gbl_global_lock_present = TRUE;
383 status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
384 acpi_ev_global_lock_handler,
385 NULL);
387 /*
388 * If the global lock does not exist on this platform, the attempt
389 * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick)
390 * Map to AE_OK, but mark global lock as not present.
391 * Any attempt to actually use the global lock will be flagged
392 * with an error.
393 */
394 if (status == AE_NO_HARDWARE_RESPONSE) {
395 ACPI_ERROR((AE_INFO,
396 "No response from Global Lock hardware, disabling lock"));
398 acpi_gbl_global_lock_present = FALSE;
399 status = AE_OK;
400 }
402 return_ACPI_STATUS(status);
403 }
405 /******************************************************************************
406 *
407 * FUNCTION: acpi_ev_acquire_global_lock
408 *
409 * PARAMETERS: Timeout - Max time to wait for the lock, in millisec.
410 *
411 * RETURN: Status
412 *
413 * DESCRIPTION: Attempt to gain ownership of the Global Lock.
414 *
415 *****************************************************************************/
417 acpi_status acpi_ev_acquire_global_lock(u16 timeout)
418 {
419 acpi_status status = AE_OK;
420 u8 acquired = FALSE;
422 ACPI_FUNCTION_TRACE(ev_acquire_global_lock);
424 #ifndef ACPI_APPLICATION
425 /* Make sure that we actually have a global lock */
427 if (!acpi_gbl_global_lock_present) {
428 return_ACPI_STATUS(AE_NO_GLOBAL_LOCK);
429 }
430 #endif
432 /* One more thread wants the global lock */
434 acpi_gbl_global_lock_thread_count++;
436 /*
437 * If we (OS side vs. BIOS side) have the hardware lock already,
438 * we are done
439 */
440 if (acpi_gbl_global_lock_acquired) {
441 return_ACPI_STATUS(AE_OK);
442 }
444 /* We must acquire the actual hardware lock */
446 ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
447 if (acquired) {
449 /* We got the lock */
451 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
452 "Acquired the HW Global Lock\n"));
454 acpi_gbl_global_lock_acquired = TRUE;
455 return_ACPI_STATUS(AE_OK);
456 }
458 /*
459 * Did not get the lock. The pending bit was set above, and we must now
460 * wait until we get the global lock released interrupt.
461 */
462 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
464 /*
465 * Acquire the global lock semaphore first.
466 * Since this wait will block, we must release the interpreter
467 */
468 status =
469 acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
470 timeout);
471 return_ACPI_STATUS(status);
472 }
474 /*******************************************************************************
475 *
476 * FUNCTION: acpi_ev_release_global_lock
477 *
478 * PARAMETERS: None
479 *
480 * RETURN: Status
481 *
482 * DESCRIPTION: Releases ownership of the Global Lock.
483 *
484 ******************************************************************************/
486 acpi_status acpi_ev_release_global_lock(void)
487 {
488 u8 pending = FALSE;
489 acpi_status status = AE_OK;
491 ACPI_FUNCTION_TRACE(ev_release_global_lock);
493 if (!acpi_gbl_global_lock_thread_count) {
494 ACPI_WARNING((AE_INFO,
495 "Cannot release HW Global Lock, it has not been acquired"));
496 return_ACPI_STATUS(AE_NOT_ACQUIRED);
497 }
499 /* One fewer thread has the global lock */
501 acpi_gbl_global_lock_thread_count--;
502 if (acpi_gbl_global_lock_thread_count) {
504 /* There are still some threads holding the lock, cannot release */
506 return_ACPI_STATUS(AE_OK);
507 }
509 /*
510 * No more threads holding lock, we can do the actual hardware
511 * release
512 */
513 ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, pending);
514 acpi_gbl_global_lock_acquired = FALSE;
516 /*
517 * If the pending bit was set, we must write GBL_RLS to the control
518 * register
519 */
520 if (pending) {
521 status = acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE,
522 1, ACPI_MTX_LOCK);
523 }
525 return_ACPI_STATUS(status);
526 }
528 /******************************************************************************
529 *
530 * FUNCTION: acpi_ev_terminate
531 *
532 * PARAMETERS: none
533 *
534 * RETURN: none
535 *
536 * DESCRIPTION: Disable events and free memory allocated for table storage.
537 *
538 ******************************************************************************/
540 void acpi_ev_terminate(void)
541 {
542 acpi_native_uint i;
543 acpi_status status;
545 ACPI_FUNCTION_TRACE(ev_terminate);
547 if (acpi_gbl_events_initialized) {
548 /*
549 * Disable all event-related functionality.
550 * In all cases, on error, print a message but obviously we don't abort.
551 */
553 /* Disable all fixed events */
555 for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
556 status = acpi_disable_event((u32) i, 0);
557 if (ACPI_FAILURE(status)) {
558 ACPI_ERROR((AE_INFO,
559 "Could not disable fixed event %d",
560 (u32) i));
561 }
562 }
564 /* Disable all GPEs in all GPE blocks */
566 status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);
568 /* Remove SCI handler */
570 status = acpi_ev_remove_sci_handler();
571 if (ACPI_FAILURE(status)) {
572 ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
573 }
574 }
576 /* Deallocate all handler objects installed within GPE info structs */
578 status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers);
580 /* Return to original mode if necessary */
582 if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
583 status = acpi_disable();
584 if (ACPI_FAILURE(status)) {
585 ACPI_WARNING((AE_INFO, "AcpiDisable failed"));
586 }
587 }
588 return_VOID;
589 }