Skip to content

Commit 8d74ef9

Browse files
committed
ACPI: Fix buffer/integer type mismatch
This is actually not a bug in the kernel, but rather Microsoft not conforming with the ACPI specification.
1 parent 38f039c commit 8d74ef9

File tree

2 files changed

+11
-17
lines changed

2 files changed

+11
-17
lines changed

drivers/acpi/acpica/dsopcode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode,
123123

124124
/* Offset is in bits, count is in bits */
125125

126-
field_flags = AML_FIELD_ACCESS_BYTE;
126+
field_flags = AML_FIELD_ACCESS_BUFFER;
127127
bit_offset = offset;
128128
bit_count = (u32) length_desc->integer.value;
129129

drivers/acpi/acpica/exfield.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
102102
void *buffer;
103103
u32 function;
104104
u16 accessor_type;
105+
u8 field_flags;
105106

106107
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
107108

@@ -199,11 +200,16 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
199200
* Note: Field.length is in bits.
200201
*/
201202
length =
202-
(acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
203+
(acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
204+
field_flags = obj_desc->common_field.field_flags;
203205

204-
if (length > acpi_gbl_integer_byte_width) {
206+
if (length > acpi_gbl_integer_byte_width ||
207+
(field_flags & AML_FIELD_ACCESS_TYPE_MASK) == AML_FIELD_ACCESS_BUFFER) {
205208

206-
/* Field is too large for an Integer, create a Buffer instead */
209+
/*
210+
* Field is either too large for an Integer, or a actually of type
211+
* buffer, so create a Buffer.
212+
*/
207213

208214
buffer_desc = acpi_ut_create_buffer_object(length);
209215
if (!buffer_desc) {
@@ -366,19 +372,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
366372
} else if (obj_desc->field.region_obj->region.space_id ==
367373
ACPI_ADR_SPACE_GSBUS) {
368374
accessor_type = obj_desc->field.attribute;
369-
length =
370-
acpi_ex_get_serial_access_length(accessor_type,
371-
obj_desc->field.
372-
access_length);
373-
374-
/*
375-
* Add additional 2 bytes for the generic_serial_bus data buffer:
376-
*
377-
* Status; (Byte 0 of the data buffer)
378-
* Length; (Byte 1 of the data buffer)
379-
* Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
380-
*/
381-
length += 2;
375+
length = source_desc->buffer.length;
382376
function = ACPI_WRITE | (accessor_type << 16);
383377
} else { /* IPMI */
384378

0 commit comments

Comments
 (0)