diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpi_processor.c | 7 | ||||
-rw-r--r-- | drivers/acpi/acpica/exfield.c | 104 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 5 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 21 |
4 files changed, 115 insertions, 22 deletions
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index c29c2c3ec0ad..b06f5f55ada9 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -170,6 +170,9 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr) acpi_status status; int ret; + if (pr->apic_id == -1) + return -ENODEV; + status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta); if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) return -ENODEV; @@ -260,10 +263,8 @@ static int acpi_processor_get_info(struct acpi_device *device) } apic_id = acpi_get_apicid(pr->handle, device_declaration, pr->acpi_id); - if (apic_id < 0) { + if (apic_id < 0) acpi_handle_debug(pr->handle, "failed to get CPU APIC ID.\n"); - return -ENODEV; - } pr->apic_id = apic_id; cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id); diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 68d97441432c..12878e1982f7 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -45,10 +45,71 @@ #include "accommon.h" #include "acdispat.h" #include "acinterp.h" +#include "amlcode.h" #define _COMPONENT ACPI_EXECUTER ACPI_MODULE_NAME("exfield") +/* Local prototypes */ +static u32 +acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length); + +/******************************************************************************* + * + * FUNCTION: acpi_get_serial_access_bytes + * + * PARAMETERS: accessor_type - The type of the protocol indicated by region + * field access attributes + * access_length - The access length of the region field + * + * RETURN: Decoded access length + * + * DESCRIPTION: This routine returns the length of the generic_serial_bus + * protocol bytes + * + ******************************************************************************/ + +static u32 +acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length) +{ + u32 length; + + switch (accessor_type) { + case AML_FIELD_ATTRIB_QUICK: + + length = 0; + 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; + break; + } + + return (length); +} + /******************************************************************************* * * FUNCTION: acpi_ex_read_data_from_field @@ -63,8 +124,9 @@ ACPI_MODULE_NAME("exfield") * Buffer, depending on the size of the field. * ******************************************************************************/ + acpi_status -acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, +acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, union acpi_operand_object *obj_desc, union acpi_operand_object **ret_buffer_desc) { @@ -73,6 +135,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, acpi_size length; void *buffer; u32 function; + u16 accessor_type; ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); @@ -116,9 +179,22 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, ACPI_READ | (obj_desc->field.attribute << 16); } else if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) { - length = ACPI_GSBUS_BUFFER_SIZE; - function = - ACPI_READ | (obj_desc->field.attribute << 16); + 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 modeled generic_serial_bus data buffer: + * typedef struct { + * BYTEStatus; // Byte 0 of the data buffer + * BYTELength; // Byte 1 of the data buffer + * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, + * } + */ + length += 2; + function = ACPI_READ | (accessor_type << 16); } else { /* IPMI */ length = ACPI_IPMI_BUFFER_SIZE; @@ -231,6 +307,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, void *buffer; union acpi_operand_object *buffer_desc; u32 function; + u16 accessor_type; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -284,9 +361,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, ACPI_WRITE | (obj_desc->field.attribute << 16); } else if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) { - length = ACPI_GSBUS_BUFFER_SIZE; - function = - ACPI_WRITE | (obj_desc->field.attribute << 16); + 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 modeled generic_serial_bus data buffer: + * typedef struct { + * BYTEStatus; // Byte 0 of the data buffer + * BYTELength; // Byte 1 of the data buffer + * BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer, + * } + */ + length += 2; + function = ACPI_WRITE | (accessor_type << 16); } else { /* IPMI */ length = ACPI_IPMI_BUFFER_SIZE; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index e7e5844c87d0..cf925c4f36b7 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -380,9 +380,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) break; default: - acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); - ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; - goto err; + acpi_handle_debug(handle, "Unknown event type 0x%x\n", type); + break; } adev = acpi_bus_get_acpi_device(handle); diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index d7d32c28829b..ad11ba4a412d 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -206,13 +206,13 @@ unlock: spin_unlock_irqrestore(&ec->lock, flags); } -static int acpi_ec_sync_query(struct acpi_ec *ec); +static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data); static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) { if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - return acpi_ec_sync_query(ec); + return acpi_ec_sync_query(ec, NULL); } return 0; } @@ -443,10 +443,8 @@ acpi_handle ec_get_handle(void) EXPORT_SYMBOL(ec_get_handle); -static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data); - /* - * Clears stale _Q events that might have accumulated in the EC. + * Process _Q events that might have accumulated in the EC. * Run with locked ec mutex. */ static void acpi_ec_clear(struct acpi_ec *ec) @@ -455,7 +453,7 @@ static void acpi_ec_clear(struct acpi_ec *ec) u8 value = 0; for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) { - status = acpi_ec_query_unlocked(ec, &value); + status = acpi_ec_sync_query(ec, &value); if (status || !value) break; } @@ -582,13 +580,18 @@ static void acpi_ec_run(void *cxt) kfree(handler); } -static int acpi_ec_sync_query(struct acpi_ec *ec) +static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data) { u8 value = 0; int status; struct acpi_ec_query_handler *handler, *copy; - if ((status = acpi_ec_query_unlocked(ec, &value))) + + status = acpi_ec_query_unlocked(ec, &value); + if (data) + *data = value; + if (status) return status; + list_for_each_entry(handler, &ec->list, node) { if (value == handler->query_bit) { /* have custom handler for this bit */ @@ -612,7 +615,7 @@ static void acpi_ec_gpe_query(void *ec_cxt) if (!ec) return; mutex_lock(&ec->mutex); - acpi_ec_sync_query(ec); + acpi_ec_sync_query(ec, NULL); mutex_unlock(&ec->mutex); } |