diff options
Diffstat (limited to 'drivers/acpi/resources/rscalc.c')
-rw-r--r-- | drivers/acpi/resources/rscalc.c | 253 |
1 files changed, 112 insertions, 141 deletions
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index c29d3a447278..eca7439ee9da 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c | |||
@@ -299,13 +299,14 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) | |||
299 | 299 | ||
300 | /* Point to the next object */ | 300 | /* Point to the next object */ |
301 | 301 | ||
302 | resource = ACPI_PTR_ADD(struct acpi_resource, | 302 | resource = |
303 | resource, resource->length); | 303 | ACPI_PTR_ADD(struct acpi_resource, resource, |
304 | resource->length); | ||
304 | } | 305 | } |
305 | 306 | ||
306 | /* Did not find an END_TAG descriptor */ | 307 | /* Did not find an end_tag resource descriptor */ |
307 | 308 | ||
308 | return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); | 309 | return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); |
309 | } | 310 | } |
310 | 311 | ||
311 | /******************************************************************************* | 312 | /******************************************************************************* |
@@ -328,185 +329,155 @@ acpi_status | |||
328 | acpi_rs_get_list_length(u8 * aml_buffer, | 329 | acpi_rs_get_list_length(u8 * aml_buffer, |
329 | u32 aml_buffer_length, acpi_size * size_needed) | 330 | u32 aml_buffer_length, acpi_size * size_needed) |
330 | { | 331 | { |
332 | acpi_status status; | ||
333 | u8 *end_aml; | ||
331 | u8 *buffer; | 334 | u8 *buffer; |
332 | struct acpi_resource_info *resource_info; | ||
333 | u32 buffer_size = 0; | 335 | u32 buffer_size = 0; |
334 | u32 bytes_parsed = 0; | ||
335 | u8 resource_type; | ||
336 | u16 temp16; | 336 | u16 temp16; |
337 | u16 resource_length; | 337 | u16 resource_length; |
338 | u16 header_length; | ||
339 | u32 extra_struct_bytes; | 338 | u32 extra_struct_bytes; |
339 | u8 resource_index; | ||
340 | u8 minimum_aml_resource_length; | ||
340 | 341 | ||
341 | ACPI_FUNCTION_TRACE("rs_get_list_length"); | 342 | ACPI_FUNCTION_TRACE("rs_get_list_length"); |
342 | 343 | ||
343 | while (bytes_parsed < aml_buffer_length) { | 344 | end_aml = aml_buffer + aml_buffer_length; |
344 | /* The next byte in the stream is the resource descriptor type */ | ||
345 | 345 | ||
346 | resource_type = acpi_ut_get_resource_type(aml_buffer); | 346 | /* Walk the list of AML resource descriptors */ |
347 | 347 | ||
348 | /* Get the base stream size and structure sizes for the descriptor */ | 348 | while (aml_buffer < end_aml) { |
349 | /* Validate the Resource Type and Resource Length */ | ||
349 | 350 | ||
350 | resource_info = acpi_rs_get_resource_info(resource_type); | 351 | status = acpi_ut_validate_resource(aml_buffer, &resource_index); |
351 | if (!resource_info) { | 352 | if (ACPI_FAILURE(status)) { |
352 | return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); | 353 | return_ACPI_STATUS(status); |
353 | } | 354 | } |
354 | 355 | ||
355 | /* Get the Length field from the input resource descriptor */ | 356 | /* Get the resource length and base (minimum) AML size */ |
356 | 357 | ||
357 | resource_length = acpi_ut_get_resource_length(aml_buffer); | 358 | resource_length = acpi_ut_get_resource_length(aml_buffer); |
359 | minimum_aml_resource_length = | ||
360 | acpi_gbl_resource_aml_sizes[resource_index]; | ||
358 | 361 | ||
359 | /* Augment the size for descriptors with optional fields */ | 362 | /* |
360 | 363 | * Augment the size for descriptors with optional | |
364 | * and/or variable length fields | ||
365 | */ | ||
361 | extra_struct_bytes = 0; | 366 | extra_struct_bytes = 0; |
367 | buffer = | ||
368 | aml_buffer + acpi_ut_get_resource_header_length(aml_buffer); | ||
362 | 369 | ||
363 | if (!(resource_type & ACPI_RESOURCE_NAME_LARGE)) { | 370 | switch (acpi_ut_get_resource_type(aml_buffer)) { |
371 | case ACPI_RESOURCE_NAME_IRQ: | ||
364 | /* | 372 | /* |
365 | * Small resource descriptors | 373 | * IRQ Resource: |
374 | * Get the number of bits set in the 16-bit IRQ mask | ||
366 | */ | 375 | */ |
367 | header_length = | 376 | ACPI_MOVE_16_TO_16(&temp16, buffer); |
368 | sizeof(struct aml_resource_small_header); | 377 | extra_struct_bytes = |
369 | buffer = aml_buffer + header_length; | 378 | acpi_rs_count_set_bits(temp16) * sizeof(u32); |
370 | 379 | break; | |
371 | switch (resource_type) { | ||
372 | case ACPI_RESOURCE_NAME_IRQ: | ||
373 | /* | ||
374 | * IRQ Resource: | ||
375 | * Get the number of bits set in the IRQ word | ||
376 | */ | ||
377 | ACPI_MOVE_16_TO_16(&temp16, buffer); | ||
378 | extra_struct_bytes = | ||
379 | (acpi_rs_count_set_bits(temp16) * | ||
380 | sizeof(u32)); | ||
381 | break; | ||
382 | |||
383 | case ACPI_RESOURCE_NAME_DMA: | ||
384 | /* | ||
385 | * DMA Resource: | ||
386 | * Get the number of bits set in the DMA channels byte | ||
387 | */ | ||
388 | ACPI_MOVE_16_TO_16(&temp16, buffer); | ||
389 | extra_struct_bytes = | ||
390 | (acpi_rs_count_set_bits(temp16) * | ||
391 | sizeof(u32)); | ||
392 | break; | ||
393 | |||
394 | case ACPI_RESOURCE_NAME_VENDOR_SMALL: | ||
395 | /* | ||
396 | * Vendor Specific Resource: | ||
397 | * Ensure a 32-bit boundary for the structure | ||
398 | */ | ||
399 | extra_struct_bytes = | ||
400 | ACPI_ROUND_UP_to_32_bITS(resource_length); | ||
401 | break; | ||
402 | 380 | ||
403 | case ACPI_RESOURCE_NAME_END_TAG: | 381 | case ACPI_RESOURCE_NAME_DMA: |
404 | /* | 382 | /* |
405 | * End Tag: | 383 | * DMA Resource: |
406 | * Terminate the loop now | 384 | * Get the number of bits set in the 8-bit DMA mask |
407 | */ | 385 | */ |
408 | aml_buffer_length = bytes_parsed; | 386 | extra_struct_bytes = |
409 | break; | 387 | acpi_rs_count_set_bits(*buffer) * sizeof(u32); |
388 | break; | ||
410 | 389 | ||
411 | default: | 390 | case ACPI_RESOURCE_NAME_VENDOR_SMALL: |
412 | break; | ||
413 | } | ||
414 | } else { | ||
415 | /* | 391 | /* |
416 | * Large resource descriptors | 392 | * Vendor Resource: |
393 | * Ensure a 32-bit boundary for the structure | ||
417 | */ | 394 | */ |
418 | header_length = | 395 | extra_struct_bytes = |
419 | sizeof(struct aml_resource_large_header); | 396 | ACPI_ROUND_UP_to_32_bITS(resource_length) - |
420 | buffer = aml_buffer + header_length; | 397 | resource_length; |
398 | break; | ||
421 | 399 | ||
422 | switch (resource_type) { | 400 | case ACPI_RESOURCE_NAME_END_TAG: |
423 | case ACPI_RESOURCE_NAME_VENDOR_LARGE: | 401 | /* |
424 | /* | 402 | * End Tag: This is the normal exit |
425 | * Vendor Defined Resource: | 403 | */ |
426 | * Add vendor data and ensure a 32-bit boundary for the structure | 404 | *size_needed = buffer_size; |
427 | */ | 405 | return_ACPI_STATUS(AE_OK); |
428 | extra_struct_bytes = | ||
429 | ACPI_ROUND_UP_to_32_bITS(resource_length); | ||
430 | break; | ||
431 | 406 | ||
432 | case ACPI_RESOURCE_NAME_ADDRESS32: | 407 | case ACPI_RESOURCE_NAME_VENDOR_LARGE: |
433 | case ACPI_RESOURCE_NAME_ADDRESS16: | 408 | /* |
434 | /* | 409 | * Vendor Resource: |
435 | * 32-Bit or 16-bit Address Resource: | 410 | * Add vendor data and ensure a 32-bit boundary for the structure |
436 | * Add the size of any optional data (resource_source) | 411 | */ |
437 | */ | 412 | extra_struct_bytes = |
438 | extra_struct_bytes = | 413 | ACPI_ROUND_UP_to_32_bITS(resource_length) - |
439 | acpi_rs_stream_option_length | 414 | resource_length; |
440 | (resource_length, | 415 | break; |
441 | resource_info-> | ||
442 | minimum_aml_resource_length); | ||
443 | break; | ||
444 | |||
445 | case ACPI_RESOURCE_NAME_EXTENDED_IRQ: | ||
446 | /* | ||
447 | * Extended IRQ: | ||
448 | * Point past the interrupt_vector_flags to get the | ||
449 | * interrupt_table_length. | ||
450 | */ | ||
451 | buffer++; | ||
452 | 416 | ||
453 | /* | 417 | case ACPI_RESOURCE_NAME_ADDRESS32: |
454 | * Add 4 bytes for each additional interrupt. Note: at least one | 418 | case ACPI_RESOURCE_NAME_ADDRESS16: |
455 | * interrupt is required and is included in the minimum | 419 | /* |
456 | * descriptor size | 420 | * 32-Bit or 16-bit Address Resource: |
457 | */ | 421 | * Add the size of any optional data (resource_source) |
458 | extra_struct_bytes = | 422 | */ |
459 | ((*buffer - 1) * sizeof(u32)); | 423 | extra_struct_bytes = |
424 | acpi_rs_stream_option_length(resource_length, | ||
425 | minimum_aml_resource_length); | ||
426 | break; | ||
460 | 427 | ||
461 | /* Add the size of any optional data (resource_source) */ | 428 | case ACPI_RESOURCE_NAME_EXTENDED_IRQ: |
429 | /* | ||
430 | * Extended IRQ: | ||
431 | * Point past the interrupt_vector_flags to get the | ||
432 | * interrupt_table_length. | ||
433 | */ | ||
434 | buffer++; | ||
435 | |||
436 | extra_struct_bytes = | ||
437 | /* | ||
438 | * Add 4 bytes for each additional interrupt. Note: at | ||
439 | * least one interrupt is required and is included in | ||
440 | * the minimum descriptor size | ||
441 | */ | ||
442 | ((*buffer - 1) * sizeof(u32)) + | ||
443 | /* Add the size of any optional data (resource_source) */ | ||
444 | acpi_rs_stream_option_length(resource_length - | ||
445 | extra_struct_bytes, | ||
446 | minimum_aml_resource_length); | ||
447 | break; | ||
462 | 448 | ||
463 | extra_struct_bytes += | 449 | case ACPI_RESOURCE_NAME_ADDRESS64: |
464 | acpi_rs_stream_option_length(resource_length | 450 | /* |
465 | - | 451 | * 64-Bit Address Resource: |
466 | extra_struct_bytes, | 452 | * Add the size of any optional data (resource_source) |
467 | resource_info-> | 453 | * Ensure a 64-bit boundary for the structure |
468 | minimum_aml_resource_length); | 454 | */ |
469 | break; | 455 | extra_struct_bytes = |
456 | ACPI_ROUND_UP_to_64_bITS | ||
457 | (acpi_rs_stream_option_length | ||
458 | (resource_length, minimum_aml_resource_length)); | ||
459 | break; | ||
470 | 460 | ||
471 | case ACPI_RESOURCE_NAME_ADDRESS64: | 461 | default: |
472 | /* | 462 | break; |
473 | * 64-Bit Address Resource: | ||
474 | * Add the size of any optional data (resource_source) | ||
475 | * Ensure a 64-bit boundary for the structure | ||
476 | */ | ||
477 | extra_struct_bytes = | ||
478 | ACPI_ROUND_UP_to_64_bITS | ||
479 | (acpi_rs_stream_option_length | ||
480 | (resource_length, | ||
481 | resource_info-> | ||
482 | minimum_aml_resource_length)); | ||
483 | break; | ||
484 | |||
485 | default: | ||
486 | break; | ||
487 | } | ||
488 | } | 463 | } |
489 | 464 | ||
490 | /* Update the required buffer size for the internal descriptor structs */ | 465 | /* Update the required buffer size for the internal descriptor structs */ |
491 | 466 | ||
492 | temp16 = | 467 | temp16 = (u16) (acpi_gbl_resource_struct_sizes[resource_index] + |
493 | (u16) (resource_info->minimum_internal_struct_length + | 468 | extra_struct_bytes); |
494 | extra_struct_bytes); | ||
495 | buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(temp16); | 469 | buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(temp16); |
496 | 470 | ||
497 | /* | 471 | /* |
498 | * Update byte count and point to the next resource within the stream | 472 | * Point to the next resource within the stream |
499 | * using the size of the header plus the length contained in the header | 473 | * using the size of the header plus the length contained in the header |
500 | */ | 474 | */ |
501 | temp16 = (u16) (header_length + resource_length); | 475 | aml_buffer += acpi_ut_get_descriptor_length(aml_buffer); |
502 | bytes_parsed += temp16; | ||
503 | aml_buffer += temp16; | ||
504 | } | 476 | } |
505 | 477 | ||
506 | /* This is the data the caller needs */ | 478 | /* Did not find an end_tag resource descriptor */ |
507 | 479 | ||
508 | *size_needed = buffer_size; | 480 | return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); |
509 | return_ACPI_STATUS(AE_OK); | ||
510 | } | 481 | } |
511 | 482 | ||
512 | /******************************************************************************* | 483 | /******************************************************************************* |