forked from Minki/linux
Merge branch 'acpica'
* acpica: ACPICA: Remove acpi_gbl_group_module_level_code and only use acpi_gbl_execute_tables_as_methods instead ACPICA: AML Parser: fix parse loop to correctly skip erroneous extended opcodes ACPICA: AML interpreter: add region addresses in global list during initialization ACPICA: Update version to 20181003 ACPICA: Never run _REG on system_memory and system_IO ACPICA: Split large interpreter file ACPICA: Update for field unit access ACPICA: Rename some of the Field Attribute defines ACPICA: Update for generic_serial_bus and attrib_raw_process_bytes protocol
This commit is contained in:
commit
3c88a889b4
@ -65,6 +65,7 @@ acpi-y += \
|
|||||||
exresnte.o \
|
exresnte.o \
|
||||||
exresolv.o \
|
exresolv.o \
|
||||||
exresop.o \
|
exresop.o \
|
||||||
|
exserial.o \
|
||||||
exstore.o \
|
exstore.o \
|
||||||
exstoren.o \
|
exstoren.o \
|
||||||
exstorob.o \
|
exstorob.o \
|
||||||
|
@ -229,6 +229,8 @@ acpi_ev_default_region_setup(acpi_handle handle,
|
|||||||
|
|
||||||
acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj);
|
acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj);
|
||||||
|
|
||||||
|
u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* evsci - SCI (System Control Interrupt) handling/dispatch
|
* evsci - SCI (System Control Interrupt) handling/dispatch
|
||||||
*/
|
*/
|
||||||
|
@ -123,6 +123,9 @@ acpi_ex_trace_point(acpi_trace_event_type type,
|
|||||||
/*
|
/*
|
||||||
* exfield - ACPI AML (p-code) execution - field manipulation
|
* exfield - ACPI AML (p-code) execution - field manipulation
|
||||||
*/
|
*/
|
||||||
|
acpi_status
|
||||||
|
acpi_ex_get_protocol_buffer_length(u32 protocol_id, u32 *return_length);
|
||||||
|
|
||||||
acpi_status
|
acpi_status
|
||||||
acpi_ex_common_buffer_setup(union acpi_operand_object *obj_desc,
|
acpi_ex_common_buffer_setup(union acpi_operand_object *obj_desc,
|
||||||
u32 buffer_length, u32 * datum_count);
|
u32 buffer_length, u32 * datum_count);
|
||||||
@ -267,6 +270,26 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
|
|||||||
|
|
||||||
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info);
|
acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exserial - field_unit support for serial address spaces
|
||||||
|
*/
|
||||||
|
acpi_status
|
||||||
|
acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc,
|
||||||
|
union acpi_operand_object **return_buffer);
|
||||||
|
|
||||||
|
acpi_status
|
||||||
|
acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
|
||||||
|
union acpi_operand_object *obj_desc,
|
||||||
|
union acpi_operand_object **return_buffer);
|
||||||
|
|
||||||
|
acpi_status
|
||||||
|
acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer);
|
||||||
|
|
||||||
|
acpi_status
|
||||||
|
acpi_ex_write_gpio(union acpi_operand_object *source_desc,
|
||||||
|
union acpi_operand_object *obj_desc,
|
||||||
|
union acpi_operand_object **return_buffer);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* exsystem - Interface to OS services
|
* exsystem - Interface to OS services
|
||||||
*/
|
*/
|
||||||
|
@ -395,9 +395,9 @@ struct acpi_simple_repair_info {
|
|||||||
/* Info for running the _REG methods */
|
/* Info for running the _REG methods */
|
||||||
|
|
||||||
struct acpi_reg_walk_info {
|
struct acpi_reg_walk_info {
|
||||||
acpi_adr_space_type space_id;
|
|
||||||
u32 function;
|
u32 function;
|
||||||
u32 reg_run_count;
|
u32 reg_run_count;
|
||||||
|
acpi_adr_space_type space_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -432,15 +432,15 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AML_FIELD_ATTRIB_QUICK = 0x02,
|
AML_FIELD_ATTRIB_QUICK = 0x02,
|
||||||
AML_FIELD_ATTRIB_SEND_RCV = 0x04,
|
AML_FIELD_ATTRIB_SEND_RECEIVE = 0x04,
|
||||||
AML_FIELD_ATTRIB_BYTE = 0x06,
|
AML_FIELD_ATTRIB_BYTE = 0x06,
|
||||||
AML_FIELD_ATTRIB_WORD = 0x08,
|
AML_FIELD_ATTRIB_WORD = 0x08,
|
||||||
AML_FIELD_ATTRIB_BLOCK = 0x0A,
|
AML_FIELD_ATTRIB_BLOCK = 0x0A,
|
||||||
AML_FIELD_ATTRIB_MULTIBYTE = 0x0B,
|
AML_FIELD_ATTRIB_BYTES = 0x0B,
|
||||||
AML_FIELD_ATTRIB_WORD_CALL = 0x0C,
|
AML_FIELD_ATTRIB_PROCESS_CALL = 0x0C,
|
||||||
AML_FIELD_ATTRIB_BLOCK_CALL = 0x0D,
|
AML_FIELD_ATTRIB_BLOCK_PROCESS_CALL = 0x0D,
|
||||||
AML_FIELD_ATTRIB_RAW_BYTES = 0x0E,
|
AML_FIELD_ATTRIB_RAW_BYTES = 0x0E,
|
||||||
AML_FIELD_ATTRIB_RAW_PROCESS = 0x0F
|
AML_FIELD_ATTRIB_RAW_PROCESS_BYTES = 0x0F
|
||||||
} AML_ACCESS_ATTRIBUTE;
|
} AML_ACCESS_ATTRIBUTE;
|
||||||
|
|
||||||
/* Bit fields in the AML method_flags byte */
|
/* Bit fields in the AML method_flags byte */
|
||||||
|
@ -417,6 +417,10 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
|
|||||||
ACPI_FORMAT_UINT64(obj_desc->region.address),
|
ACPI_FORMAT_UINT64(obj_desc->region.address),
|
||||||
obj_desc->region.length));
|
obj_desc->region.length));
|
||||||
|
|
||||||
|
status = acpi_ut_add_address_range(obj_desc->region.space_id,
|
||||||
|
obj_desc->region.address,
|
||||||
|
obj_desc->region.length, node);
|
||||||
|
|
||||||
/* Now the address and length are valid for this opregion */
|
/* Now the address and length are valid for this opregion */
|
||||||
|
|
||||||
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
|
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
|
||||||
|
@ -653,6 +653,19 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
|
|||||||
|
|
||||||
ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
|
ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These address spaces do not need a call to _REG, since the ACPI
|
||||||
|
* specification defines them as: "must always be accessible". Since
|
||||||
|
* they never change state (never become unavailable), no need to ever
|
||||||
|
* call _REG on them. Also, a data_table is not a "real" address space,
|
||||||
|
* so do not call _REG. September 2018.
|
||||||
|
*/
|
||||||
|
if ((space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
|
||||||
|
(space_id == ACPI_ADR_SPACE_SYSTEM_IO) ||
|
||||||
|
(space_id == ACPI_ADR_SPACE_DATA_TABLE)) {
|
||||||
|
return_VOID;
|
||||||
|
}
|
||||||
|
|
||||||
info.space_id = space_id;
|
info.space_id = space_id;
|
||||||
info.function = function;
|
info.function = function;
|
||||||
info.reg_run_count = 0;
|
info.reg_run_count = 0;
|
||||||
@ -714,8 +727,8 @@ acpi_ev_reg_run(acpi_handle obj_handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We only care about regions.and objects that are allowed to have address
|
* We only care about regions and objects that are allowed to have
|
||||||
* space handlers
|
* address space handlers
|
||||||
*/
|
*/
|
||||||
if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
|
if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
|
||||||
return (AE_OK);
|
return (AE_OK);
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
#define _COMPONENT ACPI_EVENTS
|
#define _COMPONENT ACPI_EVENTS
|
||||||
ACPI_MODULE_NAME("evrgnini")
|
ACPI_MODULE_NAME("evrgnini")
|
||||||
|
|
||||||
/* Local prototypes */
|
|
||||||
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node);
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* FUNCTION: acpi_ev_system_memory_region_setup
|
* FUNCTION: acpi_ev_system_memory_region_setup
|
||||||
@ -33,7 +30,6 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node);
|
|||||||
* DESCRIPTION: Setup a system_memory operation region
|
* DESCRIPTION: Setup a system_memory operation region
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
acpi_status
|
acpi_status
|
||||||
acpi_ev_system_memory_region_setup(acpi_handle handle,
|
acpi_ev_system_memory_region_setup(acpi_handle handle,
|
||||||
u32 function,
|
u32 function,
|
||||||
@ -313,7 +309,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
|
|||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
|
u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
|
||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
struct acpi_pnp_device_id *hid;
|
struct acpi_pnp_device_id *hid;
|
||||||
|
@ -193,7 +193,6 @@ acpi_remove_address_space_handler(acpi_handle device,
|
|||||||
*/
|
*/
|
||||||
region_obj =
|
region_obj =
|
||||||
handler_obj->address_space.region_list;
|
handler_obj->address_space.region_list;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove this Handler object from the list */
|
/* Remove this Handler object from the list */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* Module Name: exfield - ACPI AML (p-code) execution - field manipulation
|
* Module Name: exfield - AML execution - field_unit read/write
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||||
*
|
*
|
||||||
@ -16,64 +16,62 @@
|
|||||||
#define _COMPONENT ACPI_EXECUTER
|
#define _COMPONENT ACPI_EXECUTER
|
||||||
ACPI_MODULE_NAME("exfield")
|
ACPI_MODULE_NAME("exfield")
|
||||||
|
|
||||||
/* Local prototypes */
|
/*
|
||||||
static u32
|
* This table maps the various Attrib protocols to the byte transfer
|
||||||
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);
|
* length. Used for the generic serial bus.
|
||||||
|
*/
|
||||||
|
#define ACPI_INVALID_PROTOCOL_ID 0x80
|
||||||
|
#define ACPI_MAX_PROTOCOL_ID 0x0F
|
||||||
|
const u8 acpi_protocol_lengths[] = {
|
||||||
|
ACPI_INVALID_PROTOCOL_ID, /* 0 - reserved */
|
||||||
|
ACPI_INVALID_PROTOCOL_ID, /* 1 - reserved */
|
||||||
|
0x00, /* 2 - ATTRIB_QUICK */
|
||||||
|
ACPI_INVALID_PROTOCOL_ID, /* 3 - reserved */
|
||||||
|
0x01, /* 4 - ATTRIB_SEND_RECEIVE */
|
||||||
|
ACPI_INVALID_PROTOCOL_ID, /* 5 - reserved */
|
||||||
|
0x01, /* 6 - ATTRIB_BYTE */
|
||||||
|
ACPI_INVALID_PROTOCOL_ID, /* 7 - reserved */
|
||||||
|
0x02, /* 8 - ATTRIB_WORD */
|
||||||
|
ACPI_INVALID_PROTOCOL_ID, /* 9 - reserved */
|
||||||
|
0xFF, /* A - ATTRIB_BLOCK */
|
||||||
|
0xFF, /* B - ATTRIB_BYTES */
|
||||||
|
0x02, /* C - ATTRIB_PROCESS_CALL */
|
||||||
|
0xFF, /* D - ATTRIB_BLOCK_PROCESS_CALL */
|
||||||
|
0xFF, /* E - ATTRIB_RAW_BYTES */
|
||||||
|
0xFF /* F - ATTRIB_RAW_PROCESS_BYTES */
|
||||||
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* FUNCTION: acpi_ex_get_serial_access_length
|
* FUNCTION: acpi_ex_get_protocol_buffer_length
|
||||||
*
|
*
|
||||||
* PARAMETERS: accessor_type - The type of the protocol indicated by region
|
* PARAMETERS: protocol_id - The type of the protocol indicated by region
|
||||||
* field access attributes
|
* field access attributes
|
||||||
* access_length - The access length of the region field
|
* return_length - Where the protocol byte transfer length is
|
||||||
|
* returned
|
||||||
*
|
*
|
||||||
* RETURN: Decoded access length
|
* RETURN: Status and decoded byte transfer length
|
||||||
*
|
*
|
||||||
* DESCRIPTION: This routine returns the length of the generic_serial_bus
|
* DESCRIPTION: This routine returns the length of the generic_serial_bus
|
||||||
* protocol bytes
|
* protocol bytes
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
static u32
|
acpi_status
|
||||||
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
|
acpi_ex_get_protocol_buffer_length(u32 protocol_id, u32 *return_length)
|
||||||
{
|
{
|
||||||
u32 length;
|
|
||||||
|
|
||||||
switch (accessor_type) {
|
if ((protocol_id > ACPI_MAX_PROTOCOL_ID) ||
|
||||||
case AML_FIELD_ATTRIB_QUICK:
|
(acpi_protocol_lengths[protocol_id] == ACPI_INVALID_PROTOCOL_ID)) {
|
||||||
|
ACPI_ERROR((AE_INFO,
|
||||||
|
"Invalid Field/AccessAs protocol ID: 0x%4.4X",
|
||||||
|
protocol_id));
|
||||||
|
|
||||||
length = 0;
|
return (AE_AML_PROTOCOL);
|
||||||
break;
|
|
||||||
|
|
||||||
case AML_FIELD_ATTRIB_SEND_RCV:
|
|
||||||
case AML_FIELD_ATTRIB_BYTE:
|
|
||||||
|
|
||||||
length = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AML_FIELD_ATTRIB_WORD:
|
|
||||||
case AML_FIELD_ATTRIB_WORD_CALL:
|
|
||||||
|
|
||||||
length = 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AML_FIELD_ATTRIB_MULTIBYTE:
|
|
||||||
case AML_FIELD_ATTRIB_RAW_BYTES:
|
|
||||||
case AML_FIELD_ATTRIB_RAW_PROCESS:
|
|
||||||
|
|
||||||
length = access_length;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AML_FIELD_ATTRIB_BLOCK:
|
|
||||||
case AML_FIELD_ATTRIB_BLOCK_CALL:
|
|
||||||
default:
|
|
||||||
|
|
||||||
length = ACPI_GSBUS_BUFFER_SIZE - 2;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (length);
|
*return_length = acpi_protocol_lengths[protocol_id];
|
||||||
|
return (AE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -98,10 +96,8 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
|||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
union acpi_operand_object *buffer_desc;
|
union acpi_operand_object *buffer_desc;
|
||||||
acpi_size length;
|
|
||||||
void *buffer;
|
void *buffer;
|
||||||
u32 function;
|
u32 buffer_length;
|
||||||
u16 accessor_type;
|
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
|
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
|
||||||
|
|
||||||
@ -132,60 +128,11 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
|||||||
ACPI_ADR_SPACE_GSBUS
|
ACPI_ADR_SPACE_GSBUS
|
||||||
|| obj_desc->field.region_obj->region.space_id ==
|
|| obj_desc->field.region_obj->region.space_id ==
|
||||||
ACPI_ADR_SPACE_IPMI)) {
|
ACPI_ADR_SPACE_IPMI)) {
|
||||||
/*
|
|
||||||
* This is an SMBus, GSBus or IPMI read. We must create a buffer to
|
|
||||||
* hold the data and then directly access the region handler.
|
|
||||||
*
|
|
||||||
* Note: SMBus and GSBus protocol value is passed in upper 16-bits
|
|
||||||
* of Function
|
|
||||||
*/
|
|
||||||
if (obj_desc->field.region_obj->region.space_id ==
|
|
||||||
ACPI_ADR_SPACE_SMBUS) {
|
|
||||||
length = ACPI_SMBUS_BUFFER_SIZE;
|
|
||||||
function =
|
|
||||||
ACPI_READ | (obj_desc->field.attribute << 16);
|
|
||||||
} else if (obj_desc->field.region_obj->region.space_id ==
|
|
||||||
ACPI_ADR_SPACE_GSBUS) {
|
|
||||||
accessor_type = obj_desc->field.attribute;
|
|
||||||
length =
|
|
||||||
acpi_ex_get_serial_access_length(accessor_type,
|
|
||||||
obj_desc->field.
|
|
||||||
access_length);
|
|
||||||
|
|
||||||
/*
|
/* SMBus, GSBus, IPMI serial */
|
||||||
* Add additional 2 bytes for the generic_serial_bus data buffer:
|
|
||||||
*
|
|
||||||
* Status; (Byte 0 of the data buffer)
|
|
||||||
* Length; (Byte 1 of the data buffer)
|
|
||||||
* Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
|
|
||||||
*/
|
|
||||||
length += 2;
|
|
||||||
function = ACPI_READ | (accessor_type << 16);
|
|
||||||
} else { /* IPMI */
|
|
||||||
|
|
||||||
length = ACPI_IPMI_BUFFER_SIZE;
|
status = acpi_ex_read_serial_bus(obj_desc, ret_buffer_desc);
|
||||||
function = ACPI_READ;
|
return_ACPI_STATUS(status);
|
||||||
}
|
|
||||||
|
|
||||||
buffer_desc = acpi_ut_create_buffer_object(length);
|
|
||||||
if (!buffer_desc) {
|
|
||||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lock entire transaction if requested */
|
|
||||||
|
|
||||||
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
|
||||||
|
|
||||||
/* Call the region handler for the read */
|
|
||||||
|
|
||||||
status = acpi_ex_access_region(obj_desc, 0,
|
|
||||||
ACPI_CAST_PTR(u64,
|
|
||||||
buffer_desc->
|
|
||||||
buffer.pointer),
|
|
||||||
function);
|
|
||||||
|
|
||||||
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -198,14 +145,14 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
|||||||
*
|
*
|
||||||
* Note: Field.length is in bits.
|
* Note: Field.length is in bits.
|
||||||
*/
|
*/
|
||||||
length =
|
buffer_length =
|
||||||
(acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
|
(acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
|
||||||
|
|
||||||
if (length > acpi_gbl_integer_byte_width) {
|
if (buffer_length > acpi_gbl_integer_byte_width) {
|
||||||
|
|
||||||
/* Field is too large for an Integer, create a Buffer instead */
|
/* Field is too large for an Integer, create a Buffer instead */
|
||||||
|
|
||||||
buffer_desc = acpi_ut_create_buffer_object(length);
|
buffer_desc = acpi_ut_create_buffer_object(buffer_length);
|
||||||
if (!buffer_desc) {
|
if (!buffer_desc) {
|
||||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||||
}
|
}
|
||||||
@ -218,47 +165,24 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
|||||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
length = acpi_gbl_integer_byte_width;
|
buffer_length = acpi_gbl_integer_byte_width;
|
||||||
buffer = &buffer_desc->integer.value;
|
buffer = &buffer_desc->integer.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
||||||
(obj_desc->field.region_obj->region.space_id ==
|
(obj_desc->field.region_obj->region.space_id ==
|
||||||
ACPI_ADR_SPACE_GPIO)) {
|
ACPI_ADR_SPACE_GPIO)) {
|
||||||
/*
|
|
||||||
* For GPIO (general_purpose_io), the Address will be the bit offset
|
|
||||||
* from the previous Connection() operator, making it effectively a
|
|
||||||
* pin number index. The bit_length is the length of the field, which
|
|
||||||
* is thus the number of pins.
|
|
||||||
*/
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
|
||||||
"GPIO FieldRead [FROM]: Pin %u Bits %u\n",
|
|
||||||
obj_desc->field.pin_number_index,
|
|
||||||
obj_desc->field.bit_length));
|
|
||||||
|
|
||||||
/* Lock entire transaction if requested */
|
/* General Purpose I/O */
|
||||||
|
|
||||||
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
status = acpi_ex_read_gpio(obj_desc, buffer);
|
||||||
|
goto exit;
|
||||||
/* Perform the write */
|
|
||||||
|
|
||||||
status =
|
|
||||||
acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
|
|
||||||
ACPI_READ);
|
|
||||||
|
|
||||||
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
|
||||||
if (ACPI_FAILURE(status)) {
|
|
||||||
acpi_ut_remove_reference(buffer_desc);
|
|
||||||
} else {
|
|
||||||
*ret_buffer_desc = buffer_desc;
|
|
||||||
}
|
|
||||||
return_ACPI_STATUS(status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
||||||
"FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
|
"FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n",
|
||||||
obj_desc, obj_desc->common.type, buffer,
|
obj_desc, obj_desc->common.type, buffer,
|
||||||
(u32) length));
|
buffer_length));
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
||||||
"FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
|
"FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
|
||||||
obj_desc->common_field.bit_length,
|
obj_desc->common_field.bit_length,
|
||||||
@ -271,7 +195,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|
|||||||
|
|
||||||
/* Read from the field */
|
/* Read from the field */
|
||||||
|
|
||||||
status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
|
status = acpi_ex_extract_from_field(obj_desc, buffer, buffer_length);
|
||||||
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -304,11 +228,8 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
|||||||
union acpi_operand_object **result_desc)
|
union acpi_operand_object **result_desc)
|
||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
u32 length;
|
u32 buffer_length;
|
||||||
void *buffer;
|
void *buffer;
|
||||||
union acpi_operand_object *buffer_desc;
|
|
||||||
u32 function;
|
|
||||||
u16 accessor_type;
|
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
|
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
|
||||||
|
|
||||||
@ -329,6 +250,14 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
|||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
||||||
|
(obj_desc->field.region_obj->region.space_id ==
|
||||||
|
ACPI_ADR_SPACE_GPIO)) {
|
||||||
|
|
||||||
|
/* General Purpose I/O */
|
||||||
|
|
||||||
|
status = acpi_ex_write_gpio(source_desc, obj_desc, result_desc);
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
||||||
(obj_desc->field.region_obj->region.space_id ==
|
(obj_desc->field.region_obj->region.space_id ==
|
||||||
ACPI_ADR_SPACE_SMBUS
|
ACPI_ADR_SPACE_SMBUS
|
||||||
@ -336,125 +265,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
|||||||
ACPI_ADR_SPACE_GSBUS
|
ACPI_ADR_SPACE_GSBUS
|
||||||
|| obj_desc->field.region_obj->region.space_id ==
|
|| obj_desc->field.region_obj->region.space_id ==
|
||||||
ACPI_ADR_SPACE_IPMI)) {
|
ACPI_ADR_SPACE_IPMI)) {
|
||||||
/*
|
|
||||||
* This is an SMBus, GSBus or IPMI write. We will bypass the entire
|
|
||||||
* field mechanism and handoff the buffer directly to the handler.
|
|
||||||
* For these address spaces, the buffer is bi-directional; on a
|
|
||||||
* write, return data is returned in the same buffer.
|
|
||||||
*
|
|
||||||
* Source must be a buffer of sufficient size:
|
|
||||||
* ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or
|
|
||||||
* ACPI_IPMI_BUFFER_SIZE.
|
|
||||||
*
|
|
||||||
* Note: SMBus and GSBus protocol type is passed in upper 16-bits
|
|
||||||
* of Function
|
|
||||||
*/
|
|
||||||
if (source_desc->common.type != ACPI_TYPE_BUFFER) {
|
|
||||||
ACPI_ERROR((AE_INFO,
|
|
||||||
"SMBus/IPMI/GenericSerialBus write requires "
|
|
||||||
"Buffer, found type %s",
|
|
||||||
acpi_ut_get_object_type_name(source_desc)));
|
|
||||||
|
|
||||||
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
/* SMBus, GSBus, IPMI serial */
|
||||||
}
|
|
||||||
|
|
||||||
if (obj_desc->field.region_obj->region.space_id ==
|
|
||||||
ACPI_ADR_SPACE_SMBUS) {
|
|
||||||
length = ACPI_SMBUS_BUFFER_SIZE;
|
|
||||||
function =
|
|
||||||
ACPI_WRITE | (obj_desc->field.attribute << 16);
|
|
||||||
} else if (obj_desc->field.region_obj->region.space_id ==
|
|
||||||
ACPI_ADR_SPACE_GSBUS) {
|
|
||||||
accessor_type = obj_desc->field.attribute;
|
|
||||||
length =
|
|
||||||
acpi_ex_get_serial_access_length(accessor_type,
|
|
||||||
obj_desc->field.
|
|
||||||
access_length);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add additional 2 bytes for the generic_serial_bus data buffer:
|
|
||||||
*
|
|
||||||
* Status; (Byte 0 of the data buffer)
|
|
||||||
* Length; (Byte 1 of the data buffer)
|
|
||||||
* Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
|
|
||||||
*/
|
|
||||||
length += 2;
|
|
||||||
function = ACPI_WRITE | (accessor_type << 16);
|
|
||||||
} else { /* IPMI */
|
|
||||||
|
|
||||||
length = ACPI_IPMI_BUFFER_SIZE;
|
|
||||||
function = ACPI_WRITE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source_desc->buffer.length < length) {
|
|
||||||
ACPI_ERROR((AE_INFO,
|
|
||||||
"SMBus/IPMI/GenericSerialBus write requires "
|
|
||||||
"Buffer of length %u, found length %u",
|
|
||||||
length, source_desc->buffer.length));
|
|
||||||
|
|
||||||
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the bi-directional buffer */
|
|
||||||
|
|
||||||
buffer_desc = acpi_ut_create_buffer_object(length);
|
|
||||||
if (!buffer_desc) {
|
|
||||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = buffer_desc->buffer.pointer;
|
|
||||||
memcpy(buffer, source_desc->buffer.pointer, length);
|
|
||||||
|
|
||||||
/* Lock entire transaction if requested */
|
|
||||||
|
|
||||||
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Perform the write (returns status and perhaps data in the
|
|
||||||
* same buffer)
|
|
||||||
*/
|
|
||||||
status =
|
|
||||||
acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
|
|
||||||
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
|
||||||
|
|
||||||
*result_desc = buffer_desc;
|
|
||||||
return_ACPI_STATUS(status);
|
|
||||||
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
|
||||||
(obj_desc->field.region_obj->region.space_id ==
|
|
||||||
ACPI_ADR_SPACE_GPIO)) {
|
|
||||||
/*
|
|
||||||
* For GPIO (general_purpose_io), we will bypass the entire field
|
|
||||||
* mechanism and handoff the bit address and bit width directly to
|
|
||||||
* the handler. The Address will be the bit offset
|
|
||||||
* from the previous Connection() operator, making it effectively a
|
|
||||||
* pin number index. The bit_length is the length of the field, which
|
|
||||||
* is thus the number of pins.
|
|
||||||
*/
|
|
||||||
if (source_desc->common.type != ACPI_TYPE_INTEGER) {
|
|
||||||
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
|
||||||
"GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
|
|
||||||
acpi_ut_get_type_name(source_desc->common.
|
|
||||||
type),
|
|
||||||
source_desc->common.type,
|
|
||||||
(u32)source_desc->integer.value,
|
|
||||||
obj_desc->field.pin_number_index,
|
|
||||||
obj_desc->field.bit_length));
|
|
||||||
|
|
||||||
buffer = &source_desc->integer.value;
|
|
||||||
|
|
||||||
/* Lock entire transaction if requested */
|
|
||||||
|
|
||||||
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
|
||||||
|
|
||||||
/* Perform the write */
|
|
||||||
|
|
||||||
status =
|
status =
|
||||||
acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
|
acpi_ex_write_serial_bus(source_desc, obj_desc,
|
||||||
ACPI_WRITE);
|
result_desc);
|
||||||
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,23 +280,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
|||||||
case ACPI_TYPE_INTEGER:
|
case ACPI_TYPE_INTEGER:
|
||||||
|
|
||||||
buffer = &source_desc->integer.value;
|
buffer = &source_desc->integer.value;
|
||||||
length = sizeof(source_desc->integer.value);
|
buffer_length = sizeof(source_desc->integer.value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACPI_TYPE_BUFFER:
|
case ACPI_TYPE_BUFFER:
|
||||||
|
|
||||||
buffer = source_desc->buffer.pointer;
|
buffer = source_desc->buffer.pointer;
|
||||||
length = source_desc->buffer.length;
|
buffer_length = source_desc->buffer.length;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACPI_TYPE_STRING:
|
case ACPI_TYPE_STRING:
|
||||||
|
|
||||||
buffer = source_desc->string.pointer;
|
buffer = source_desc->string.pointer;
|
||||||
length = source_desc->string.length;
|
buffer_length = source_desc->string.length;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +303,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
|||||||
"FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
|
"FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
|
||||||
source_desc,
|
source_desc,
|
||||||
acpi_ut_get_type_name(source_desc->common.type),
|
acpi_ut_get_type_name(source_desc->common.type),
|
||||||
source_desc->common.type, buffer, length));
|
source_desc->common.type, buffer, buffer_length));
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
||||||
"FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
|
"FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
|
||||||
@ -505,8 +320,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|
|||||||
|
|
||||||
/* Write to the field */
|
/* Write to the field */
|
||||||
|
|
||||||
status = acpi_ex_insert_into_field(obj_desc, buffer, length);
|
status = acpi_ex_insert_into_field(obj_desc, buffer, buffer_length);
|
||||||
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
360
drivers/acpi/acpica/exserial.c
Normal file
360
drivers/acpi/acpica/exserial.c
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* Module Name: exserial - field_unit support for serial address spaces
|
||||||
|
*
|
||||||
|
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include <acpi/acpi.h>
|
||||||
|
#include "accommon.h"
|
||||||
|
#include "acdispat.h"
|
||||||
|
#include "acinterp.h"
|
||||||
|
#include "amlcode.h"
|
||||||
|
|
||||||
|
#define _COMPONENT ACPI_EXECUTER
|
||||||
|
ACPI_MODULE_NAME("exserial")
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ex_read_gpio
|
||||||
|
*
|
||||||
|
* PARAMETERS: obj_desc - The named field to read
|
||||||
|
* buffer - Where the return data is returnd
|
||||||
|
*
|
||||||
|
* RETURN: Status
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Read from a named field that references a Generic Serial Bus
|
||||||
|
* field
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
acpi_status acpi_ex_read_gpio(union acpi_operand_object *obj_desc, void *buffer)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
ACPI_FUNCTION_TRACE_PTR(ex_read_gpio, obj_desc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For GPIO (general_purpose_io), the Address will be the bit offset
|
||||||
|
* from the previous Connection() operator, making it effectively a
|
||||||
|
* pin number index. The bit_length is the length of the field, which
|
||||||
|
* is thus the number of pins.
|
||||||
|
*/
|
||||||
|
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
||||||
|
"GPIO FieldRead [FROM]: Pin %u Bits %u\n",
|
||||||
|
obj_desc->field.pin_number_index,
|
||||||
|
obj_desc->field.bit_length));
|
||||||
|
|
||||||
|
/* Lock entire transaction if requested */
|
||||||
|
|
||||||
|
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
|
/* Perform the read */
|
||||||
|
|
||||||
|
status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_READ);
|
||||||
|
|
||||||
|
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ex_write_gpio
|
||||||
|
*
|
||||||
|
* PARAMETERS: source_desc - Contains data to write. Expect to be
|
||||||
|
* an Integer object.
|
||||||
|
* obj_desc - The named field
|
||||||
|
* result_desc - Where the return value is returned, if any
|
||||||
|
*
|
||||||
|
* RETURN: Status
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Write to a named field that references a General Purpose I/O
|
||||||
|
* field.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
acpi_status
|
||||||
|
acpi_ex_write_gpio(union acpi_operand_object *source_desc,
|
||||||
|
union acpi_operand_object *obj_desc,
|
||||||
|
union acpi_operand_object **return_buffer)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
void *buffer;
|
||||||
|
|
||||||
|
ACPI_FUNCTION_TRACE_PTR(ex_write_gpio, obj_desc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For GPIO (general_purpose_io), we will bypass the entire field
|
||||||
|
* mechanism and handoff the bit address and bit width directly to
|
||||||
|
* the handler. The Address will be the bit offset
|
||||||
|
* from the previous Connection() operator, making it effectively a
|
||||||
|
* pin number index. The bit_length is the length of the field, which
|
||||||
|
* is thus the number of pins.
|
||||||
|
*/
|
||||||
|
if (source_desc->common.type != ACPI_TYPE_INTEGER) {
|
||||||
|
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
|
||||||
|
"GPIO FieldWrite [FROM]: (%s:%X), Value %.8X [TO]: Pin %u Bits %u\n",
|
||||||
|
acpi_ut_get_type_name(source_desc->common.type),
|
||||||
|
source_desc->common.type,
|
||||||
|
(u32)source_desc->integer.value,
|
||||||
|
obj_desc->field.pin_number_index,
|
||||||
|
obj_desc->field.bit_length));
|
||||||
|
|
||||||
|
buffer = &source_desc->integer.value;
|
||||||
|
|
||||||
|
/* Lock entire transaction if requested */
|
||||||
|
|
||||||
|
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
|
/* Perform the write */
|
||||||
|
|
||||||
|
status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_WRITE);
|
||||||
|
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ex_read_serial_bus
|
||||||
|
*
|
||||||
|
* PARAMETERS: obj_desc - The named field to read
|
||||||
|
* return_buffer - Where the return value is returned, if any
|
||||||
|
*
|
||||||
|
* RETURN: Status
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Read from a named field that references a serial bus
|
||||||
|
* (SMBus, IPMI, or GSBus).
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
acpi_status
|
||||||
|
acpi_ex_read_serial_bus(union acpi_operand_object *obj_desc,
|
||||||
|
union acpi_operand_object **return_buffer)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
u32 buffer_length;
|
||||||
|
union acpi_operand_object *buffer_desc;
|
||||||
|
u32 function;
|
||||||
|
u16 accessor_type;
|
||||||
|
|
||||||
|
ACPI_FUNCTION_TRACE_PTR(ex_read_serial_bus, obj_desc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an SMBus, GSBus or IPMI read. We must create a buffer to
|
||||||
|
* hold the data and then directly access the region handler.
|
||||||
|
*
|
||||||
|
* Note: SMBus and GSBus protocol value is passed in upper 16-bits
|
||||||
|
* of Function
|
||||||
|
*
|
||||||
|
* Common buffer format:
|
||||||
|
* Status; (Byte 0 of the data buffer)
|
||||||
|
* Length; (Byte 1 of the data buffer)
|
||||||
|
* Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
|
||||||
|
*/
|
||||||
|
switch (obj_desc->field.region_obj->region.space_id) {
|
||||||
|
case ACPI_ADR_SPACE_SMBUS:
|
||||||
|
|
||||||
|
buffer_length = ACPI_SMBUS_BUFFER_SIZE;
|
||||||
|
function = ACPI_READ | (obj_desc->field.attribute << 16);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACPI_ADR_SPACE_IPMI:
|
||||||
|
|
||||||
|
buffer_length = ACPI_IPMI_BUFFER_SIZE;
|
||||||
|
function = ACPI_READ;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACPI_ADR_SPACE_GSBUS:
|
||||||
|
|
||||||
|
accessor_type = obj_desc->field.attribute;
|
||||||
|
if (accessor_type == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES) {
|
||||||
|
ACPI_ERROR((AE_INFO,
|
||||||
|
"Invalid direct read using bidirectional write-then-read protocol"));
|
||||||
|
|
||||||
|
return_ACPI_STATUS(AE_AML_PROTOCOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
status =
|
||||||
|
acpi_ex_get_protocol_buffer_length(accessor_type,
|
||||||
|
&buffer_length);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
ACPI_ERROR((AE_INFO,
|
||||||
|
"Invalid protocol ID for GSBus: 0x%4.4X",
|
||||||
|
accessor_type));
|
||||||
|
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add header length to get the full size of the buffer */
|
||||||
|
|
||||||
|
buffer_length += ACPI_SERIAL_HEADER_SIZE;
|
||||||
|
function = ACPI_READ | (accessor_type << 16);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the local transfer buffer that is returned to the caller */
|
||||||
|
|
||||||
|
buffer_desc = acpi_ut_create_buffer_object(buffer_length);
|
||||||
|
if (!buffer_desc) {
|
||||||
|
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock entire transaction if requested */
|
||||||
|
|
||||||
|
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
|
/* Call the region handler for the write-then-read */
|
||||||
|
|
||||||
|
status = acpi_ex_access_region(obj_desc, 0,
|
||||||
|
ACPI_CAST_PTR(u64,
|
||||||
|
buffer_desc->buffer.
|
||||||
|
pointer), function);
|
||||||
|
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
|
*return_buffer = buffer_desc;
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ex_write_serial_bus
|
||||||
|
*
|
||||||
|
* PARAMETERS: source_desc - Contains data to write
|
||||||
|
* obj_desc - The named field
|
||||||
|
* return_buffer - Where the return value is returned, if any
|
||||||
|
*
|
||||||
|
* RETURN: Status
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Write to a named field that references a serial bus
|
||||||
|
* (SMBus, IPMI, GSBus).
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
acpi_status
|
||||||
|
acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
|
||||||
|
union acpi_operand_object *obj_desc,
|
||||||
|
union acpi_operand_object **return_buffer)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
u32 buffer_length;
|
||||||
|
u32 data_length;
|
||||||
|
void *buffer;
|
||||||
|
union acpi_operand_object *buffer_desc;
|
||||||
|
u32 function;
|
||||||
|
u16 accessor_type;
|
||||||
|
|
||||||
|
ACPI_FUNCTION_TRACE_PTR(ex_write_serial_bus, obj_desc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an SMBus, GSBus or IPMI write. We will bypass the entire
|
||||||
|
* field mechanism and handoff the buffer directly to the handler.
|
||||||
|
* For these address spaces, the buffer is bidirectional; on a
|
||||||
|
* write, return data is returned in the same buffer.
|
||||||
|
*
|
||||||
|
* Source must be a buffer of sufficient size, these are fixed size:
|
||||||
|
* ACPI_SMBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
|
||||||
|
*
|
||||||
|
* Note: SMBus and GSBus protocol type is passed in upper 16-bits
|
||||||
|
* of Function
|
||||||
|
*
|
||||||
|
* Common buffer format:
|
||||||
|
* Status; (Byte 0 of the data buffer)
|
||||||
|
* Length; (Byte 1 of the data buffer)
|
||||||
|
* Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
|
||||||
|
*/
|
||||||
|
if (source_desc->common.type != ACPI_TYPE_BUFFER) {
|
||||||
|
ACPI_ERROR((AE_INFO,
|
||||||
|
"SMBus/IPMI/GenericSerialBus write requires "
|
||||||
|
"Buffer, found type %s",
|
||||||
|
acpi_ut_get_object_type_name(source_desc)));
|
||||||
|
|
||||||
|
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (obj_desc->field.region_obj->region.space_id) {
|
||||||
|
case ACPI_ADR_SPACE_SMBUS:
|
||||||
|
|
||||||
|
buffer_length = ACPI_SMBUS_BUFFER_SIZE;
|
||||||
|
data_length = ACPI_SMBUS_DATA_SIZE;
|
||||||
|
function = ACPI_WRITE | (obj_desc->field.attribute << 16);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACPI_ADR_SPACE_IPMI:
|
||||||
|
|
||||||
|
buffer_length = ACPI_IPMI_BUFFER_SIZE;
|
||||||
|
data_length = ACPI_IPMI_DATA_SIZE;
|
||||||
|
function = ACPI_WRITE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACPI_ADR_SPACE_GSBUS:
|
||||||
|
|
||||||
|
accessor_type = obj_desc->field.attribute;
|
||||||
|
status =
|
||||||
|
acpi_ex_get_protocol_buffer_length(accessor_type,
|
||||||
|
&buffer_length);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
ACPI_ERROR((AE_INFO,
|
||||||
|
"Invalid protocol ID for GSBus: 0x%4.4X",
|
||||||
|
accessor_type));
|
||||||
|
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add header length to get the full size of the buffer */
|
||||||
|
|
||||||
|
buffer_length += ACPI_SERIAL_HEADER_SIZE;
|
||||||
|
data_length = source_desc->buffer.pointer[1];
|
||||||
|
function = ACPI_WRITE | (accessor_type << 16);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
OBSOLETE ?
|
||||||
|
/* Check for possible buffer overflow */
|
||||||
|
if (data_length > source_desc->buffer.length) {
|
||||||
|
ACPI_ERROR((AE_INFO,
|
||||||
|
"Length in buffer header (%u)(%u) is greater than "
|
||||||
|
"the physical buffer length (%u) and will overflow",
|
||||||
|
data_length, buffer_length,
|
||||||
|
source_desc->buffer.length));
|
||||||
|
|
||||||
|
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Create the transfer/bidirectional/return buffer */
|
||||||
|
|
||||||
|
buffer_desc = acpi_ut_create_buffer_object(buffer_length);
|
||||||
|
if (!buffer_desc) {
|
||||||
|
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the input buffer data to the transfer buffer */
|
||||||
|
|
||||||
|
buffer = buffer_desc->buffer.pointer;
|
||||||
|
memcpy(buffer, source_desc->buffer.pointer, data_length);
|
||||||
|
|
||||||
|
/* Lock entire transaction if requested */
|
||||||
|
|
||||||
|
acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform the write (returns status and perhaps data in the
|
||||||
|
* same buffer)
|
||||||
|
*/
|
||||||
|
status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
|
||||||
|
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
|
||||||
|
|
||||||
|
*return_buffer = buffer_desc;
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
@ -147,7 +147,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
|
|||||||
* future. Use of this option can cause problems with AML code that
|
* future. Use of this option can cause problems with AML code that
|
||||||
* depends upon in-order immediate execution of module-level code.
|
* depends upon in-order immediate execution of module-level code.
|
||||||
*/
|
*/
|
||||||
if (acpi_gbl_group_module_level_code &&
|
if (!acpi_gbl_execute_tables_as_methods &&
|
||||||
(walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
|
(walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
|
||||||
((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
|
((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
|
||||||
/*
|
/*
|
||||||
@ -417,6 +417,7 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
|
|||||||
union acpi_parse_object *op = NULL; /* current op */
|
union acpi_parse_object *op = NULL; /* current op */
|
||||||
struct acpi_parse_state *parser_state;
|
struct acpi_parse_state *parser_state;
|
||||||
u8 *aml_op_start = NULL;
|
u8 *aml_op_start = NULL;
|
||||||
|
u8 opcode_length;
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
|
ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
|
||||||
|
|
||||||
@ -540,8 +541,19 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
|
|||||||
"Skip parsing opcode %s",
|
"Skip parsing opcode %s",
|
||||||
acpi_ps_get_opcode_name
|
acpi_ps_get_opcode_name
|
||||||
(walk_state->opcode)));
|
(walk_state->opcode)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine the opcode length before skipping the opcode.
|
||||||
|
* An opcode can be 1 byte or 2 bytes in length.
|
||||||
|
*/
|
||||||
|
opcode_length = 1;
|
||||||
|
if ((walk_state->opcode & 0xFF00) ==
|
||||||
|
AML_EXTENDED_OPCODE) {
|
||||||
|
opcode_length = 2;
|
||||||
|
}
|
||||||
walk_state->parser_state.aml =
|
walk_state->parser_state.aml =
|
||||||
walk_state->aml + 1;
|
walk_state->aml + opcode_length;
|
||||||
|
|
||||||
walk_state->parser_state.aml =
|
walk_state->parser_state.aml =
|
||||||
acpi_ps_get_next_package_end
|
acpi_ps_get_next_package_end
|
||||||
(&walk_state->parser_state);
|
(&walk_state->parser_state);
|
||||||
|
@ -69,8 +69,7 @@ acpi_status ACPI_INIT_FUNCTION acpi_load_tables(void)
|
|||||||
"While loading namespace from ACPI tables"));
|
"While loading namespace from ACPI tables"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (acpi_gbl_execute_tables_as_methods
|
if (acpi_gbl_execute_tables_as_methods) {
|
||||||
|| !acpi_gbl_group_module_level_code) {
|
|
||||||
/*
|
/*
|
||||||
* If the module-level code support is enabled, initialize the objects
|
* If the module-level code support is enabled, initialize the objects
|
||||||
* in the namespace that remain uninitialized. This runs the executable
|
* in the namespace that remain uninitialized. This runs the executable
|
||||||
|
@ -173,11 +173,20 @@
|
|||||||
#define ACPI_RSDP_CHECKSUM_LENGTH 20
|
#define ACPI_RSDP_CHECKSUM_LENGTH 20
|
||||||
#define ACPI_RSDP_XCHECKSUM_LENGTH 36
|
#define ACPI_RSDP_XCHECKSUM_LENGTH 36
|
||||||
|
|
||||||
/* SMBus, GSBus and IPMI bidirectional buffer size */
|
/*
|
||||||
|
* SMBus, GSBus and IPMI buffer sizes. All have a 2-byte header,
|
||||||
|
* containing both Status and Length.
|
||||||
|
*/
|
||||||
|
#define ACPI_SERIAL_HEADER_SIZE 2 /* Common for below. Status and Length fields */
|
||||||
|
|
||||||
#define ACPI_SMBUS_BUFFER_SIZE 34
|
#define ACPI_SMBUS_DATA_SIZE 32
|
||||||
#define ACPI_GSBUS_BUFFER_SIZE 34
|
#define ACPI_SMBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_SMBUS_DATA_SIZE
|
||||||
#define ACPI_IPMI_BUFFER_SIZE 66
|
|
||||||
|
#define ACPI_IPMI_DATA_SIZE 64
|
||||||
|
#define ACPI_IPMI_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_IPMI_DATA_SIZE
|
||||||
|
|
||||||
|
#define ACPI_MAX_GSBUS_DATA_SIZE 255
|
||||||
|
#define ACPI_MAX_GSBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_MAX_GSBUS_DATA_SIZE
|
||||||
|
|
||||||
/* _sx_d and _sx_w control methods */
|
/* _sx_d and _sx_w control methods */
|
||||||
|
|
||||||
|
@ -171,8 +171,10 @@ struct acpi_exception_info {
|
|||||||
#define AE_AML_LOOP_TIMEOUT EXCEP_AML (0x0021)
|
#define AE_AML_LOOP_TIMEOUT EXCEP_AML (0x0021)
|
||||||
#define AE_AML_UNINITIALIZED_NODE EXCEP_AML (0x0022)
|
#define AE_AML_UNINITIALIZED_NODE EXCEP_AML (0x0022)
|
||||||
#define AE_AML_TARGET_TYPE EXCEP_AML (0x0023)
|
#define AE_AML_TARGET_TYPE EXCEP_AML (0x0023)
|
||||||
|
#define AE_AML_PROTOCOL EXCEP_AML (0x0024)
|
||||||
|
#define AE_AML_BUFFER_LENGTH EXCEP_AML (0x0025)
|
||||||
|
|
||||||
#define AE_CODE_AML_MAX 0x0023
|
#define AE_CODE_AML_MAX 0x0025
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal exceptions used for control
|
* Internal exceptions used for control
|
||||||
@ -347,7 +349,10 @@ static const struct acpi_exception_info acpi_gbl_exception_names_aml[] = {
|
|||||||
EXCEP_TXT("AE_AML_UNINITIALIZED_NODE",
|
EXCEP_TXT("AE_AML_UNINITIALIZED_NODE",
|
||||||
"A namespace node is uninitialized or unresolved"),
|
"A namespace node is uninitialized or unresolved"),
|
||||||
EXCEP_TXT("AE_AML_TARGET_TYPE",
|
EXCEP_TXT("AE_AML_TARGET_TYPE",
|
||||||
"A target operand of an incorrect type was encountered")
|
"A target operand of an incorrect type was encountered"),
|
||||||
|
EXCEP_TXT("AE_AML_PROTOCOL", "Violation of a fixed ACPI protocol"),
|
||||||
|
EXCEP_TXT("AE_AML_BUFFER_LENGTH",
|
||||||
|
"The length of the buffer is invalid/incorrect")
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = {
|
static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
/* Current ACPICA subsystem version in YYYYMMDD format */
|
/* Current ACPICA subsystem version in YYYYMMDD format */
|
||||||
|
|
||||||
#define ACPI_CA_VERSION 0x20180810
|
#define ACPI_CA_VERSION 0x20181003
|
||||||
|
|
||||||
#include <acpi/acconfig.h>
|
#include <acpi/acconfig.h>
|
||||||
#include <acpi/actypes.h>
|
#include <acpi/actypes.h>
|
||||||
@ -156,13 +156,6 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_copy_dsdt_locally, FALSE);
|
|||||||
*/
|
*/
|
||||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
|
ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
|
||||||
|
|
||||||
/*
|
|
||||||
* Optionally support group module level code.
|
|
||||||
* NOTE, this is essentially obsolete and will be removed soon
|
|
||||||
* (01/2018).
|
|
||||||
*/
|
|
||||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, FALSE);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Optionally support module level code by parsing an entire table as
|
* Optionally support module level code by parsing an entire table as
|
||||||
* a method as it is loaded. Default is TRUE.
|
* a method as it is loaded. Default is TRUE.
|
||||||
|
Loading…
Reference in New Issue
Block a user