Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPICA: Update for field unit access

Mostly for access to Generic Serial Bus, but also cleanup
for the other fields.

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Bob Moore and committed by
Rafael J. Wysocki
e324e101 f8553720

+448 -285
+3
drivers/acpi/acpica/acinterp.h
··· 124 124 * exfield - ACPI AML (p-code) execution - field manipulation 125 125 */ 126 126 acpi_status 127 + acpi_ex_get_protocol_buffer_length(u32 protocol_id, u32 *return_length); 128 + 129 + acpi_status 127 130 acpi_ex_common_buffer_setup(union acpi_operand_object *obj_desc, 128 131 u32 buffer_length, u32 * datum_count); 129 132
+432 -280
drivers/acpi/acpica/exfield.c
··· 1 1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 2 /****************************************************************************** 3 3 * 4 - * Module Name: exfield - ACPI AML (p-code) execution - field manipulation 4 + * Module Name: exfield - AML execution - field_unit read/write 5 5 * 6 6 * Copyright (C) 2000 - 2018, Intel Corp. 7 7 * ··· 17 17 ACPI_MODULE_NAME("exfield") 18 18 19 19 /* Local prototypes */ 20 - static u32 21 - acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length); 20 + static acpi_status 21 + acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc, 22 + union acpi_operand_object **return_buffer); 23 + 24 + static acpi_status 25 + acpi_ex_write_serial_bus(union acpi_operand_object *source_desc, 26 + union acpi_operand_object *obj_desc, 27 + union acpi_operand_object **return_buffer); 28 + 29 + static acpi_status 30 + acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer); 31 + 32 + static acpi_status 33 + acpi_ex_write_gpio(union acpi_operand_object *source_desc, 34 + union acpi_operand_object *obj_desc, 35 + union acpi_operand_object **return_buffer); 36 + 37 + /* 38 + * This table maps the various Attrib protocols to the byte transfer 39 + * length. Used for the generic serial bus. 40 + */ 41 + #define ACPI_INVALID_PROTOCOL_ID 0x80 42 + #define ACPI_MAX_PROTOCOL_ID 0x0F 43 + 44 + const u8 acpi_protocol_lengths[] = { 45 + ACPI_INVALID_PROTOCOL_ID, /* 0 - reserved */ 46 + ACPI_INVALID_PROTOCOL_ID, /* 1 - reserved */ 47 + 0x00, /* 2 - ATTRIB_QUICK */ 48 + ACPI_INVALID_PROTOCOL_ID, /* 3 - reserved */ 49 + 0x01, /* 4 - ATTRIB_SEND_RECEIVE */ 50 + ACPI_INVALID_PROTOCOL_ID, /* 5 - reserved */ 51 + 0x01, /* 6 - ATTRIB_BYTE */ 52 + ACPI_INVALID_PROTOCOL_ID, /* 7 - reserved */ 53 + 0x02, /* 8 - ATTRIB_WORD */ 54 + ACPI_INVALID_PROTOCOL_ID, /* 9 - reserved */ 55 + 0xFF, /* A - ATTRIB_BLOCK */ 56 + 0xFF, /* B - ATTRIB_BYTES */ 57 + 0x02, /* C - ATTRIB_PROCESS_CALL */ 58 + 0xFF, /* D - ATTRIB_BLOCK_PROCESS_CALL */ 59 + 0xFF, /* E - ATTRIB_RAW_BYTES */ 60 + 0xFF /* F - ATTRIB_RAW_PROCESS_BYTES */ 61 + }; 22 62 23 63 /******************************************************************************* 24 64 * 25 - * FUNCTION: acpi_ex_get_serial_access_length 65 + * FUNCTION: acpi_ex_get_protocol_buffer_length 26 66 * 27 - * PARAMETERS: accessor_type - The type of the protocol indicated by region 67 + * PARAMETERS: protocol_id - The type of the protocol indicated by region 28 68 * field access attributes 29 - * access_length - The access length of the region field 69 + * return_length - Where the protocol byte transfer length is 70 + * returned 30 71 * 31 - * RETURN: Decoded access length 72 + * RETURN: Status and decoded byte transfer length 32 73 * 33 74 * DESCRIPTION: This routine returns the length of the generic_serial_bus 34 75 * protocol bytes 35 76 * 36 77 ******************************************************************************/ 37 78 38 - static u32 39 - acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length) 79 + acpi_status 80 + acpi_ex_get_protocol_buffer_length(u32 protocol_id, u32 *return_length) 40 81 { 41 - u32 length; 42 82 43 - switch (accessor_type) { 44 - case AML_FIELD_ATTRIB_QUICK: 83 + if ((protocol_id > ACPI_MAX_PROTOCOL_ID) || 84 + (acpi_protocol_lengths[protocol_id] == ACPI_INVALID_PROTOCOL_ID)) { 85 + ACPI_ERROR((AE_INFO, 86 + "Invalid Field/AccessAs protocol ID: 0x%4.4X", 87 + protocol_id)); 45 88 46 - length = 0; 47 - break; 48 - 49 - case AML_FIELD_ATTRIB_SEND_RCV: 50 - case AML_FIELD_ATTRIB_BYTE: 51 - 52 - length = 1; 53 - break; 54 - 55 - case AML_FIELD_ATTRIB_WORD: 56 - case AML_FIELD_ATTRIB_WORD_CALL: 57 - 58 - length = 2; 59 - break; 60 - 61 - case AML_FIELD_ATTRIB_MULTIBYTE: 62 - case AML_FIELD_ATTRIB_RAW_BYTES: 63 - 64 - length = access_length; 65 - break; 66 - 67 - case AML_FIELD_ATTRIB_RAW_PROCESS: 68 - /* 69 - * Worst case bidirectional buffer size. This ignores the 70 - * access_length argument to access_as because it is not needed. 71 - * August 2018. 72 - */ 73 - length = ACPI_MAX_GSBUS_BUFFER_SIZE; 74 - break; 75 - 76 - case AML_FIELD_ATTRIB_BLOCK: 77 - case AML_FIELD_ATTRIB_BLOCK_CALL: 78 - default: 79 - 80 - length = ACPI_GSBUS_BUFFER_SIZE - 2; 81 - break; 89 + return (AE_AML_PROTOCOL); 82 90 } 83 91 84 - return (length); 92 + *return_length = acpi_protocol_lengths[protocol_id]; 93 + return (AE_OK); 85 94 } 86 95 87 96 /******************************************************************************* ··· 115 106 { 116 107 acpi_status status; 117 108 union acpi_operand_object *buffer_desc; 118 - acpi_size length; 119 109 void *buffer; 120 - u32 function; 121 - u16 accessor_type; 110 + u32 buffer_length; 122 111 123 112 ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); 124 113 ··· 147 140 ACPI_ADR_SPACE_GSBUS 148 141 || obj_desc->field.region_obj->region.space_id == 149 142 ACPI_ADR_SPACE_IPMI)) { 150 - /* 151 - * This is an SMBus, GSBus or IPMI read. We must create a buffer to 152 - * hold the data and then directly access the region handler. 153 - * 154 - * Note: SMBus and GSBus protocol value is passed in upper 16-bits 155 - * of Function 156 - */ 157 - if (obj_desc->field.region_obj->region.space_id == 158 - ACPI_ADR_SPACE_SMBUS) { 159 - length = ACPI_SMBUS_BUFFER_SIZE; 160 - function = 161 - ACPI_READ | (obj_desc->field.attribute << 16); 162 - } else if (obj_desc->field.region_obj->region.space_id == 163 - ACPI_ADR_SPACE_GSBUS) { 164 - accessor_type = obj_desc->field.attribute; 165 - if (accessor_type == AML_FIELD_ATTRIB_RAW_PROCESS) { 166 - ACPI_ERROR((AE_INFO, 167 - "Invalid direct read using bidirectional write-then-read protocol")); 168 143 169 - return_ACPI_STATUS(AE_AML_PROTOCOL); 170 - } 144 + /* SMBus, GSBus, IPMI serial */ 171 145 172 - length = 173 - acpi_ex_get_serial_access_length(accessor_type, 174 - obj_desc->field. 175 - access_length); 176 - 177 - /* 178 - * Add additional 2 bytes for the generic_serial_bus data buffer: 179 - * 180 - * Status; (Byte 0 of the data buffer) 181 - * Length; (Byte 1 of the data buffer) 182 - * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 183 - */ 184 - length += 2; 185 - function = ACPI_READ | (accessor_type << 16); 186 - } else { /* IPMI */ 187 - 188 - length = ACPI_IPMI_BUFFER_SIZE; 189 - function = ACPI_READ; 190 - } 191 - 192 - buffer_desc = acpi_ut_create_buffer_object(length); 193 - if (!buffer_desc) { 194 - return_ACPI_STATUS(AE_NO_MEMORY); 195 - } 196 - 197 - /* Lock entire transaction if requested */ 198 - 199 - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); 200 - 201 - /* Call the region handler for the read */ 202 - 203 - status = acpi_ex_access_region(obj_desc, 0, 204 - ACPI_CAST_PTR(u64, 205 - buffer_desc-> 206 - buffer.pointer), 207 - function); 208 - 209 - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 210 - goto exit; 146 + status = acpi_ex_read_serial_bus(obj_desc, ret_buffer_desc); 147 + return_ACPI_STATUS(status); 211 148 } 212 149 213 150 /* ··· 164 213 * 165 214 * Note: Field.length is in bits. 166 215 */ 167 - length = 216 + buffer_length = 168 217 (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length); 169 218 170 - if (length > acpi_gbl_integer_byte_width) { 219 + if (buffer_length > acpi_gbl_integer_byte_width) { 171 220 172 221 /* Field is too large for an Integer, create a Buffer instead */ 173 222 174 - buffer_desc = acpi_ut_create_buffer_object(length); 223 + buffer_desc = acpi_ut_create_buffer_object(buffer_length); 175 224 if (!buffer_desc) { 176 225 return_ACPI_STATUS(AE_NO_MEMORY); 177 226 } ··· 184 233 return_ACPI_STATUS(AE_NO_MEMORY); 185 234 } 186 235 187 - length = acpi_gbl_integer_byte_width; 236 + buffer_length = acpi_gbl_integer_byte_width; 188 237 buffer = &buffer_desc->integer.value; 189 238 } 190 239 191 240 if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && 192 241 (obj_desc->field.region_obj->region.space_id == 193 242 ACPI_ADR_SPACE_GPIO)) { 194 - /* 195 - * For GPIO (general_purpose_io), the Address will be the bit offset 196 - * from the previous Connection() operator, making it effectively a 197 - * pin number index. The bit_length is the length of the field, which 198 - * is thus the number of pins. 199 - */ 200 - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 201 - "GPIO FieldRead [FROM]: Pin %u Bits %u\n", 202 - obj_desc->field.pin_number_index, 203 - obj_desc->field.bit_length)); 204 243 205 - /* Lock entire transaction if requested */ 244 + /* General Purpose I/O */ 206 245 207 - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); 208 - 209 - /* Perform the write */ 210 - 211 - status = 212 - acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, 213 - ACPI_READ); 214 - 215 - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 216 - if (ACPI_FAILURE(status)) { 217 - acpi_ut_remove_reference(buffer_desc); 218 - } else { 219 - *ret_buffer_desc = buffer_desc; 220 - } 221 - return_ACPI_STATUS(status); 246 + status = acpi_ex_read_gpio(obj_desc, buffer); 247 + goto exit; 222 248 } 223 249 224 250 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 225 251 "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", 226 252 obj_desc, obj_desc->common.type, buffer, 227 - (u32) length)); 253 + buffer_length)); 228 254 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 229 255 "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", 230 256 obj_desc->common_field.bit_length, ··· 214 286 215 287 /* Read from the field */ 216 288 217 - status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); 289 + status = acpi_ex_extract_from_field(obj_desc, buffer, buffer_length); 218 290 acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 219 291 220 292 exit: ··· 247 319 union acpi_operand_object **result_desc) 248 320 { 249 321 acpi_status status; 250 - u32 length; 251 - u32 data_length; 322 + u32 buffer_length; 252 323 void *buffer; 253 - union acpi_operand_object *buffer_desc; 254 - u32 function; 255 - u16 accessor_type; 256 324 257 325 ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); 258 326 ··· 271 347 } 272 348 } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && 273 349 (obj_desc->field.region_obj->region.space_id == 350 + ACPI_ADR_SPACE_GPIO)) { 351 + 352 + /* General Purpose I/O */ 353 + 354 + status = acpi_ex_write_gpio(source_desc, obj_desc, result_desc); 355 + return_ACPI_STATUS(status); 356 + } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && 357 + (obj_desc->field.region_obj->region.space_id == 274 358 ACPI_ADR_SPACE_SMBUS 275 359 || obj_desc->field.region_obj->region.space_id == 276 360 ACPI_ADR_SPACE_GSBUS 277 361 || obj_desc->field.region_obj->region.space_id == 278 362 ACPI_ADR_SPACE_IPMI)) { 279 - /* 280 - * This is an SMBus, GSBus or IPMI write. We will bypass the entire 281 - * field mechanism and handoff the buffer directly to the handler. 282 - * For these address spaces, the buffer is bi-directional; on a 283 - * write, return data is returned in the same buffer. 284 - * 285 - * Source must be a buffer of sufficient size: 286 - * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or 287 - * ACPI_IPMI_BUFFER_SIZE. 288 - * 289 - * Note: SMBus and GSBus protocol type is passed in upper 16-bits 290 - * of Function 291 - */ 292 - if (source_desc->common.type != ACPI_TYPE_BUFFER) { 293 - ACPI_ERROR((AE_INFO, 294 - "SMBus/IPMI/GenericSerialBus write requires " 295 - "Buffer, found type %s", 296 - acpi_ut_get_object_type_name(source_desc))); 297 363 298 - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 299 - } 300 - 301 - if (obj_desc->field.region_obj->region.space_id == 302 - ACPI_ADR_SPACE_SMBUS) { 303 - length = ACPI_SMBUS_BUFFER_SIZE; 304 - data_length = length; 305 - function = 306 - ACPI_WRITE | (obj_desc->field.attribute << 16); 307 - } else if (obj_desc->field.region_obj->region.space_id == 308 - ACPI_ADR_SPACE_GSBUS) { 309 - accessor_type = obj_desc->field.attribute; 310 - length = 311 - acpi_ex_get_serial_access_length(accessor_type, 312 - obj_desc->field. 313 - access_length); 314 - 315 - /* 316 - * Buffer format for Generic Serial Bus protocols: 317 - * Status; (Byte 0 of the data buffer) 318 - * Length; (Byte 1 of the data buffer) 319 - * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 320 - */ 321 - data_length = source_desc->buffer.pointer[1]; /* Data length is 2nd byte */ 322 - if (!data_length) { 323 - ACPI_ERROR((AE_INFO, 324 - "Invalid zero data length in transfer buffer")); 325 - 326 - return_ACPI_STATUS(AE_AML_BUFFER_LENGTH); 327 - } 328 - 329 - function = ACPI_WRITE | (accessor_type << 16); 330 - } else { /* IPMI */ 331 - 332 - length = ACPI_IPMI_BUFFER_SIZE; 333 - data_length = length; 334 - function = ACPI_WRITE; 335 - } 336 - 337 - if (source_desc->buffer.length < data_length) { 338 - ACPI_ERROR((AE_INFO, 339 - "SMBus/IPMI/GenericSerialBus write requires " 340 - "Buffer data length %u, found buffer length %u", 341 - data_length, source_desc->buffer.length)); 342 - 343 - return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); 344 - } 345 - 346 - /* Create the transfer/bidirectional buffer */ 347 - 348 - buffer_desc = acpi_ut_create_buffer_object(length); 349 - if (!buffer_desc) { 350 - return_ACPI_STATUS(AE_NO_MEMORY); 351 - } 352 - 353 - /* Copy the input buffer data to the transfer buffer */ 354 - 355 - buffer = buffer_desc->buffer.pointer; 356 - memcpy(buffer, source_desc->buffer.pointer, data_length); 357 - 358 - /* Lock entire transaction if requested */ 359 - 360 - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); 361 - 362 - /* 363 - * Perform the write (returns status and perhaps data in the 364 - * same buffer) 365 - */ 366 - status = 367 - acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function); 368 - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 369 - 370 - *result_desc = buffer_desc; 371 - return_ACPI_STATUS(status); 372 - } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && 373 - (obj_desc->field.region_obj->region.space_id == 374 - ACPI_ADR_SPACE_GPIO)) { 375 - /* 376 - * For GPIO (general_purpose_io), we will bypass the entire field 377 - * mechanism and handoff the bit address and bit width directly to 378 - * the handler. The Address will be the bit offset 379 - * from the previous Connection() operator, making it effectively a 380 - * pin number index. The bit_length is the length of the field, which 381 - * is thus the number of pins. 382 - */ 383 - if (source_desc->common.type != ACPI_TYPE_INTEGER) { 384 - return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 385 - } 386 - 387 - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 388 - "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", 389 - acpi_ut_get_type_name(source_desc->common. 390 - type), 391 - source_desc->common.type, 392 - (u32)source_desc->integer.value, 393 - obj_desc->field.pin_number_index, 394 - obj_desc->field.bit_length)); 395 - 396 - buffer = &source_desc->integer.value; 397 - 398 - /* Lock entire transaction if requested */ 399 - 400 - acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); 401 - 402 - /* Perform the write */ 364 + /* SMBus, GSBus, IPMI serial */ 403 365 404 366 status = 405 - acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, 406 - ACPI_WRITE); 407 - acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 367 + acpi_ex_write_serial_bus(source_desc, obj_desc, 368 + result_desc); 408 369 return_ACPI_STATUS(status); 409 370 } 410 371 ··· 299 490 case ACPI_TYPE_INTEGER: 300 491 301 492 buffer = &source_desc->integer.value; 302 - length = sizeof(source_desc->integer.value); 493 + buffer_length = sizeof(source_desc->integer.value); 303 494 break; 304 495 305 496 case ACPI_TYPE_BUFFER: 306 497 307 498 buffer = source_desc->buffer.pointer; 308 - length = source_desc->buffer.length; 499 + buffer_length = source_desc->buffer.length; 309 500 break; 310 501 311 502 case ACPI_TYPE_STRING: 312 503 313 504 buffer = source_desc->string.pointer; 314 - length = source_desc->string.length; 505 + buffer_length = source_desc->string.length; 315 506 break; 316 507 317 508 default: 318 - 319 509 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 320 510 } 321 511 ··· 322 514 "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", 323 515 source_desc, 324 516 acpi_ut_get_type_name(source_desc->common.type), 325 - source_desc->common.type, buffer, length)); 517 + source_desc->common.type, buffer, buffer_length)); 326 518 327 519 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 328 520 "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", ··· 339 531 340 532 /* Write to the field */ 341 533 342 - status = acpi_ex_insert_into_field(obj_desc, buffer, length); 534 + status = acpi_ex_insert_into_field(obj_desc, buffer, buffer_length); 535 + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 536 + return_ACPI_STATUS(status); 537 + } 538 + 539 + /******************************************************************************* 540 + * 541 + * FUNCTION: acpi_ex_read_gpio 542 + * 543 + * PARAMETERS: obj_desc - The named field to read 544 + * buffer - Where the return data is returnd 545 + * 546 + * RETURN: Status 547 + * 548 + * DESCRIPTION: Read from a named field that references a Generic Serial Bus 549 + * field 550 + * 551 + ******************************************************************************/ 552 + 553 + static acpi_status 554 + acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer) 555 + { 556 + acpi_status status; 557 + 558 + ACPI_FUNCTION_TRACE_PTR(ex_read_gpio, obj_desc); 559 + 560 + /* 561 + * For GPIO (general_purpose_io), the Address will be the bit offset 562 + * from the previous Connection() operator, making it effectively a 563 + * pin number index. The bit_length is the length of the field, which 564 + * is thus the number of pins. 565 + */ 566 + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 567 + "GPIO FieldRead [FROM]: Pin %u Bits %u\n", 568 + obj_desc->field.pin_number_index, 569 + obj_desc->field.bit_length)); 570 + 571 + /* Lock entire transaction if requested */ 572 + 573 + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); 574 + 575 + /* Perform the read */ 576 + 577 + status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_READ); 578 + 579 + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 580 + return_ACPI_STATUS(status); 581 + } 582 + 583 + /******************************************************************************* 584 + * 585 + * FUNCTION: acpi_ex_write_gpio 586 + * 587 + * PARAMETERS: source_desc - Contains data to write. Expect to be 588 + * an Integer object. 589 + * obj_desc - The named field 590 + * result_desc - Where the return value is returned, if any 591 + * 592 + * RETURN: Status 593 + * 594 + * DESCRIPTION: Write to a named field that references a General Purpose I/O 595 + * field. 596 + * 597 + ******************************************************************************/ 598 + 599 + static acpi_status 600 + acpi_ex_write_gpio(union acpi_operand_object *source_desc, 601 + union acpi_operand_object *obj_desc, 602 + union acpi_operand_object **return_buffer) 603 + { 604 + acpi_status status; 605 + void *buffer; 606 + 607 + ACPI_FUNCTION_TRACE_PTR(ex_write_gpio, obj_desc); 608 + 609 + /* 610 + * For GPIO (general_purpose_io), we will bypass the entire field 611 + * mechanism and handoff the bit address and bit width directly to 612 + * the handler. The Address will be the bit offset 613 + * from the previous Connection() operator, making it effectively a 614 + * pin number index. The bit_length is the length of the field, which 615 + * is thus the number of pins. 616 + */ 617 + if (source_desc->common.type != ACPI_TYPE_INTEGER) { 618 + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 619 + } 620 + 621 + ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 622 + "GPIO FieldWrite [FROM]: (%s:%X), Value %.8X [TO]: Pin %u Bits %u\n", 623 + acpi_ut_get_type_name(source_desc->common.type), 624 + source_desc->common.type, 625 + (u32)source_desc->integer.value, 626 + obj_desc->field.pin_number_index, 627 + obj_desc->field.bit_length)); 628 + 629 + buffer = &source_desc->integer.value; 630 + 631 + /* Lock entire transaction if requested */ 632 + 633 + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); 634 + 635 + /* Perform the write */ 636 + 637 + status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_WRITE); 638 + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 639 + return_ACPI_STATUS(status); 640 + } 641 + 642 + /******************************************************************************* 643 + * 644 + * FUNCTION: acpi_ex_read_serial_bus 645 + * 646 + * PARAMETERS: obj_desc - The named field to read 647 + * return_buffer - Where the return value is returned, if any 648 + * 649 + * RETURN: Status 650 + * 651 + * DESCRIPTION: Read from a named field that references a serial bus 652 + * (SMBus, IPMI, or GSBus). 653 + * 654 + ******************************************************************************/ 655 + 656 + static acpi_status 657 + acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc, 658 + union acpi_operand_object **return_buffer) 659 + { 660 + acpi_status status; 661 + u32 buffer_length; 662 + union acpi_operand_object *buffer_desc; 663 + u32 function; 664 + u16 accessor_type; 665 + 666 + ACPI_FUNCTION_TRACE_PTR(ex_read_serial_bus, obj_desc); 667 + 668 + /* 669 + * This is an SMBus, GSBus or IPMI read. We must create a buffer to 670 + * hold the data and then directly access the region handler. 671 + * 672 + * Note: SMBus and GSBus protocol value is passed in upper 16-bits 673 + * of Function 674 + * 675 + * Common buffer format: 676 + * Status; (Byte 0 of the data buffer) 677 + * Length; (Byte 1 of the data buffer) 678 + * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 679 + */ 680 + switch (obj_desc->field.region_obj->region.space_id) { 681 + case ACPI_ADR_SPACE_SMBUS: 682 + 683 + buffer_length = ACPI_SMBUS_BUFFER_SIZE; 684 + function = ACPI_READ | (obj_desc->field.attribute << 16); 685 + break; 686 + 687 + case ACPI_ADR_SPACE_IPMI: 688 + 689 + buffer_length = ACPI_IPMI_BUFFER_SIZE; 690 + function = ACPI_READ; 691 + break; 692 + 693 + case ACPI_ADR_SPACE_GSBUS: 694 + 695 + accessor_type = obj_desc->field.attribute; 696 + if (accessor_type == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES) { 697 + ACPI_ERROR((AE_INFO, 698 + "Invalid direct read using bidirectional write-then-read protocol")); 699 + 700 + return_ACPI_STATUS(AE_AML_PROTOCOL); 701 + } 702 + 703 + status = 704 + acpi_ex_get_protocol_buffer_length(accessor_type, 705 + &buffer_length); 706 + if (ACPI_FAILURE(status)) { 707 + ACPI_ERROR((AE_INFO, 708 + "Invalid protocol ID for GSBus: 0x%4.4X", 709 + accessor_type)); 710 + 711 + return_ACPI_STATUS(status); 712 + } 713 + 714 + /* Add header length to get the full size of the buffer */ 715 + 716 + buffer_length += ACPI_SERIAL_HEADER_SIZE; 717 + function = ACPI_READ | (accessor_type << 16); 718 + break; 719 + 720 + default: 721 + return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); 722 + } 723 + 724 + /* Create the local transfer buffer that is returned to the caller */ 725 + 726 + buffer_desc = acpi_ut_create_buffer_object(buffer_length); 727 + if (!buffer_desc) { 728 + return_ACPI_STATUS(AE_NO_MEMORY); 729 + } 730 + 731 + /* Lock entire transaction if requested */ 732 + 733 + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); 734 + 735 + /* Call the region handler for the write-then-read */ 736 + 737 + status = acpi_ex_access_region(obj_desc, 0, 738 + ACPI_CAST_PTR(u64, 739 + buffer_desc->buffer. 740 + pointer), function); 343 741 acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 344 742 743 + *return_buffer = buffer_desc; 744 + return_ACPI_STATUS(status); 745 + } 746 + 747 + /******************************************************************************* 748 + * 749 + * FUNCTION: acpi_ex_write_serial_bus 750 + * 751 + * PARAMETERS: source_desc - Contains data to write 752 + * obj_desc - The named field 753 + * return_buffer - Where the return value is returned, if any 754 + * 755 + * RETURN: Status 756 + * 757 + * DESCRIPTION: Write to a named field that references a serial bus 758 + * (SMBus, IPMI, GSBus). 759 + * 760 + ******************************************************************************/ 761 + 762 + static acpi_status 763 + acpi_ex_write_serial_bus(union acpi_operand_object *source_desc, 764 + union acpi_operand_object *obj_desc, 765 + union acpi_operand_object **return_buffer) 766 + { 767 + acpi_status status; 768 + u32 buffer_length; 769 + u32 data_length; 770 + void *buffer; 771 + union acpi_operand_object *buffer_desc; 772 + u32 function; 773 + u16 accessor_type; 774 + 775 + ACPI_FUNCTION_TRACE_PTR(ex_write_serial_bus, obj_desc); 776 + 777 + /* 778 + * This is an SMBus, GSBus or IPMI write. We will bypass the entire 779 + * field mechanism and handoff the buffer directly to the handler. 780 + * For these address spaces, the buffer is bidirectional; on a 781 + * write, return data is returned in the same buffer. 782 + * 783 + * Source must be a buffer of sufficient size, these are fixed size: 784 + * ACPI_SMBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE. 785 + * 786 + * Note: SMBus and GSBus protocol type is passed in upper 16-bits 787 + * of Function 788 + * 789 + * Common buffer format: 790 + * Status; (Byte 0 of the data buffer) 791 + * Length; (Byte 1 of the data buffer) 792 + * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) 793 + */ 794 + if (source_desc->common.type != ACPI_TYPE_BUFFER) { 795 + ACPI_ERROR((AE_INFO, 796 + "SMBus/IPMI/GenericSerialBus write requires " 797 + "Buffer, found type %s", 798 + acpi_ut_get_object_type_name(source_desc))); 799 + 800 + return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 801 + } 802 + 803 + switch (obj_desc->field.region_obj->region.space_id) { 804 + case ACPI_ADR_SPACE_SMBUS: 805 + 806 + buffer_length = ACPI_SMBUS_BUFFER_SIZE; 807 + data_length = ACPI_SMBUS_DATA_SIZE; 808 + function = ACPI_WRITE | (obj_desc->field.attribute << 16); 809 + break; 810 + 811 + case ACPI_ADR_SPACE_IPMI: 812 + 813 + buffer_length = ACPI_IPMI_BUFFER_SIZE; 814 + data_length = ACPI_IPMI_DATA_SIZE; 815 + function = ACPI_WRITE; 816 + break; 817 + 818 + case ACPI_ADR_SPACE_GSBUS: 819 + 820 + accessor_type = obj_desc->field.attribute; 821 + status = 822 + acpi_ex_get_protocol_buffer_length(accessor_type, 823 + &buffer_length); 824 + if (ACPI_FAILURE(status)) { 825 + ACPI_ERROR((AE_INFO, 826 + "Invalid protocol ID for GSBus: 0x%4.4X", 827 + accessor_type)); 828 + 829 + return_ACPI_STATUS(status); 830 + } 831 + 832 + /* Add header length to get the full size of the buffer */ 833 + 834 + buffer_length += ACPI_SERIAL_HEADER_SIZE; 835 + data_length = source_desc->buffer.pointer[1]; 836 + function = ACPI_WRITE | (accessor_type << 16); 837 + break; 838 + 839 + default: 840 + return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); 841 + } 842 + 843 + #if 0 844 + OBSOLETE ? 845 + /* Check for possible buffer overflow */ 846 + if (data_length > source_desc->buffer.length) { 847 + ACPI_ERROR((AE_INFO, 848 + "Length in buffer header (%u)(%u) is greater than " 849 + "the physical buffer length (%u) and will overflow", 850 + data_length, buffer_length, 851 + source_desc->buffer.length)); 852 + 853 + return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); 854 + } 855 + #endif 856 + 857 + /* Create the transfer/bidirectional/return buffer */ 858 + 859 + buffer_desc = acpi_ut_create_buffer_object(buffer_length); 860 + if (!buffer_desc) { 861 + return_ACPI_STATUS(AE_NO_MEMORY); 862 + } 863 + 864 + /* Copy the input buffer data to the transfer buffer */ 865 + 866 + buffer = buffer_desc->buffer.pointer; 867 + memcpy(buffer, source_desc->buffer.pointer, data_length); 868 + 869 + /* Lock entire transaction if requested */ 870 + 871 + acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); 872 + 873 + /* 874 + * Perform the write (returns status and perhaps data in the 875 + * same buffer) 876 + */ 877 + status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function); 878 + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); 879 + 880 + *return_buffer = buffer_desc; 345 881 return_ACPI_STATUS(status); 346 882 }
+13 -5
include/acpi/acconfig.h
··· 173 173 #define ACPI_RSDP_CHECKSUM_LENGTH 20 174 174 #define ACPI_RSDP_XCHECKSUM_LENGTH 36 175 175 176 - /* SMBus, GSBus and IPMI bidirectional buffer size */ 176 + /* 177 + * SMBus, GSBus and IPMI buffer sizes. All have a 2-byte header, 178 + * containing both Status and Length. 179 + */ 180 + #define ACPI_SERIAL_HEADER_SIZE 2 /* Common for below. Status and Length fields */ 177 181 178 - #define ACPI_SMBUS_BUFFER_SIZE 34 179 - #define ACPI_IPMI_BUFFER_SIZE 66 180 - #define ACPI_GSBUS_BUFFER_SIZE 34 /* Not clear if this is needed */ 181 - #define ACPI_MAX_GSBUS_BUFFER_SIZE 255 /* Worst-case bidirectional buffer */ 182 + #define ACPI_SMBUS_DATA_SIZE 32 183 + #define ACPI_SMBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_SMBUS_DATA_SIZE 184 + 185 + #define ACPI_IPMI_DATA_SIZE 64 186 + #define ACPI_IPMI_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_IPMI_DATA_SIZE 187 + 188 + #define ACPI_MAX_GSBUS_DATA_SIZE 255 189 + #define ACPI_MAX_GSBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_MAX_GSBUS_DATA_SIZE 182 190 183 191 /* _sx_d and _sx_w control methods */ 184 192