diff options
Diffstat (limited to 'drivers/acpi/executer/exfldio.c')
-rw-r--r-- | drivers/acpi/executer/exfldio.c | 67 |
1 files changed, 44 insertions, 23 deletions
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index bd1af35f7fcf..051053f7cccb 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c | |||
@@ -87,7 +87,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, | |||
87 | acpi_status status = AE_OK; | 87 | acpi_status status = AE_OK; |
88 | union acpi_operand_object *rgn_desc; | 88 | union acpi_operand_object *rgn_desc; |
89 | 89 | ||
90 | ACPI_FUNCTION_TRACE_U32("ex_setup_region", field_datum_byte_offset); | 90 | ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset); |
91 | 91 | ||
92 | rgn_desc = obj_desc->common_field.region_obj; | 92 | rgn_desc = obj_desc->common_field.region_obj; |
93 | 93 | ||
@@ -112,7 +112,18 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, | |||
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | /* Exit if Address/Length have been disallowed by the host OS */ | ||
116 | |||
117 | if (rgn_desc->common.flags & AOPOBJ_INVALID) { | ||
118 | return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Exit now for SMBus address space, it has a non-linear address space | ||
123 | * and the request cannot be directly validated | ||
124 | */ | ||
115 | if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { | 125 | if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { |
126 | |||
116 | /* SMBus has a non-linear address space */ | 127 | /* SMBus has a non-linear address space */ |
117 | 128 | ||
118 | return_ACPI_STATUS(AE_OK); | 129 | return_ACPI_STATUS(AE_OK); |
@@ -134,10 +145,10 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, | |||
134 | * length of one field datum (access width) must fit within the region. | 145 | * length of one field datum (access width) must fit within the region. |
135 | * (Region length is specified in bytes) | 146 | * (Region length is specified in bytes) |
136 | */ | 147 | */ |
137 | if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + | 148 | if (rgn_desc->region.length < |
138 | field_datum_byte_offset + | 149 | (obj_desc->common_field.base_byte_offset + |
139 | obj_desc->common_field. | 150 | field_datum_byte_offset + |
140 | access_byte_width)) { | 151 | obj_desc->common_field.access_byte_width)) { |
141 | if (acpi_gbl_enable_interpreter_slack) { | 152 | if (acpi_gbl_enable_interpreter_slack) { |
142 | /* | 153 | /* |
143 | * Slack mode only: We will go ahead and allow access to this | 154 | * Slack mode only: We will go ahead and allow access to this |
@@ -217,7 +228,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, | |||
217 | union acpi_operand_object *rgn_desc; | 228 | union acpi_operand_object *rgn_desc; |
218 | acpi_physical_address address; | 229 | acpi_physical_address address; |
219 | 230 | ||
220 | ACPI_FUNCTION_TRACE("ex_access_region"); | 231 | ACPI_FUNCTION_TRACE(ex_access_region); |
221 | 232 | ||
222 | /* | 233 | /* |
223 | * Ensure that the region operands are fully evaluated and verify | 234 | * Ensure that the region operands are fully evaluated and verify |
@@ -246,7 +257,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, | |||
246 | } | 257 | } |
247 | 258 | ||
248 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, | 259 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, |
249 | " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n", | 260 | " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", |
250 | acpi_ut_get_region_name(rgn_desc->region. | 261 | acpi_ut_get_region_name(rgn_desc->region. |
251 | space_id), | 262 | space_id), |
252 | rgn_desc->region.space_id, | 263 | rgn_desc->region.space_id, |
@@ -352,7 +363,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, | |||
352 | acpi_status status; | 363 | acpi_status status; |
353 | acpi_integer local_value; | 364 | acpi_integer local_value; |
354 | 365 | ||
355 | ACPI_FUNCTION_TRACE_U32("ex_field_datum_io", field_datum_byte_offset); | 366 | ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset); |
356 | 367 | ||
357 | if (read_write == ACPI_READ) { | 368 | if (read_write == ACPI_READ) { |
358 | if (!value) { | 369 | if (!value) { |
@@ -487,10 +498,11 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, | |||
487 | } | 498 | } |
488 | 499 | ||
489 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, | 500 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
490 | "I/O to Data Register: value_ptr %p\n", | 501 | "I/O to Data Register: ValuePtr %p\n", |
491 | value)); | 502 | value)); |
492 | 503 | ||
493 | if (read_write == ACPI_READ) { | 504 | if (read_write == ACPI_READ) { |
505 | |||
494 | /* Read the datum from the data_register */ | 506 | /* Read the datum from the data_register */ |
495 | 507 | ||
496 | status = | 508 | status = |
@@ -559,7 +571,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, | |||
559 | acpi_integer merged_value; | 571 | acpi_integer merged_value; |
560 | acpi_integer current_value; | 572 | acpi_integer current_value; |
561 | 573 | ||
562 | ACPI_FUNCTION_TRACE_U32("ex_write_with_update_rule", mask); | 574 | ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask); |
563 | 575 | ||
564 | /* Start with the new bits */ | 576 | /* Start with the new bits */ |
565 | 577 | ||
@@ -568,6 +580,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, | |||
568 | /* If the mask is all ones, we don't need to worry about the update rule */ | 580 | /* If the mask is all ones, we don't need to worry about the update rule */ |
569 | 581 | ||
570 | if (mask != ACPI_INTEGER_MAX) { | 582 | if (mask != ACPI_INTEGER_MAX) { |
583 | |||
571 | /* Decode the update rule */ | 584 | /* Decode the update rule */ |
572 | 585 | ||
573 | switch (obj_desc->common_field. | 586 | switch (obj_desc->common_field. |
@@ -614,7 +627,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, | |||
614 | default: | 627 | default: |
615 | 628 | ||
616 | ACPI_ERROR((AE_INFO, | 629 | ACPI_ERROR((AE_INFO, |
617 | "Unknown update_rule value: %X", | 630 | "Unknown UpdateRule value: %X", |
618 | (obj_desc->common_field. | 631 | (obj_desc->common_field. |
619 | field_flags & | 632 | field_flags & |
620 | AML_FIELD_UPDATE_RULE_MASK))); | 633 | AML_FIELD_UPDATE_RULE_MASK))); |
@@ -623,7 +636,7 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, | |||
623 | } | 636 | } |
624 | 637 | ||
625 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, | 638 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
626 | "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n", | 639 | "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n", |
627 | ACPI_FORMAT_UINT64(mask), | 640 | ACPI_FORMAT_UINT64(mask), |
628 | field_datum_byte_offset, | 641 | field_datum_byte_offset, |
629 | obj_desc->common_field.access_byte_width, | 642 | obj_desc->common_field.access_byte_width, |
@@ -666,7 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, | |||
666 | u32 field_datum_count; | 679 | u32 field_datum_count; |
667 | u32 i; | 680 | u32 i; |
668 | 681 | ||
669 | ACPI_FUNCTION_TRACE("ex_extract_from_field"); | 682 | ACPI_FUNCTION_TRACE(ex_extract_from_field); |
670 | 683 | ||
671 | /* Validate target buffer and clear it */ | 684 | /* Validate target buffer and clear it */ |
672 | 685 | ||
@@ -704,6 +717,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, | |||
704 | /* Read the rest of the field */ | 717 | /* Read the rest of the field */ |
705 | 718 | ||
706 | for (i = 1; i < field_datum_count; i++) { | 719 | for (i = 1; i < field_datum_count; i++) { |
720 | |||
707 | /* Get next input datum from the field */ | 721 | /* Get next input datum from the field */ |
708 | 722 | ||
709 | field_offset += obj_desc->common_field.access_byte_width; | 723 | field_offset += obj_desc->common_field.access_byte_width; |
@@ -771,6 +785,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
771 | { | 785 | { |
772 | acpi_status status; | 786 | acpi_status status; |
773 | acpi_integer mask; | 787 | acpi_integer mask; |
788 | acpi_integer width_mask; | ||
774 | acpi_integer merged_datum; | 789 | acpi_integer merged_datum; |
775 | acpi_integer raw_datum = 0; | 790 | acpi_integer raw_datum = 0; |
776 | u32 field_offset = 0; | 791 | u32 field_offset = 0; |
@@ -780,7 +795,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
780 | u32 field_datum_count; | 795 | u32 field_datum_count; |
781 | u32 i; | 796 | u32 i; |
782 | 797 | ||
783 | ACPI_FUNCTION_TRACE("ex_insert_into_field"); | 798 | ACPI_FUNCTION_TRACE(ex_insert_into_field); |
784 | 799 | ||
785 | /* Validate input buffer */ | 800 | /* Validate input buffer */ |
786 | 801 | ||
@@ -795,15 +810,20 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
795 | 810 | ||
796 | /* Compute the number of datums (access width data items) */ | 811 | /* Compute the number of datums (access width data items) */ |
797 | 812 | ||
813 | width_mask = | ||
814 | ACPI_MASK_BITS_ABOVE(obj_desc->common_field.access_bit_width); | ||
798 | mask = | 815 | mask = |
799 | ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset); | 816 | width_mask & ACPI_MASK_BITS_BELOW(obj_desc->common_field. |
800 | datum_count = | 817 | start_field_bit_offset); |
801 | ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, | 818 | |
802 | obj_desc->common_field.access_bit_width); | 819 | datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, |
803 | field_datum_count = | 820 | obj_desc->common_field.access_bit_width); |
804 | ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + | 821 | |
805 | obj_desc->common_field.start_field_bit_offset, | 822 | field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + |
806 | obj_desc->common_field.access_bit_width); | 823 | obj_desc->common_field. |
824 | start_field_bit_offset, | ||
825 | obj_desc->common_field. | ||
826 | access_bit_width); | ||
807 | 827 | ||
808 | /* Get initial Datum from the input buffer */ | 828 | /* Get initial Datum from the input buffer */ |
809 | 829 | ||
@@ -817,6 +837,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
817 | /* Write the entire field */ | 837 | /* Write the entire field */ |
818 | 838 | ||
819 | for (i = 1; i < field_datum_count; i++) { | 839 | for (i = 1; i < field_datum_count; i++) { |
840 | |||
820 | /* Write merged datum to the target field */ | 841 | /* Write merged datum to the target field */ |
821 | 842 | ||
822 | merged_datum &= mask; | 843 | merged_datum &= mask; |
@@ -833,7 +854,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
833 | merged_datum = raw_datum >> | 854 | merged_datum = raw_datum >> |
834 | (obj_desc->common_field.access_bit_width - | 855 | (obj_desc->common_field.access_bit_width - |
835 | obj_desc->common_field.start_field_bit_offset); | 856 | obj_desc->common_field.start_field_bit_offset); |
836 | mask = ACPI_INTEGER_MAX; | 857 | mask = width_mask; |
837 | 858 | ||
838 | if (i == datum_count) { | 859 | if (i == datum_count) { |
839 | break; | 860 | break; |