ia64/linux-2.6.18-xen.hg

annotate drivers/acpi/utils.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
rev   line source
ian@0 1 /*
ian@0 2 * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
ian@0 3 *
ian@0 4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
ian@0 5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
ian@0 6 *
ian@0 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ian@0 8 *
ian@0 9 * This program is free software; you can redistribute it and/or modify
ian@0 10 * it under the terms of the GNU General Public License as published by
ian@0 11 * the Free Software Foundation; either version 2 of the License, or (at
ian@0 12 * your option) any later version.
ian@0 13 *
ian@0 14 * This program is distributed in the hope that it will be useful, but
ian@0 15 * WITHOUT ANY WARRANTY; without even the implied warranty of
ian@0 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ian@0 17 * General Public License for more details.
ian@0 18 *
ian@0 19 * You should have received a copy of the GNU General Public License along
ian@0 20 * with this program; if not, write to the Free Software Foundation, Inc.,
ian@0 21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
ian@0 22 *
ian@0 23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ian@0 24 */
ian@0 25
ian@0 26 #include <linux/kernel.h>
ian@0 27 #include <linux/module.h>
ian@0 28 #include <linux/init.h>
ian@0 29 #include <linux/types.h>
ian@0 30 #include <acpi/acpi_bus.h>
ian@0 31 #include <acpi/acpi_drivers.h>
ian@0 32
ian@0 33 #define _COMPONENT ACPI_BUS_COMPONENT
ian@0 34 ACPI_MODULE_NAME("acpi_utils")
ian@0 35
ian@0 36 /* --------------------------------------------------------------------------
ian@0 37 Object Evaluation Helpers
ian@0 38 -------------------------------------------------------------------------- */
ian@0 39 #ifdef ACPI_DEBUG_OUTPUT
ian@0 40 #define acpi_util_eval_error(h,p,s) {\
ian@0 41 char prefix[80] = {'\0'};\
ian@0 42 struct acpi_buffer buffer = {sizeof(prefix), prefix};\
ian@0 43 acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
ian@0 44 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",\
ian@0 45 (char *) prefix, p, acpi_format_exception(s))); }
ian@0 46 #else
ian@0 47 #define acpi_util_eval_error(h,p,s)
ian@0 48 #endif
ian@0 49 acpi_status
ian@0 50 acpi_extract_package(union acpi_object *package,
ian@0 51 struct acpi_buffer *format, struct acpi_buffer *buffer)
ian@0 52 {
ian@0 53 u32 size_required = 0;
ian@0 54 u32 tail_offset = 0;
ian@0 55 char *format_string = NULL;
ian@0 56 u32 format_count = 0;
ian@0 57 u32 i = 0;
ian@0 58 u8 *head = NULL;
ian@0 59 u8 *tail = NULL;
ian@0 60
ian@0 61
ian@0 62 if (!package || (package->type != ACPI_TYPE_PACKAGE)
ian@0 63 || (package->package.count < 1)) {
ian@0 64 printk(KERN_WARNING PREFIX "Invalid package argument\n");
ian@0 65 return AE_BAD_PARAMETER;
ian@0 66 }
ian@0 67
ian@0 68 if (!format || !format->pointer || (format->length < 1)) {
ian@0 69 printk(KERN_WARNING PREFIX "Invalid format argument\n");
ian@0 70 return AE_BAD_PARAMETER;
ian@0 71 }
ian@0 72
ian@0 73 if (!buffer) {
ian@0 74 printk(KERN_WARNING PREFIX "Invalid buffer argument\n");
ian@0 75 return AE_BAD_PARAMETER;
ian@0 76 }
ian@0 77
ian@0 78 format_count = (format->length / sizeof(char)) - 1;
ian@0 79 if (format_count > package->package.count) {
ian@0 80 printk(KERN_WARNING PREFIX "Format specifies more objects [%d]"
ian@0 81 " than exist in package [%d].\n",
ian@0 82 format_count, package->package.count);
ian@0 83 return AE_BAD_DATA;
ian@0 84 }
ian@0 85
ian@0 86 format_string = (char *)format->pointer;
ian@0 87
ian@0 88 /*
ian@0 89 * Calculate size_required.
ian@0 90 */
ian@0 91 for (i = 0; i < format_count; i++) {
ian@0 92
ian@0 93 union acpi_object *element = &(package->package.elements[i]);
ian@0 94
ian@0 95 if (!element) {
ian@0 96 return AE_BAD_DATA;
ian@0 97 }
ian@0 98
ian@0 99 switch (element->type) {
ian@0 100
ian@0 101 case ACPI_TYPE_INTEGER:
ian@0 102 switch (format_string[i]) {
ian@0 103 case 'N':
ian@0 104 size_required += sizeof(acpi_integer);
ian@0 105 tail_offset += sizeof(acpi_integer);
ian@0 106 break;
ian@0 107 case 'S':
ian@0 108 size_required +=
ian@0 109 sizeof(char *) + sizeof(acpi_integer) +
ian@0 110 sizeof(char);
ian@0 111 tail_offset += sizeof(char *);
ian@0 112 break;
ian@0 113 default:
ian@0 114 printk(KERN_WARNING PREFIX "Invalid package element"
ian@0 115 " [%d]: got number, expecing"
ian@0 116 " [%c]\n",
ian@0 117 i, format_string[i]);
ian@0 118 return AE_BAD_DATA;
ian@0 119 break;
ian@0 120 }
ian@0 121 break;
ian@0 122
ian@0 123 case ACPI_TYPE_STRING:
ian@0 124 case ACPI_TYPE_BUFFER:
ian@0 125 switch (format_string[i]) {
ian@0 126 case 'S':
ian@0 127 size_required +=
ian@0 128 sizeof(char *) +
ian@0 129 (element->string.length * sizeof(char)) +
ian@0 130 sizeof(char);
ian@0 131 tail_offset += sizeof(char *);
ian@0 132 break;
ian@0 133 case 'B':
ian@0 134 size_required +=
ian@0 135 sizeof(u8 *) +
ian@0 136 (element->buffer.length * sizeof(u8));
ian@0 137 tail_offset += sizeof(u8 *);
ian@0 138 break;
ian@0 139 default:
ian@0 140 printk(KERN_WARNING PREFIX "Invalid package element"
ian@0 141 " [%d] got string/buffer,"
ian@0 142 " expecing [%c]\n",
ian@0 143 i, format_string[i]);
ian@0 144 return AE_BAD_DATA;
ian@0 145 break;
ian@0 146 }
ian@0 147 break;
ian@0 148
ian@0 149 case ACPI_TYPE_PACKAGE:
ian@0 150 default:
ian@0 151 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
ian@0 152 "Found unsupported element at index=%d\n",
ian@0 153 i));
ian@0 154 /* TBD: handle nested packages... */
ian@0 155 return AE_SUPPORT;
ian@0 156 break;
ian@0 157 }
ian@0 158 }
ian@0 159
ian@0 160 /*
ian@0 161 * Validate output buffer.
ian@0 162 */
ian@0 163 if (buffer->length < size_required) {
ian@0 164 buffer->length = size_required;
ian@0 165 return AE_BUFFER_OVERFLOW;
ian@0 166 } else if (buffer->length != size_required || !buffer->pointer) {
ian@0 167 return AE_BAD_PARAMETER;
ian@0 168 }
ian@0 169
ian@0 170 head = buffer->pointer;
ian@0 171 tail = buffer->pointer + tail_offset;
ian@0 172
ian@0 173 /*
ian@0 174 * Extract package data.
ian@0 175 */
ian@0 176 for (i = 0; i < format_count; i++) {
ian@0 177
ian@0 178 u8 **pointer = NULL;
ian@0 179 union acpi_object *element = &(package->package.elements[i]);
ian@0 180
ian@0 181 if (!element) {
ian@0 182 return AE_BAD_DATA;
ian@0 183 }
ian@0 184
ian@0 185 switch (element->type) {
ian@0 186
ian@0 187 case ACPI_TYPE_INTEGER:
ian@0 188 switch (format_string[i]) {
ian@0 189 case 'N':
ian@0 190 *((acpi_integer *) head) =
ian@0 191 element->integer.value;
ian@0 192 head += sizeof(acpi_integer);
ian@0 193 break;
ian@0 194 case 'S':
ian@0 195 pointer = (u8 **) head;
ian@0 196 *pointer = tail;
ian@0 197 *((acpi_integer *) tail) =
ian@0 198 element->integer.value;
ian@0 199 head += sizeof(acpi_integer *);
ian@0 200 tail += sizeof(acpi_integer);
ian@0 201 /* NULL terminate string */
ian@0 202 *tail = (char)0;
ian@0 203 tail += sizeof(char);
ian@0 204 break;
ian@0 205 default:
ian@0 206 /* Should never get here */
ian@0 207 break;
ian@0 208 }
ian@0 209 break;
ian@0 210
ian@0 211 case ACPI_TYPE_STRING:
ian@0 212 case ACPI_TYPE_BUFFER:
ian@0 213 switch (format_string[i]) {
ian@0 214 case 'S':
ian@0 215 pointer = (u8 **) head;
ian@0 216 *pointer = tail;
ian@0 217 memcpy(tail, element->string.pointer,
ian@0 218 element->string.length);
ian@0 219 head += sizeof(char *);
ian@0 220 tail += element->string.length * sizeof(char);
ian@0 221 /* NULL terminate string */
ian@0 222 *tail = (char)0;
ian@0 223 tail += sizeof(char);
ian@0 224 break;
ian@0 225 case 'B':
ian@0 226 pointer = (u8 **) head;
ian@0 227 *pointer = tail;
ian@0 228 memcpy(tail, element->buffer.pointer,
ian@0 229 element->buffer.length);
ian@0 230 head += sizeof(u8 *);
ian@0 231 tail += element->buffer.length * sizeof(u8);
ian@0 232 break;
ian@0 233 default:
ian@0 234 /* Should never get here */
ian@0 235 break;
ian@0 236 }
ian@0 237 break;
ian@0 238
ian@0 239 case ACPI_TYPE_PACKAGE:
ian@0 240 /* TBD: handle nested packages... */
ian@0 241 default:
ian@0 242 /* Should never get here */
ian@0 243 break;
ian@0 244 }
ian@0 245 }
ian@0 246
ian@0 247 return AE_OK;
ian@0 248 }
ian@0 249
ian@0 250 EXPORT_SYMBOL(acpi_extract_package);
ian@0 251
ian@0 252 acpi_status
ian@0 253 acpi_evaluate_integer(acpi_handle handle,
ian@0 254 acpi_string pathname,
ian@0 255 struct acpi_object_list *arguments, unsigned long *data)
ian@0 256 {
ian@0 257 acpi_status status = AE_OK;
ian@0 258 union acpi_object *element;
ian@0 259 struct acpi_buffer buffer = { 0, NULL };
ian@0 260
ian@0 261
ian@0 262 if (!data)
ian@0 263 return AE_BAD_PARAMETER;
ian@0 264
ian@0 265 element = kmalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
ian@0 266 if (!element)
ian@0 267 return AE_NO_MEMORY;
ian@0 268
ian@0 269 memset(element, 0, sizeof(union acpi_object));
ian@0 270 buffer.length = sizeof(union acpi_object);
ian@0 271 buffer.pointer = element;
ian@0 272 status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
ian@0 273 if (ACPI_FAILURE(status)) {
ian@0 274 acpi_util_eval_error(handle, pathname, status);
ian@0 275 kfree(element);
ian@0 276 return status;
ian@0 277 }
ian@0 278
ian@0 279 if (element->type != ACPI_TYPE_INTEGER) {
ian@0 280 acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
ian@0 281 kfree(element);
ian@0 282 return AE_BAD_DATA;
ian@0 283 }
ian@0 284
ian@0 285 *data = element->integer.value;
ian@0 286 kfree(element);
ian@0 287
ian@0 288 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data));
ian@0 289
ian@0 290 return AE_OK;
ian@0 291 }
ian@0 292
ian@0 293 EXPORT_SYMBOL(acpi_evaluate_integer);
ian@0 294
ian@0 295 #if 0
ian@0 296 acpi_status
ian@0 297 acpi_evaluate_string(acpi_handle handle,
ian@0 298 acpi_string pathname,
ian@0 299 acpi_object_list * arguments, acpi_string * data)
ian@0 300 {
ian@0 301 acpi_status status = AE_OK;
ian@0 302 acpi_object *element = NULL;
ian@0 303 acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
ian@0 304
ian@0 305
ian@0 306 if (!data)
ian@0 307 return AE_BAD_PARAMETER;
ian@0 308
ian@0 309 status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
ian@0 310 if (ACPI_FAILURE(status)) {
ian@0 311 acpi_util_eval_error(handle, pathname, status);
ian@0 312 return status;
ian@0 313 }
ian@0 314
ian@0 315 element = (acpi_object *) buffer.pointer;
ian@0 316
ian@0 317 if ((element->type != ACPI_TYPE_STRING)
ian@0 318 || (element->type != ACPI_TYPE_BUFFER)
ian@0 319 || !element->string.length) {
ian@0 320 acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
ian@0 321 return AE_BAD_DATA;
ian@0 322 }
ian@0 323
ian@0 324 *data = kmalloc(element->string.length + 1, GFP_KERNEL);
ian@0 325 if (!data) {
ian@0 326 printk(KERN_ERR PREFIX "Memory allocation\n");
ian@0 327 return -ENOMEM;
ian@0 328 }
ian@0 329 memset(*data, 0, element->string.length + 1);
ian@0 330
ian@0 331 memcpy(*data, element->string.pointer, element->string.length);
ian@0 332
ian@0 333 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data));
ian@0 334
ian@0 335 kfree(buffer.pointer);
ian@0 336
ian@0 337 return AE_OK;
ian@0 338 }
ian@0 339 #endif
ian@0 340
ian@0 341 acpi_status
ian@0 342 acpi_evaluate_reference(acpi_handle handle,
ian@0 343 acpi_string pathname,
ian@0 344 struct acpi_object_list *arguments,
ian@0 345 struct acpi_handle_list *list)
ian@0 346 {
ian@0 347 acpi_status status = AE_OK;
ian@0 348 union acpi_object *package = NULL;
ian@0 349 union acpi_object *element = NULL;
ian@0 350 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
ian@0 351 u32 i = 0;
ian@0 352
ian@0 353
ian@0 354 if (!list) {
ian@0 355 return AE_BAD_PARAMETER;
ian@0 356 }
ian@0 357
ian@0 358 /* Evaluate object. */
ian@0 359
ian@0 360 status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
ian@0 361 if (ACPI_FAILURE(status))
ian@0 362 goto end;
ian@0 363
ian@0 364 package = (union acpi_object *)buffer.pointer;
ian@0 365
ian@0 366 if ((buffer.length == 0) || !package) {
ian@0 367 printk(KERN_ERR PREFIX "No return object (len %X ptr %p)\n",
ian@0 368 (unsigned)buffer.length, package);
ian@0 369 status = AE_BAD_DATA;
ian@0 370 acpi_util_eval_error(handle, pathname, status);
ian@0 371 goto end;
ian@0 372 }
ian@0 373 if (package->type != ACPI_TYPE_PACKAGE) {
ian@0 374 printk(KERN_ERR PREFIX "Expecting a [Package], found type %X\n",
ian@0 375 package->type);
ian@0 376 status = AE_BAD_DATA;
ian@0 377 acpi_util_eval_error(handle, pathname, status);
ian@0 378 goto end;
ian@0 379 }
ian@0 380 if (!package->package.count) {
ian@0 381 printk(KERN_ERR PREFIX "[Package] has zero elements (%p)\n",
ian@0 382 package);
ian@0 383 status = AE_BAD_DATA;
ian@0 384 acpi_util_eval_error(handle, pathname, status);
ian@0 385 goto end;
ian@0 386 }
ian@0 387
ian@0 388 if (package->package.count > ACPI_MAX_HANDLES) {
ian@0 389 return AE_NO_MEMORY;
ian@0 390 }
ian@0 391 list->count = package->package.count;
ian@0 392
ian@0 393 /* Extract package data. */
ian@0 394
ian@0 395 for (i = 0; i < list->count; i++) {
ian@0 396
ian@0 397 element = &(package->package.elements[i]);
ian@0 398
ian@0 399 if (element->type != ACPI_TYPE_ANY) {
ian@0 400 status = AE_BAD_DATA;
ian@0 401 printk(KERN_ERR PREFIX
ian@0 402 "Expecting a [Reference] package element, found type %X\n",
ian@0 403 element->type);
ian@0 404 acpi_util_eval_error(handle, pathname, status);
ian@0 405 break;
ian@0 406 }
ian@0 407
ian@0 408 /* Get the acpi_handle. */
ian@0 409
ian@0 410 list->handles[i] = element->reference.handle;
ian@0 411 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n",
ian@0 412 list->handles[i]));
ian@0 413 }
ian@0 414
ian@0 415 end:
ian@0 416 if (ACPI_FAILURE(status)) {
ian@0 417 list->count = 0;
ian@0 418 //kfree(list->handles);
ian@0 419 }
ian@0 420
ian@0 421 kfree(buffer.pointer);
ian@0 422
ian@0 423 return status;
ian@0 424 }
ian@0 425
ian@0 426 EXPORT_SYMBOL(acpi_evaluate_reference);