diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 04:29:00 -0500 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2006-02-09 04:29:00 -0500 |
| commit | 9caafa6c8686e319cf4d5f3757b3972c6c522b7c (patch) | |
| tree | b38979b835b5d22e681b175d0b98a3c7560d9c59 /drivers/acpi/resources/rsxface.c | |
| parent | 51e9f2ff83df6b1c81c5c44f4486c68ed87aa20e (diff) | |
| parent | cac0e8e8bb2e7a086643bdd00c41d900a79bb4fa (diff) | |
Merge branch 'upstream-fixes'
Diffstat (limited to 'drivers/acpi/resources/rsxface.c')
| -rw-r--r-- | drivers/acpi/resources/rsxface.c | 230 |
1 files changed, 173 insertions, 57 deletions
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index ee5a5c509199..88b67077aeeb 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
| 6 | 6 | ||
| 7 | /* | 7 | /* |
| 8 | * Copyright (C) 2000 - 2005, R. Byron Moore | 8 | * Copyright (C) 2000 - 2006, R. Byron Moore |
| 9 | * All rights reserved. | 9 | * All rights reserved. |
| 10 | * | 10 | * |
| 11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
| @@ -57,13 +57,17 @@ ACPI_MODULE_NAME("rsxface") | |||
| 57 | ACPI_COPY_FIELD(out, in, decode); \ | 57 | ACPI_COPY_FIELD(out, in, decode); \ |
| 58 | ACPI_COPY_FIELD(out, in, min_address_fixed); \ | 58 | ACPI_COPY_FIELD(out, in, min_address_fixed); \ |
| 59 | ACPI_COPY_FIELD(out, in, max_address_fixed); \ | 59 | ACPI_COPY_FIELD(out, in, max_address_fixed); \ |
| 60 | ACPI_COPY_FIELD(out, in, attribute); \ | 60 | ACPI_COPY_FIELD(out, in, info); \ |
| 61 | ACPI_COPY_FIELD(out, in, granularity); \ | 61 | ACPI_COPY_FIELD(out, in, granularity); \ |
| 62 | ACPI_COPY_FIELD(out, in, min_address_range); \ | 62 | ACPI_COPY_FIELD(out, in, minimum); \ |
| 63 | ACPI_COPY_FIELD(out, in, max_address_range); \ | 63 | ACPI_COPY_FIELD(out, in, maximum); \ |
| 64 | ACPI_COPY_FIELD(out, in, address_translation_offset); \ | 64 | ACPI_COPY_FIELD(out, in, translation_offset); \ |
| 65 | ACPI_COPY_FIELD(out, in, address_length); \ | 65 | ACPI_COPY_FIELD(out, in, address_length); \ |
| 66 | ACPI_COPY_FIELD(out, in, resource_source); | 66 | ACPI_COPY_FIELD(out, in, resource_source); |
| 67 | /* Local prototypes */ | ||
| 68 | static acpi_status | ||
| 69 | acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); | ||
| 70 | |||
| 67 | /******************************************************************************* | 71 | /******************************************************************************* |
| 68 | * | 72 | * |
| 69 | * FUNCTION: acpi_get_irq_routing_table | 73 | * FUNCTION: acpi_get_irq_routing_table |
| @@ -86,6 +90,7 @@ ACPI_MODULE_NAME("rsxface") | |||
| 86 | * the object indicated by the passed device_handle. | 90 | * the object indicated by the passed device_handle. |
| 87 | * | 91 | * |
| 88 | ******************************************************************************/ | 92 | ******************************************************************************/ |
| 93 | |||
| 89 | acpi_status | 94 | acpi_status |
| 90 | acpi_get_irq_routing_table(acpi_handle device_handle, | 95 | acpi_get_irq_routing_table(acpi_handle device_handle, |
| 91 | struct acpi_buffer *ret_buffer) | 96 | struct acpi_buffer *ret_buffer) |
| @@ -222,12 +227,12 @@ EXPORT_SYMBOL(acpi_get_possible_resources); | |||
| 222 | * | 227 | * |
| 223 | * FUNCTION: acpi_walk_resources | 228 | * FUNCTION: acpi_walk_resources |
| 224 | * | 229 | * |
| 225 | * PARAMETERS: device_handle - a handle to the device object for the | 230 | * PARAMETERS: device_handle - Handle to the device object for the |
| 226 | * device we are querying | 231 | * device we are querying |
| 227 | * Path - method name of the resources we want | 232 | * Name - Method name of the resources we want |
| 228 | * (METHOD_NAME__CRS or METHOD_NAME__PRS) | 233 | * (METHOD_NAME__CRS or METHOD_NAME__PRS) |
| 229 | * user_function - called for each resource | 234 | * user_function - Called for each resource |
| 230 | * Context - passed to user_function | 235 | * Context - Passed to user_function |
| 231 | * | 236 | * |
| 232 | * RETURN: Status | 237 | * RETURN: Status |
| 233 | * | 238 | * |
| @@ -239,79 +244,74 @@ EXPORT_SYMBOL(acpi_get_possible_resources); | |||
| 239 | 244 | ||
| 240 | acpi_status | 245 | acpi_status |
| 241 | acpi_walk_resources(acpi_handle device_handle, | 246 | acpi_walk_resources(acpi_handle device_handle, |
| 242 | char *path, | 247 | char *name, |
| 243 | ACPI_WALK_RESOURCE_CALLBACK user_function, void *context) | 248 | ACPI_WALK_RESOURCE_CALLBACK user_function, void *context) |
| 244 | { | 249 | { |
| 245 | acpi_status status; | 250 | acpi_status status; |
| 246 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 251 | struct acpi_buffer buffer; |
| 247 | struct acpi_resource *resource; | 252 | struct acpi_resource *resource; |
| 248 | struct acpi_resource *buffer_end; | 253 | struct acpi_resource *resource_end; |
| 249 | 254 | ||
| 250 | ACPI_FUNCTION_TRACE("acpi_walk_resources"); | 255 | ACPI_FUNCTION_TRACE("acpi_walk_resources"); |
| 251 | 256 | ||
| 252 | if (!device_handle || | 257 | /* Parameter validation */ |
| 253 | (ACPI_STRNCMP(path, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) && | 258 | |
| 254 | ACPI_STRNCMP(path, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) { | 259 | if (!device_handle || !user_function || !name || |
| 260 | (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) && | ||
| 261 | ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) { | ||
| 255 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 262 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
| 256 | } | 263 | } |
| 257 | 264 | ||
| 258 | status = acpi_rs_get_method_data(device_handle, path, &buffer); | 265 | /* Get the _CRS or _PRS resource list */ |
| 266 | |||
| 267 | buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | ||
| 268 | status = acpi_rs_get_method_data(device_handle, name, &buffer); | ||
| 259 | if (ACPI_FAILURE(status)) { | 269 | if (ACPI_FAILURE(status)) { |
| 260 | return_ACPI_STATUS(status); | 270 | return_ACPI_STATUS(status); |
| 261 | } | 271 | } |
| 262 | 272 | ||
| 263 | /* Setup pointers */ | 273 | /* Buffer now contains the resource list */ |
| 264 | 274 | ||
| 265 | resource = (struct acpi_resource *)buffer.pointer; | 275 | resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); |
| 266 | buffer_end = ACPI_CAST_PTR(struct acpi_resource, | 276 | resource_end = |
| 267 | ((u8 *) buffer.pointer + buffer.length)); | 277 | ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); |
| 268 | 278 | ||
| 269 | /* Walk the resource list */ | 279 | /* Walk the resource list until the end_tag is found (or buffer end) */ |
| 270 | 280 | ||
| 271 | for (;;) { | 281 | while (resource < resource_end) { |
| 272 | if (!resource || resource->id == ACPI_RSTYPE_END_TAG) { | 282 | /* Sanity check the resource */ |
| 283 | |||
| 284 | if (resource->type > ACPI_RESOURCE_TYPE_MAX) { | ||
| 285 | status = AE_AML_INVALID_RESOURCE_TYPE; | ||
| 273 | break; | 286 | break; |
| 274 | } | 287 | } |
| 275 | 288 | ||
| 276 | status = user_function(resource, context); | 289 | /* Invoke the user function, abort on any error returned */ |
| 277 | |||
| 278 | switch (status) { | ||
| 279 | case AE_OK: | ||
| 280 | case AE_CTRL_DEPTH: | ||
| 281 | 290 | ||
| 282 | /* Just keep going */ | 291 | status = user_function(resource, context); |
| 292 | if (ACPI_FAILURE(status)) { | ||
| 293 | if (status == AE_CTRL_TERMINATE) { | ||
| 294 | /* This is an OK termination by the user function */ | ||
| 283 | 295 | ||
| 284 | status = AE_OK; | 296 | status = AE_OK; |
| 297 | } | ||
| 285 | break; | 298 | break; |
| 299 | } | ||
| 286 | 300 | ||
| 287 | case AE_CTRL_TERMINATE: | 301 | /* end_tag indicates end-of-list */ |
| 288 | |||
| 289 | /* Exit now, with OK stats */ | ||
| 290 | |||
| 291 | status = AE_OK; | ||
| 292 | goto cleanup; | ||
| 293 | |||
| 294 | default: | ||
| 295 | |||
| 296 | /* All others are valid exceptions */ | ||
| 297 | 302 | ||
| 298 | goto cleanup; | 303 | if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { |
| 304 | break; | ||
| 299 | } | 305 | } |
| 300 | 306 | ||
| 301 | /* Get the next resource descriptor */ | 307 | /* Get the next resource descriptor */ |
| 302 | 308 | ||
| 303 | resource = ACPI_NEXT_RESOURCE(resource); | 309 | resource = |
| 304 | 310 | ACPI_ADD_PTR(struct acpi_resource, resource, | |
| 305 | /* Check for end-of-buffer */ | 311 | resource->length); |
| 306 | |||
| 307 | if (resource >= buffer_end) { | ||
| 308 | goto cleanup; | ||
| 309 | } | ||
| 310 | } | 312 | } |
| 311 | 313 | ||
| 312 | cleanup: | 314 | ACPI_MEM_FREE(buffer.pointer); |
| 313 | |||
| 314 | acpi_os_free(buffer.pointer); | ||
| 315 | return_ACPI_STATUS(status); | 315 | return_ACPI_STATUS(status); |
| 316 | } | 316 | } |
| 317 | 317 | ||
| @@ -360,8 +360,8 @@ EXPORT_SYMBOL(acpi_set_current_resources); | |||
| 360 | * | 360 | * |
| 361 | * FUNCTION: acpi_resource_to_address64 | 361 | * FUNCTION: acpi_resource_to_address64 |
| 362 | * | 362 | * |
| 363 | * PARAMETERS: resource - Pointer to a resource | 363 | * PARAMETERS: Resource - Pointer to a resource |
| 364 | * out - Pointer to the users's return | 364 | * Out - Pointer to the users's return |
| 365 | * buffer (a struct | 365 | * buffer (a struct |
| 366 | * struct acpi_resource_address64) | 366 | * struct acpi_resource_address64) |
| 367 | * | 367 | * |
| @@ -381,20 +381,26 @@ acpi_resource_to_address64(struct acpi_resource *resource, | |||
| 381 | struct acpi_resource_address16 *address16; | 381 | struct acpi_resource_address16 *address16; |
| 382 | struct acpi_resource_address32 *address32; | 382 | struct acpi_resource_address32 *address32; |
| 383 | 383 | ||
| 384 | switch (resource->id) { | 384 | if (!resource || !out) { |
| 385 | case ACPI_RSTYPE_ADDRESS16: | 385 | return (AE_BAD_PARAMETER); |
| 386 | } | ||
| 387 | |||
| 388 | /* Convert 16 or 32 address descriptor to 64 */ | ||
| 389 | |||
| 390 | switch (resource->type) { | ||
| 391 | case ACPI_RESOURCE_TYPE_ADDRESS16: | ||
| 386 | 392 | ||
| 387 | address16 = (struct acpi_resource_address16 *)&resource->data; | 393 | address16 = (struct acpi_resource_address16 *)&resource->data; |
| 388 | ACPI_COPY_ADDRESS(out, address16); | 394 | ACPI_COPY_ADDRESS(out, address16); |
| 389 | break; | 395 | break; |
| 390 | 396 | ||
| 391 | case ACPI_RSTYPE_ADDRESS32: | 397 | case ACPI_RESOURCE_TYPE_ADDRESS32: |
| 392 | 398 | ||
| 393 | address32 = (struct acpi_resource_address32 *)&resource->data; | 399 | address32 = (struct acpi_resource_address32 *)&resource->data; |
| 394 | ACPI_COPY_ADDRESS(out, address32); | 400 | ACPI_COPY_ADDRESS(out, address32); |
| 395 | break; | 401 | break; |
| 396 | 402 | ||
| 397 | case ACPI_RSTYPE_ADDRESS64: | 403 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
| 398 | 404 | ||
| 399 | /* Simple copy for 64 bit source */ | 405 | /* Simple copy for 64 bit source */ |
| 400 | 406 | ||
| @@ -410,3 +416,113 @@ acpi_resource_to_address64(struct acpi_resource *resource, | |||
| 410 | } | 416 | } |
| 411 | 417 | ||
| 412 | EXPORT_SYMBOL(acpi_resource_to_address64); | 418 | EXPORT_SYMBOL(acpi_resource_to_address64); |
| 419 | |||
| 420 | /******************************************************************************* | ||
| 421 | * | ||
| 422 | * FUNCTION: acpi_get_vendor_resource | ||
| 423 | * | ||
| 424 | * PARAMETERS: device_handle - Handle for the parent device object | ||
| 425 | * Name - Method name for the parent resource | ||
| 426 | * (METHOD_NAME__CRS or METHOD_NAME__PRS) | ||
| 427 | * Uuid - Pointer to the UUID to be matched. | ||
| 428 | * includes both subtype and 16-byte UUID | ||
| 429 | * ret_buffer - Where the vendor resource is returned | ||
| 430 | * | ||
| 431 | * RETURN: Status | ||
| 432 | * | ||
| 433 | * DESCRIPTION: Walk a resource template for the specified evice to find a | ||
| 434 | * vendor-defined resource that matches the supplied UUID and | ||
| 435 | * UUID subtype. Returns a struct acpi_resource of type Vendor. | ||
| 436 | * | ||
| 437 | ******************************************************************************/ | ||
| 438 | |||
| 439 | acpi_status | ||
| 440 | acpi_get_vendor_resource(acpi_handle device_handle, | ||
| 441 | char *name, | ||
| 442 | struct acpi_vendor_uuid * uuid, | ||
| 443 | struct acpi_buffer * ret_buffer) | ||
| 444 | { | ||
| 445 | struct acpi_vendor_walk_info info; | ||
| 446 | acpi_status status; | ||
| 447 | |||
| 448 | /* Other parameters are validated by acpi_walk_resources */ | ||
| 449 | |||
| 450 | if (!uuid || !ret_buffer) { | ||
| 451 | return (AE_BAD_PARAMETER); | ||
| 452 | } | ||
| 453 | |||
| 454 | info.uuid = uuid; | ||
| 455 | info.buffer = ret_buffer; | ||
| 456 | info.status = AE_NOT_EXIST; | ||
| 457 | |||
| 458 | /* Walk the _CRS or _PRS resource list for this device */ | ||
| 459 | |||
| 460 | status = | ||
| 461 | acpi_walk_resources(device_handle, name, | ||
| 462 | acpi_rs_match_vendor_resource, &info); | ||
| 463 | if (ACPI_FAILURE(status)) { | ||
| 464 | return (status); | ||
| 465 | } | ||
| 466 | |||
| 467 | return (info.status); | ||
| 468 | } | ||
| 469 | |||
| 470 | /******************************************************************************* | ||
| 471 | * | ||
| 472 | * FUNCTION: acpi_rs_match_vendor_resource | ||
| 473 | * | ||
| 474 | * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK | ||
| 475 | * | ||
| 476 | * RETURN: Status | ||
| 477 | * | ||
| 478 | * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID | ||
| 479 | * | ||
| 480 | ******************************************************************************/ | ||
| 481 | |||
| 482 | static acpi_status | ||
| 483 | acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) | ||
| 484 | { | ||
| 485 | struct acpi_vendor_walk_info *info = context; | ||
| 486 | struct acpi_resource_vendor_typed *vendor; | ||
| 487 | struct acpi_buffer *buffer; | ||
| 488 | acpi_status status; | ||
| 489 | |||
| 490 | /* Ignore all descriptors except Vendor */ | ||
| 491 | |||
| 492 | if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) { | ||
| 493 | return (AE_OK); | ||
| 494 | } | ||
| 495 | |||
| 496 | vendor = &resource->data.vendor_typed; | ||
| 497 | |||
| 498 | /* | ||
| 499 | * For a valid match, these conditions must hold: | ||
| 500 | * | ||
| 501 | * 1) Length of descriptor data must be at least as long as a UUID struct | ||
| 502 | * 2) The UUID subtypes must match | ||
| 503 | * 3) The UUID data must match | ||
| 504 | */ | ||
| 505 | if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) || | ||
| 506 | (vendor->uuid_subtype != info->uuid->subtype) || | ||
| 507 | (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { | ||
| 508 | return (AE_OK); | ||
| 509 | } | ||
| 510 | |||
| 511 | /* Validate/Allocate/Clear caller buffer */ | ||
| 512 | |||
| 513 | buffer = info->buffer; | ||
| 514 | status = acpi_ut_initialize_buffer(buffer, resource->length); | ||
| 515 | if (ACPI_FAILURE(status)) { | ||
| 516 | return (status); | ||
| 517 | } | ||
| 518 | |||
| 519 | /* Found the correct resource, copy and return it */ | ||
| 520 | |||
| 521 | ACPI_MEMCPY(buffer->pointer, resource, resource->length); | ||
| 522 | buffer->length = resource->length; | ||
| 523 | |||
| 524 | /* Found the desired descriptor, terminate resource walk */ | ||
| 525 | |||
| 526 | info->status = AE_OK; | ||
| 527 | return (AE_CTRL_TERMINATE); | ||
| 528 | } | ||
