ia64/linux-2.6.18-xen.hg

annotate drivers/acpi/namespace/nsxfeval.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 *
ian@0 3 * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
ian@0 4 * ACPI Object evaluation interfaces
ian@0 5 *
ian@0 6 ******************************************************************************/
ian@0 7
ian@0 8 /*
ian@0 9 * Copyright (C) 2000 - 2006, R. Byron Moore
ian@0 10 * All rights reserved.
ian@0 11 *
ian@0 12 * Redistribution and use in source and binary forms, with or without
ian@0 13 * modification, are permitted provided that the following conditions
ian@0 14 * are met:
ian@0 15 * 1. Redistributions of source code must retain the above copyright
ian@0 16 * notice, this list of conditions, and the following disclaimer,
ian@0 17 * without modification.
ian@0 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
ian@0 19 * substantially similar to the "NO WARRANTY" disclaimer below
ian@0 20 * ("Disclaimer") and any redistribution must be conditioned upon
ian@0 21 * including a substantially similar Disclaimer requirement for further
ian@0 22 * binary redistribution.
ian@0 23 * 3. Neither the names of the above-listed copyright holders nor the names
ian@0 24 * of any contributors may be used to endorse or promote products derived
ian@0 25 * from this software without specific prior written permission.
ian@0 26 *
ian@0 27 * Alternatively, this software may be distributed under the terms of the
ian@0 28 * GNU General Public License ("GPL") version 2 as published by the Free
ian@0 29 * Software Foundation.
ian@0 30 *
ian@0 31 * NO WARRANTY
ian@0 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
ian@0 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
ian@0 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
ian@0 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
ian@0 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ian@0 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
ian@0 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ian@0 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
ian@0 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
ian@0 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
ian@0 42 * POSSIBILITY OF SUCH DAMAGES.
ian@0 43 */
ian@0 44
ian@0 45 #include <acpi/acpi.h>
ian@0 46 #include <acpi/acnamesp.h>
ian@0 47 #include <acpi/acinterp.h>
ian@0 48
ian@0 49 #define _COMPONENT ACPI_NAMESPACE
ian@0 50 ACPI_MODULE_NAME("nsxfeval")
ian@0 51
ian@0 52 #ifdef ACPI_FUTURE_USAGE
ian@0 53 /*******************************************************************************
ian@0 54 *
ian@0 55 * FUNCTION: acpi_evaluate_object_typed
ian@0 56 *
ian@0 57 * PARAMETERS: Handle - Object handle (optional)
ian@0 58 * Pathname - Object pathname (optional)
ian@0 59 * external_params - List of parameters to pass to method,
ian@0 60 * terminated by NULL. May be NULL
ian@0 61 * if no parameters are being passed.
ian@0 62 * return_buffer - Where to put method's return value (if
ian@0 63 * any). If NULL, no value is returned.
ian@0 64 * return_type - Expected type of return object
ian@0 65 *
ian@0 66 * RETURN: Status
ian@0 67 *
ian@0 68 * DESCRIPTION: Find and evaluate the given object, passing the given
ian@0 69 * parameters if necessary. One of "Handle" or "Pathname" must
ian@0 70 * be valid (non-null)
ian@0 71 *
ian@0 72 ******************************************************************************/
ian@0 73 acpi_status
ian@0 74 acpi_evaluate_object_typed(acpi_handle handle,
ian@0 75 acpi_string pathname,
ian@0 76 struct acpi_object_list * external_params,
ian@0 77 struct acpi_buffer * return_buffer,
ian@0 78 acpi_object_type return_type)
ian@0 79 {
ian@0 80 acpi_status status;
ian@0 81 u8 must_free = FALSE;
ian@0 82
ian@0 83 ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
ian@0 84
ian@0 85 /* Return buffer must be valid */
ian@0 86
ian@0 87 if (!return_buffer) {
ian@0 88 return_ACPI_STATUS(AE_BAD_PARAMETER);
ian@0 89 }
ian@0 90
ian@0 91 if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
ian@0 92 must_free = TRUE;
ian@0 93 }
ian@0 94
ian@0 95 /* Evaluate the object */
ian@0 96
ian@0 97 status =
ian@0 98 acpi_evaluate_object(handle, pathname, external_params,
ian@0 99 return_buffer);
ian@0 100 if (ACPI_FAILURE(status)) {
ian@0 101 return_ACPI_STATUS(status);
ian@0 102 }
ian@0 103
ian@0 104 /* Type ANY means "don't care" */
ian@0 105
ian@0 106 if (return_type == ACPI_TYPE_ANY) {
ian@0 107 return_ACPI_STATUS(AE_OK);
ian@0 108 }
ian@0 109
ian@0 110 if (return_buffer->length == 0) {
ian@0 111
ian@0 112 /* Error because caller specifically asked for a return value */
ian@0 113
ian@0 114 ACPI_ERROR((AE_INFO, "No return value"));
ian@0 115 return_ACPI_STATUS(AE_NULL_OBJECT);
ian@0 116 }
ian@0 117
ian@0 118 /* Examine the object type returned from evaluate_object */
ian@0 119
ian@0 120 if (((union acpi_object *)return_buffer->pointer)->type == return_type) {
ian@0 121 return_ACPI_STATUS(AE_OK);
ian@0 122 }
ian@0 123
ian@0 124 /* Return object type does not match requested type */
ian@0 125
ian@0 126 ACPI_ERROR((AE_INFO,
ian@0 127 "Incorrect return type [%s] requested [%s]",
ian@0 128 acpi_ut_get_type_name(((union acpi_object *)return_buffer->
ian@0 129 pointer)->type),
ian@0 130 acpi_ut_get_type_name(return_type)));
ian@0 131
ian@0 132 if (must_free) {
ian@0 133
ian@0 134 /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
ian@0 135
ian@0 136 ACPI_FREE(return_buffer->pointer);
ian@0 137 return_buffer->pointer = NULL;
ian@0 138 }
ian@0 139
ian@0 140 return_buffer->length = 0;
ian@0 141 return_ACPI_STATUS(AE_TYPE);
ian@0 142 }
ian@0 143
ian@0 144 ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
ian@0 145 #endif /* ACPI_FUTURE_USAGE */
ian@0 146
ian@0 147 /*******************************************************************************
ian@0 148 *
ian@0 149 * FUNCTION: acpi_evaluate_object
ian@0 150 *
ian@0 151 * PARAMETERS: Handle - Object handle (optional)
ian@0 152 * Pathname - Object pathname (optional)
ian@0 153 * external_params - List of parameters to pass to method,
ian@0 154 * terminated by NULL. May be NULL
ian@0 155 * if no parameters are being passed.
ian@0 156 * return_buffer - Where to put method's return value (if
ian@0 157 * any). If NULL, no value is returned.
ian@0 158 *
ian@0 159 * RETURN: Status
ian@0 160 *
ian@0 161 * DESCRIPTION: Find and evaluate the given object, passing the given
ian@0 162 * parameters if necessary. One of "Handle" or "Pathname" must
ian@0 163 * be valid (non-null)
ian@0 164 *
ian@0 165 ******************************************************************************/
ian@0 166 acpi_status
ian@0 167 acpi_evaluate_object(acpi_handle handle,
ian@0 168 acpi_string pathname,
ian@0 169 struct acpi_object_list *external_params,
ian@0 170 struct acpi_buffer *return_buffer)
ian@0 171 {
ian@0 172 acpi_status status;
ian@0 173 acpi_status status2;
ian@0 174 struct acpi_evaluate_info *info;
ian@0 175 acpi_size buffer_space_needed;
ian@0 176 u32 i;
ian@0 177
ian@0 178 ACPI_FUNCTION_TRACE(acpi_evaluate_object);
ian@0 179
ian@0 180 /* Allocate and initialize the evaluation information block */
ian@0 181
ian@0 182 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
ian@0 183 if (!info) {
ian@0 184 return_ACPI_STATUS(AE_NO_MEMORY);
ian@0 185 }
ian@0 186
ian@0 187 info->pathname = pathname;
ian@0 188 info->parameter_type = ACPI_PARAM_ARGS;
ian@0 189
ian@0 190 /* Convert and validate the device handle */
ian@0 191
ian@0 192 info->prefix_node = acpi_ns_map_handle_to_node(handle);
ian@0 193 if (!info->prefix_node) {
ian@0 194 status = AE_BAD_PARAMETER;
ian@0 195 goto cleanup;
ian@0 196 }
ian@0 197
ian@0 198 /*
ian@0 199 * If there are parameters to be passed to a control method, the external
ian@0 200 * objects must all be converted to internal objects
ian@0 201 */
ian@0 202 if (external_params && external_params->count) {
ian@0 203 /*
ian@0 204 * Allocate a new parameter block for the internal objects
ian@0 205 * Add 1 to count to allow for null terminated internal list
ian@0 206 */
ian@0 207 info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
ian@0 208 external_params->
ian@0 209 count +
ian@0 210 1) * sizeof(void *));
ian@0 211 if (!info->parameters) {
ian@0 212 status = AE_NO_MEMORY;
ian@0 213 goto cleanup;
ian@0 214 }
ian@0 215
ian@0 216 /* Convert each external object in the list to an internal object */
ian@0 217
ian@0 218 for (i = 0; i < external_params->count; i++) {
ian@0 219 status =
ian@0 220 acpi_ut_copy_eobject_to_iobject(&external_params->
ian@0 221 pointer[i],
ian@0 222 &info->
ian@0 223 parameters[i]);
ian@0 224 if (ACPI_FAILURE(status)) {
ian@0 225 goto cleanup;
ian@0 226 }
ian@0 227 }
ian@0 228 info->parameters[external_params->count] = NULL;
ian@0 229 }
ian@0 230
ian@0 231 /*
ian@0 232 * Three major cases:
ian@0 233 * 1) Fully qualified pathname
ian@0 234 * 2) No handle, not fully qualified pathname (error)
ian@0 235 * 3) Valid handle
ian@0 236 */
ian@0 237 if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) {
ian@0 238
ian@0 239 /* The path is fully qualified, just evaluate by name */
ian@0 240
ian@0 241 info->prefix_node = NULL;
ian@0 242 status = acpi_ns_evaluate(info);
ian@0 243 } else if (!handle) {
ian@0 244 /*
ian@0 245 * A handle is optional iff a fully qualified pathname is specified.
ian@0 246 * Since we've already handled fully qualified names above, this is
ian@0 247 * an error
ian@0 248 */
ian@0 249 if (!pathname) {
ian@0 250 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
ian@0 251 "Both Handle and Pathname are NULL"));
ian@0 252 } else {
ian@0 253 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
ian@0 254 "Null Handle with relative pathname [%s]",
ian@0 255 pathname));
ian@0 256 }
ian@0 257
ian@0 258 status = AE_BAD_PARAMETER;
ian@0 259 } else {
ian@0 260 /* We have a namespace a node and a possible relative path */
ian@0 261
ian@0 262 status = acpi_ns_evaluate(info);
ian@0 263 }
ian@0 264
ian@0 265 /*
ian@0 266 * If we are expecting a return value, and all went well above,
ian@0 267 * copy the return value to an external object.
ian@0 268 */
ian@0 269 if (return_buffer) {
ian@0 270 if (!info->return_object) {
ian@0 271 return_buffer->length = 0;
ian@0 272 } else {
ian@0 273 if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
ian@0 274 ACPI_DESC_TYPE_NAMED) {
ian@0 275 /*
ian@0 276 * If we received a NS Node as a return object, this means that
ian@0 277 * the object we are evaluating has nothing interesting to
ian@0 278 * return (such as a mutex, etc.) We return an error because
ian@0 279 * these types are essentially unsupported by this interface.
ian@0 280 * We don't check up front because this makes it easier to add
ian@0 281 * support for various types at a later date if necessary.
ian@0 282 */
ian@0 283 status = AE_TYPE;
ian@0 284 info->return_object = NULL; /* No need to delete a NS Node */
ian@0 285 return_buffer->length = 0;
ian@0 286 }
ian@0 287
ian@0 288 if (ACPI_SUCCESS(status)) {
ian@0 289
ian@0 290 /* Get the size of the returned object */
ian@0 291
ian@0 292 status =
ian@0 293 acpi_ut_get_object_size(info->return_object,
ian@0 294 &buffer_space_needed);
ian@0 295 if (ACPI_SUCCESS(status)) {
ian@0 296
ian@0 297 /* Validate/Allocate/Clear caller buffer */
ian@0 298
ian@0 299 status =
ian@0 300 acpi_ut_initialize_buffer
ian@0 301 (return_buffer,
ian@0 302 buffer_space_needed);
ian@0 303 if (ACPI_FAILURE(status)) {
ian@0 304 /*
ian@0 305 * Caller's buffer is too small or a new one can't
ian@0 306 * be allocated
ian@0 307 */
ian@0 308 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
ian@0 309 "Needed buffer size %X, %s\n",
ian@0 310 (u32)
ian@0 311 buffer_space_needed,
ian@0 312 acpi_format_exception
ian@0 313 (status)));
ian@0 314 } else {
ian@0 315 /* We have enough space for the object, build it */
ian@0 316
ian@0 317 status =
ian@0 318 acpi_ut_copy_iobject_to_eobject
ian@0 319 (info->return_object,
ian@0 320 return_buffer);
ian@0 321 }
ian@0 322 }
ian@0 323 }
ian@0 324 }
ian@0 325 }
ian@0 326
ian@0 327 if (info->return_object) {
ian@0 328 /*
ian@0 329 * Delete the internal return object. NOTE: Interpreter must be
ian@0 330 * locked to avoid race condition.
ian@0 331 */
ian@0 332 status2 = acpi_ex_enter_interpreter();
ian@0 333 if (ACPI_SUCCESS(status2)) {
ian@0 334
ian@0 335 /* Remove one reference on the return object (should delete it) */
ian@0 336
ian@0 337 acpi_ut_remove_reference(info->return_object);
ian@0 338 acpi_ex_exit_interpreter();
ian@0 339 }
ian@0 340 }
ian@0 341
ian@0 342 cleanup:
ian@0 343
ian@0 344 /* Free the input parameter list (if we created one) */
ian@0 345
ian@0 346 if (info->parameters) {
ian@0 347
ian@0 348 /* Free the allocated parameter block */
ian@0 349
ian@0 350 acpi_ut_delete_internal_object_list(info->parameters);
ian@0 351 }
ian@0 352
ian@0 353 ACPI_FREE(info);
ian@0 354 return_ACPI_STATUS(status);
ian@0 355 }
ian@0 356
ian@0 357 ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
ian@0 358
ian@0 359 /*******************************************************************************
ian@0 360 *
ian@0 361 * FUNCTION: acpi_walk_namespace
ian@0 362 *
ian@0 363 * PARAMETERS: Type - acpi_object_type to search for
ian@0 364 * start_object - Handle in namespace where search begins
ian@0 365 * max_depth - Depth to which search is to reach
ian@0 366 * user_function - Called when an object of "Type" is found
ian@0 367 * Context - Passed to user function
ian@0 368 * return_value - Location where return value of
ian@0 369 * user_function is put if terminated early
ian@0 370 *
ian@0 371 * RETURNS Return value from the user_function if terminated early.
ian@0 372 * Otherwise, returns NULL.
ian@0 373 *
ian@0 374 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
ian@0 375 * starting (and ending) at the object specified by start_handle.
ian@0 376 * The user_function is called whenever an object that matches
ian@0 377 * the type parameter is found. If the user function returns
ian@0 378 * a non-zero value, the search is terminated immediately and this
ian@0 379 * value is returned to the caller.
ian@0 380 *
ian@0 381 * The point of this procedure is to provide a generic namespace
ian@0 382 * walk routine that can be called from multiple places to
ian@0 383 * provide multiple services; the User Function can be tailored
ian@0 384 * to each task, whether it is a print function, a compare
ian@0 385 * function, etc.
ian@0 386 *
ian@0 387 ******************************************************************************/
ian@0 388 acpi_status
ian@0 389 acpi_walk_namespace(acpi_object_type type,
ian@0 390 acpi_handle start_object,
ian@0 391 u32 max_depth,
ian@0 392 acpi_walk_callback user_function,
ian@0 393 void *context, void **return_value)
ian@0 394 {
ian@0 395 acpi_status status;
ian@0 396
ian@0 397 ACPI_FUNCTION_TRACE(acpi_walk_namespace);
ian@0 398
ian@0 399 /* Parameter validation */
ian@0 400
ian@0 401 if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) {
ian@0 402 return_ACPI_STATUS(AE_BAD_PARAMETER);
ian@0 403 }
ian@0 404
ian@0 405 /*
ian@0 406 * Lock the namespace around the walk.
ian@0 407 * The namespace will be unlocked/locked around each call
ian@0 408 * to the user function - since this function
ian@0 409 * must be allowed to make Acpi calls itself.
ian@0 410 */
ian@0 411 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
ian@0 412 if (ACPI_FAILURE(status)) {
ian@0 413 return_ACPI_STATUS(status);
ian@0 414 }
ian@0 415
ian@0 416 status = acpi_ns_walk_namespace(type, start_object, max_depth,
ian@0 417 ACPI_NS_WALK_UNLOCK,
ian@0 418 user_function, context, return_value);
ian@0 419
ian@0 420 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
ian@0 421 return_ACPI_STATUS(status);
ian@0 422 }
ian@0 423
ian@0 424 ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
ian@0 425
ian@0 426 /*******************************************************************************
ian@0 427 *
ian@0 428 * FUNCTION: acpi_ns_get_device_callback
ian@0 429 *
ian@0 430 * PARAMETERS: Callback from acpi_get_device
ian@0 431 *
ian@0 432 * RETURN: Status
ian@0 433 *
ian@0 434 * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
ian@0 435 * present devices, or if they specified a HID, it filters based
ian@0 436 * on that.
ian@0 437 *
ian@0 438 ******************************************************************************/
ian@0 439 static acpi_status
ian@0 440 acpi_ns_get_device_callback(acpi_handle obj_handle,
ian@0 441 u32 nesting_level,
ian@0 442 void *context, void **return_value)
ian@0 443 {
ian@0 444 struct acpi_get_devices_info *info = context;
ian@0 445 acpi_status status;
ian@0 446 struct acpi_namespace_node *node;
ian@0 447 u32 flags;
ian@0 448 struct acpi_device_id hid;
ian@0 449 struct acpi_compatible_id_list *cid;
ian@0 450 acpi_native_uint i;
ian@0 451
ian@0 452 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
ian@0 453 if (ACPI_FAILURE(status)) {
ian@0 454 return (status);
ian@0 455 }
ian@0 456
ian@0 457 node = acpi_ns_map_handle_to_node(obj_handle);
ian@0 458 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
ian@0 459 if (ACPI_FAILURE(status)) {
ian@0 460 return (status);
ian@0 461 }
ian@0 462
ian@0 463 if (!node) {
ian@0 464 return (AE_BAD_PARAMETER);
ian@0 465 }
ian@0 466
ian@0 467 /* Run _STA to determine if device is present */
ian@0 468
ian@0 469 status = acpi_ut_execute_STA(node, &flags);
ian@0 470 if (ACPI_FAILURE(status)) {
ian@0 471 return (AE_CTRL_DEPTH);
ian@0 472 }
ian@0 473
ian@0 474 if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
ian@0 475
ian@0 476 /* Don't examine children of the device if not present */
ian@0 477
ian@0 478 return (AE_CTRL_DEPTH);
ian@0 479 }
ian@0 480
ian@0 481 /* Filter based on device HID & CID */
ian@0 482
ian@0 483 if (info->hid != NULL) {
ian@0 484 status = acpi_ut_execute_HID(node, &hid);
ian@0 485 if (status == AE_NOT_FOUND) {
ian@0 486 return (AE_OK);
ian@0 487 } else if (ACPI_FAILURE(status)) {
ian@0 488 return (AE_CTRL_DEPTH);
ian@0 489 }
ian@0 490
ian@0 491 if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) {
ian@0 492
ian@0 493 /* Get the list of Compatible IDs */
ian@0 494
ian@0 495 status = acpi_ut_execute_CID(node, &cid);
ian@0 496 if (status == AE_NOT_FOUND) {
ian@0 497 return (AE_OK);
ian@0 498 } else if (ACPI_FAILURE(status)) {
ian@0 499 return (AE_CTRL_DEPTH);
ian@0 500 }
ian@0 501
ian@0 502 /* Walk the CID list */
ian@0 503
ian@0 504 for (i = 0; i < cid->count; i++) {
ian@0 505 if (ACPI_STRNCMP(cid->id[i].value, info->hid,
ian@0 506 sizeof(struct
ian@0 507 acpi_compatible_id)) !=
ian@0 508 0) {
ian@0 509 ACPI_FREE(cid);
ian@0 510 return (AE_OK);
ian@0 511 }
ian@0 512 }
ian@0 513 ACPI_FREE(cid);
ian@0 514 }
ian@0 515 }
ian@0 516
ian@0 517 status = info->user_function(obj_handle, nesting_level, info->context,
ian@0 518 return_value);
ian@0 519 return (status);
ian@0 520 }
ian@0 521
ian@0 522 /*******************************************************************************
ian@0 523 *
ian@0 524 * FUNCTION: acpi_get_devices
ian@0 525 *
ian@0 526 * PARAMETERS: HID - HID to search for. Can be NULL.
ian@0 527 * user_function - Called when a matching object is found
ian@0 528 * Context - Passed to user function
ian@0 529 * return_value - Location where return value of
ian@0 530 * user_function is put if terminated early
ian@0 531 *
ian@0 532 * RETURNS Return value from the user_function if terminated early.
ian@0 533 * Otherwise, returns NULL.
ian@0 534 *
ian@0 535 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
ian@0 536 * starting (and ending) at the object specified by start_handle.
ian@0 537 * The user_function is called whenever an object of type
ian@0 538 * Device is found. If the user function returns
ian@0 539 * a non-zero value, the search is terminated immediately and this
ian@0 540 * value is returned to the caller.
ian@0 541 *
ian@0 542 * This is a wrapper for walk_namespace, but the callback performs
ian@0 543 * additional filtering. Please see acpi_get_device_callback.
ian@0 544 *
ian@0 545 ******************************************************************************/
ian@0 546
ian@0 547 acpi_status
ian@0 548 acpi_get_devices(char *HID,
ian@0 549 acpi_walk_callback user_function,
ian@0 550 void *context, void **return_value)
ian@0 551 {
ian@0 552 acpi_status status;
ian@0 553 struct acpi_get_devices_info info;
ian@0 554
ian@0 555 ACPI_FUNCTION_TRACE(acpi_get_devices);
ian@0 556
ian@0 557 /* Parameter validation */
ian@0 558
ian@0 559 if (!user_function) {
ian@0 560 return_ACPI_STATUS(AE_BAD_PARAMETER);
ian@0 561 }
ian@0 562
ian@0 563 /*
ian@0 564 * We're going to call their callback from OUR callback, so we need
ian@0 565 * to know what it is, and their context parameter.
ian@0 566 */
ian@0 567 info.hid = HID;
ian@0 568 info.context = context;
ian@0 569 info.user_function = user_function;
ian@0 570
ian@0 571 /*
ian@0 572 * Lock the namespace around the walk.
ian@0 573 * The namespace will be unlocked/locked around each call
ian@0 574 * to the user function - since this function
ian@0 575 * must be allowed to make Acpi calls itself.
ian@0 576 */
ian@0 577 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
ian@0 578 if (ACPI_FAILURE(status)) {
ian@0 579 return_ACPI_STATUS(status);
ian@0 580 }
ian@0 581
ian@0 582 status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ian@0 583 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
ian@0 584 acpi_ns_get_device_callback, &info,
ian@0 585 return_value);
ian@0 586
ian@0 587 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
ian@0 588 return_ACPI_STATUS(status);
ian@0 589 }
ian@0 590
ian@0 591 ACPI_EXPORT_SYMBOL(acpi_get_devices)
ian@0 592
ian@0 593 /*******************************************************************************
ian@0 594 *
ian@0 595 * FUNCTION: acpi_attach_data
ian@0 596 *
ian@0 597 * PARAMETERS: obj_handle - Namespace node
ian@0 598 * Handler - Handler for this attachment
ian@0 599 * Data - Pointer to data to be attached
ian@0 600 *
ian@0 601 * RETURN: Status
ian@0 602 *
ian@0 603 * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
ian@0 604 *
ian@0 605 ******************************************************************************/
ian@0 606 acpi_status
ian@0 607 acpi_attach_data(acpi_handle obj_handle,
ian@0 608 acpi_object_handler handler, void *data)
ian@0 609 {
ian@0 610 struct acpi_namespace_node *node;
ian@0 611 acpi_status status;
ian@0 612
ian@0 613 /* Parameter validation */
ian@0 614
ian@0 615 if (!obj_handle || !handler || !data) {
ian@0 616 return (AE_BAD_PARAMETER);
ian@0 617 }
ian@0 618
ian@0 619 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
ian@0 620 if (ACPI_FAILURE(status)) {
ian@0 621 return (status);
ian@0 622 }
ian@0 623
ian@0 624 /* Convert and validate the handle */
ian@0 625
ian@0 626 node = acpi_ns_map_handle_to_node(obj_handle);
ian@0 627 if (!node) {
ian@0 628 status = AE_BAD_PARAMETER;
ian@0 629 goto unlock_and_exit;
ian@0 630 }
ian@0 631
ian@0 632 status = acpi_ns_attach_data(node, handler, data);
ian@0 633
ian@0 634 unlock_and_exit:
ian@0 635 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
ian@0 636 return (status);
ian@0 637 }
ian@0 638
ian@0 639 ACPI_EXPORT_SYMBOL(acpi_attach_data)
ian@0 640
ian@0 641 /*******************************************************************************
ian@0 642 *
ian@0 643 * FUNCTION: acpi_detach_data
ian@0 644 *
ian@0 645 * PARAMETERS: obj_handle - Namespace node handle
ian@0 646 * Handler - Handler used in call to acpi_attach_data
ian@0 647 *
ian@0 648 * RETURN: Status
ian@0 649 *
ian@0 650 * DESCRIPTION: Remove data that was previously attached to a node.
ian@0 651 *
ian@0 652 ******************************************************************************/
ian@0 653 acpi_status
ian@0 654 acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
ian@0 655 {
ian@0 656 struct acpi_namespace_node *node;
ian@0 657 acpi_status status;
ian@0 658
ian@0 659 /* Parameter validation */
ian@0 660
ian@0 661 if (!obj_handle || !handler) {
ian@0 662 return (AE_BAD_PARAMETER);
ian@0 663 }
ian@0 664
ian@0 665 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
ian@0 666 if (ACPI_FAILURE(status)) {
ian@0 667 return (status);
ian@0 668 }
ian@0 669
ian@0 670 /* Convert and validate the handle */
ian@0 671
ian@0 672 node = acpi_ns_map_handle_to_node(obj_handle);
ian@0 673 if (!node) {
ian@0 674 status = AE_BAD_PARAMETER;
ian@0 675 goto unlock_and_exit;
ian@0 676 }
ian@0 677
ian@0 678 status = acpi_ns_detach_data(node, handler);
ian@0 679
ian@0 680 unlock_and_exit:
ian@0 681 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
ian@0 682 return (status);
ian@0 683 }
ian@0 684
ian@0 685 ACPI_EXPORT_SYMBOL(acpi_detach_data)
ian@0 686
ian@0 687 /*******************************************************************************
ian@0 688 *
ian@0 689 * FUNCTION: acpi_get_data
ian@0 690 *
ian@0 691 * PARAMETERS: obj_handle - Namespace node
ian@0 692 * Handler - Handler used in call to attach_data
ian@0 693 * Data - Where the data is returned
ian@0 694 *
ian@0 695 * RETURN: Status
ian@0 696 *
ian@0 697 * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
ian@0 698 *
ian@0 699 ******************************************************************************/
ian@0 700 acpi_status
ian@0 701 acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
ian@0 702 {
ian@0 703 struct acpi_namespace_node *node;
ian@0 704 acpi_status status;
ian@0 705
ian@0 706 /* Parameter validation */
ian@0 707
ian@0 708 if (!obj_handle || !handler || !data) {
ian@0 709 return (AE_BAD_PARAMETER);
ian@0 710 }
ian@0 711
ian@0 712 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
ian@0 713 if (ACPI_FAILURE(status)) {
ian@0 714 return (status);
ian@0 715 }
ian@0 716
ian@0 717 /* Convert and validate the handle */
ian@0 718
ian@0 719 node = acpi_ns_map_handle_to_node(obj_handle);
ian@0 720 if (!node) {
ian@0 721 status = AE_BAD_PARAMETER;
ian@0 722 goto unlock_and_exit;
ian@0 723 }
ian@0 724
ian@0 725 status = acpi_ns_get_attached_data(node, handler, data);
ian@0 726
ian@0 727 unlock_and_exit:
ian@0 728 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
ian@0 729 return (status);
ian@0 730 }
ian@0 731
ian@0 732 ACPI_EXPORT_SYMBOL(acpi_get_data)