aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2010-08-05 21:09:33 -0400
committerLen Brown <len.brown@intel.com>2010-10-01 01:46:32 -0400
commit09387b43153953006471dbb06ece6bf779d10937 (patch)
tree109d294ec27e0719dfb3ea5a2cd79f6811edd3be
parentc5f0231ee6b0441e4c45f461f2b6652b10195494 (diff)
ACPICA: Revert "Revert "Enable multi-byte EC transfers
This reverts commit f23b9c7(http://git.moblin.org/cgit.cgi/acpica/commit/?id=f23b9c7) The problem with this change was determined to be a problem with the FreeBSD host OSL (OS services layer), not with this patch itself. Therefore, re-introducing this change into the main ACPICA code. See ACPICA bugzilla 863. http://www.acpica.org/bugzilla/show_bug.cgi?id=863 Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/acpica/acobject.h2
-rw-r--r--drivers/acpi/acpica/exfldio.c75
-rw-r--r--drivers/acpi/acpica/exprep.c45
3 files changed, 73 insertions, 49 deletions
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index 54857fa87aaf..bdbfaf22bd14 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -248,7 +248,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
248 u32 base_byte_offset; /* Byte offset within containing object */\ 248 u32 base_byte_offset; /* Byte offset within containing object */\
249 u32 value; /* Value to store into the Bank or Index register */\ 249 u32 value; /* Value to store into the Bank or Index register */\
250 u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\ 250 u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
251 u8 access_bit_width; /* Read/Write size in bits (8-64) */ 251
252 252
253struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ 253struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
254 ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */ 254 ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */
diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c
index 047217303a4b..38293fd3e088 100644
--- a/drivers/acpi/acpica/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -119,8 +119,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
119 } 119 }
120 120
121 /* 121 /*
122 * Exit now for SMBus or IPMI address space, it has a non-linear address space 122 * Exit now for SMBus or IPMI address space, it has a non-linear
123 * and the request cannot be directly validated 123 * address space and the request cannot be directly validated
124 */ 124 */
125 if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS || 125 if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
126 rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) { 126 rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
@@ -147,8 +147,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
147 * (Region length is specified in bytes) 147 * (Region length is specified in bytes)
148 */ 148 */
149 if (rgn_desc->region.length < 149 if (rgn_desc->region.length <
150 (obj_desc->common_field.base_byte_offset + 150 (obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
151 field_datum_byte_offset +
152 obj_desc->common_field.access_byte_width)) { 151 obj_desc->common_field.access_byte_width)) {
153 if (acpi_gbl_enable_interpreter_slack) { 152 if (acpi_gbl_enable_interpreter_slack) {
154 /* 153 /*
@@ -680,6 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
680 u32 buffer_tail_bits; 679 u32 buffer_tail_bits;
681 u32 datum_count; 680 u32 datum_count;
682 u32 field_datum_count; 681 u32 field_datum_count;
682 u32 access_bit_width;
683 u32 i; 683 u32 i;
684 684
685 ACPI_FUNCTION_TRACE(ex_extract_from_field); 685 ACPI_FUNCTION_TRACE(ex_extract_from_field);
@@ -694,16 +694,36 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
694 694
695 return_ACPI_STATUS(AE_BUFFER_OVERFLOW); 695 return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
696 } 696 }
697
697 ACPI_MEMSET(buffer, 0, buffer_length); 698 ACPI_MEMSET(buffer, 0, buffer_length);
699 access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
700
701 /* Handle the simple case here */
702
703 if ((obj_desc->common_field.start_field_bit_offset == 0) &&
704 (obj_desc->common_field.bit_length == access_bit_width)) {
705 status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ);
706 return_ACPI_STATUS(status);
707 }
708
709/* TBD: Move to common setup code */
710
711 /* Field algorithm is limited to sizeof(u64), truncate if needed */
712
713 if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
714 obj_desc->common_field.access_byte_width = sizeof(u64);
715 access_bit_width = sizeof(u64) * 8;
716 }
698 717
699 /* Compute the number of datums (access width data items) */ 718 /* Compute the number of datums (access width data items) */
700 719
701 datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, 720 datum_count =
702 obj_desc->common_field.access_bit_width); 721 ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
722 access_bit_width);
723
703 field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + 724 field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
704 obj_desc->common_field. 725 obj_desc->common_field.
705 start_field_bit_offset, 726 start_field_bit_offset,
706 obj_desc->common_field.
707 access_bit_width); 727 access_bit_width);
708 728
709 /* Priming read from the field */ 729 /* Priming read from the field */
@@ -738,12 +758,11 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
738 * This avoids the differences in behavior between different compilers 758 * This avoids the differences in behavior between different compilers
739 * concerning shift values larger than the target data width. 759 * concerning shift values larger than the target data width.
740 */ 760 */
741 if ((obj_desc->common_field.access_bit_width - 761 if (access_bit_width -
742 obj_desc->common_field.start_field_bit_offset) < 762 obj_desc->common_field.start_field_bit_offset <
743 ACPI_INTEGER_BIT_SIZE) { 763 ACPI_INTEGER_BIT_SIZE) {
744 merged_datum |= 764 merged_datum |=
745 raw_datum << (obj_desc->common_field. 765 raw_datum << (access_bit_width -
746 access_bit_width -
747 obj_desc->common_field. 766 obj_desc->common_field.
748 start_field_bit_offset); 767 start_field_bit_offset);
749 } 768 }
@@ -765,8 +784,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
765 784
766 /* Mask off any extra bits in the last datum */ 785 /* Mask off any extra bits in the last datum */
767 786
768 buffer_tail_bits = obj_desc->common_field.bit_length % 787 buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
769 obj_desc->common_field.access_bit_width;
770 if (buffer_tail_bits) { 788 if (buffer_tail_bits) {
771 merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); 789 merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
772 } 790 }
@@ -798,6 +816,7 @@ acpi_status
798acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, 816acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
799 void *buffer, u32 buffer_length) 817 void *buffer, u32 buffer_length)
800{ 818{
819 void *new_buffer;
801 acpi_status status; 820 acpi_status status;
802 u64 mask; 821 u64 mask;
803 u64 width_mask; 822 u64 width_mask;
@@ -808,9 +827,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
808 u32 buffer_tail_bits; 827 u32 buffer_tail_bits;
809 u32 datum_count; 828 u32 datum_count;
810 u32 field_datum_count; 829 u32 field_datum_count;
811 u32 i; 830 u32 access_bit_width;
812 u32 required_length; 831 u32 required_length;
813 void *new_buffer; 832 u32 i;
814 833
815 ACPI_FUNCTION_TRACE(ex_insert_into_field); 834 ACPI_FUNCTION_TRACE(ex_insert_into_field);
816 835
@@ -844,17 +863,24 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
844 buffer_length = required_length; 863 buffer_length = required_length;
845 } 864 }
846 865
866/* TBD: Move to common setup code */
867
868 /* Algo is limited to sizeof(u64), so cut the access_byte_width */
869 if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
870 obj_desc->common_field.access_byte_width = sizeof(u64);
871 }
872
873 access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
874
847 /* 875 /*
848 * Create the bitmasks used for bit insertion. 876 * Create the bitmasks used for bit insertion.
849 * Note: This if/else is used to bypass compiler differences with the 877 * Note: This if/else is used to bypass compiler differences with the
850 * shift operator 878 * shift operator
851 */ 879 */
852 if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) { 880 if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
853 width_mask = ACPI_UINT64_MAX; 881 width_mask = ACPI_UINT64_MAX;
854 } else { 882 } else {
855 width_mask = 883 width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
856 ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
857 access_bit_width);
858 } 884 }
859 885
860 mask = width_mask & 886 mask = width_mask &
@@ -863,12 +889,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
863 /* Compute the number of datums (access width data items) */ 889 /* Compute the number of datums (access width data items) */
864 890
865 datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, 891 datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
866 obj_desc->common_field.access_bit_width); 892 access_bit_width);
867 893
868 field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + 894 field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
869 obj_desc->common_field. 895 obj_desc->common_field.
870 start_field_bit_offset, 896 start_field_bit_offset,
871 obj_desc->common_field.
872 access_bit_width); 897 access_bit_width);
873 898
874 /* Get initial Datum from the input buffer */ 899 /* Get initial Datum from the input buffer */
@@ -905,12 +930,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
905 * This avoids the differences in behavior between different compilers 930 * This avoids the differences in behavior between different compilers
906 * concerning shift values larger than the target data width. 931 * concerning shift values larger than the target data width.
907 */ 932 */
908 if ((obj_desc->common_field.access_bit_width - 933 if ((access_bit_width -
909 obj_desc->common_field.start_field_bit_offset) < 934 obj_desc->common_field.start_field_bit_offset) <
910 ACPI_INTEGER_BIT_SIZE) { 935 ACPI_INTEGER_BIT_SIZE) {
911 merged_datum = 936 merged_datum =
912 raw_datum >> (obj_desc->common_field. 937 raw_datum >> (access_bit_width -
913 access_bit_width -
914 obj_desc->common_field. 938 obj_desc->common_field.
915 start_field_bit_offset); 939 start_field_bit_offset);
916 } else { 940 } else {
@@ -929,6 +953,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
929 ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset, 953 ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
930 ACPI_MIN(obj_desc->common_field.access_byte_width, 954 ACPI_MIN(obj_desc->common_field.access_byte_width,
931 buffer_length - buffer_offset)); 955 buffer_length - buffer_offset));
956
932 merged_datum |= 957 merged_datum |=
933 raw_datum << obj_desc->common_field.start_field_bit_offset; 958 raw_datum << obj_desc->common_field.start_field_bit_offset;
934 } 959 }
@@ -937,7 +962,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
937 962
938 buffer_tail_bits = (obj_desc->common_field.bit_length + 963 buffer_tail_bits = (obj_desc->common_field.bit_length +
939 obj_desc->common_field.start_field_bit_offset) % 964 obj_desc->common_field.start_field_bit_offset) %
940 obj_desc->common_field.access_bit_width; 965 access_bit_width;
941 if (buffer_tail_bits) { 966 if (buffer_tail_bits) {
942 mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); 967 mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
943 } 968 }
diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c
index 98a331d2249b..7aae29f73d3f 100644
--- a/drivers/acpi/acpica/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -355,12 +355,10 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
355 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 355 return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
356 } 356 }
357 357
358 /* Setup width (access granularity) fields */ 358 /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */
359 359
360 obj_desc->common_field.access_byte_width = (u8) 360 obj_desc->common_field.access_byte_width = (u8)
361 ACPI_DIV_8(access_bit_width); /* 1, 2, 4, 8 */ 361 ACPI_DIV_8(access_bit_width);
362
363 obj_desc->common_field.access_bit_width = (u8) access_bit_width;
364 362
365 /* 363 /*
366 * base_byte_offset is the address of the start of the field within the 364 * base_byte_offset is the address of the start of the field within the
@@ -405,8 +403,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
405{ 403{
406 union acpi_operand_object *obj_desc; 404 union acpi_operand_object *obj_desc;
407 union acpi_operand_object *second_desc = NULL; 405 union acpi_operand_object *second_desc = NULL;
408 u32 type;
409 acpi_status status; 406 acpi_status status;
407 u32 access_byte_width;
408 u32 type;
410 409
411 ACPI_FUNCTION_TRACE(ex_prep_field_value); 410 ACPI_FUNCTION_TRACE(ex_prep_field_value);
412 411
@@ -421,8 +420,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
421 type = acpi_ns_get_type(info->region_node); 420 type = acpi_ns_get_type(info->region_node);
422 if (type != ACPI_TYPE_REGION) { 421 if (type != ACPI_TYPE_REGION) {
423 ACPI_ERROR((AE_INFO, 422 ACPI_ERROR((AE_INFO,
424 "Needed Region, found type 0x%X (%s)", 423 "Needed Region, found type 0x%X (%s)", type,
425 type, acpi_ut_get_type_name(type))); 424 acpi_ut_get_type_name(type)));
426 425
427 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 426 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
428 } 427 }
@@ -438,7 +437,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
438 /* Initialize areas of the object that are common to all fields */ 437 /* Initialize areas of the object that are common to all fields */
439 438
440 obj_desc->common_field.node = info->field_node; 439 obj_desc->common_field.node = info->field_node;
441 status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags, 440 status = acpi_ex_prep_common_field_object(obj_desc,
441 info->field_flags,
442 info->attribute, 442 info->attribute,
443 info->field_bit_position, 443 info->field_bit_position,
444 info->field_bit_length); 444 info->field_bit_length);
@@ -455,26 +455,25 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
455 obj_desc->field.region_obj = 455 obj_desc->field.region_obj =
456 acpi_ns_get_attached_object(info->region_node); 456 acpi_ns_get_attached_object(info->region_node);
457 457
458 /* An additional reference for the container */ 458 /* Allow full data read from EC address space */
459 459
460 acpi_ut_add_reference(obj_desc->field.region_obj); 460 if ((obj_desc->field.region_obj->region.space_id ==
461 ACPI_ADR_SPACE_EC)
462 && (obj_desc->common_field.bit_length > 8)) {
463 access_byte_width =
464 ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.
465 bit_length);
466
467 /* Maximum byte width supported is 255 */
461 468
462 /* allow full data read from EC address space */ 469 if (access_byte_width < 256) {
463 if (obj_desc->field.region_obj->region.space_id ==
464 ACPI_ADR_SPACE_EC) {
465 if (obj_desc->common_field.bit_length > 8) {
466 unsigned width =
467 ACPI_ROUND_BITS_UP_TO_BYTES(
468 obj_desc->common_field.bit_length);
469 // access_bit_width is u8, don't overflow it
470 if (width > 8)
471 width = 8;
472 obj_desc->common_field.access_byte_width = 470 obj_desc->common_field.access_byte_width =
473 width; 471 (u8)access_byte_width;
474 obj_desc->common_field.access_bit_width =
475 8 * width;
476 } 472 }
477 } 473 }
474 /* An additional reference for the container */
475
476 acpi_ut_add_reference(obj_desc->field.region_obj);
478 477
479 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 478 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
480 "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", 479 "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",