summaryrefslogtreecommitdiff
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r--drivers/acpi/acpica/hwsleep.c43
-rw-r--r--drivers/acpi/acpica/hwvalid.c86
-rw-r--r--drivers/acpi/acpica/rscalc.c7
-rw-r--r--drivers/acpi/acpica/rscreate.c27
4 files changed, 107 insertions, 56 deletions
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index baa5fc05e124..db307a356f08 100644
--- a/drivers/acpi/acpica/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -211,6 +211,12 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
+static unsigned int gts, bfs;
+module_param(gts, uint, 0644);
+module_param(bfs, uint, 0644);
+MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend.");
+MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".);
+
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state
@@ -278,16 +284,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
return_ACPI_STATUS(status);
}
- /* Execute the _GTS method */
+ if (gts) {
+ /* Execute the _GTS method */
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = sleep_state;
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = sleep_state;
- status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- return_ACPI_STATUS(status);
+ status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ return_ACPI_STATUS(status);
+ }
}
/* Get current value of PM1A control */
@@ -513,18 +521,19 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
}
}
- /* Execute the _BFS method */
+ if (bfs) {
+ /* Execute the _BFS method */
- arg_list.count = 1;
- arg_list.pointer = &arg;
- arg.type = ACPI_TYPE_INTEGER;
- arg.integer.value = sleep_state;
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = sleep_state;
- status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
+ status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
+ }
}
-
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c
index 7737afb157c3..ec33f270c5b7 100644
--- a/drivers/acpi/acpica/hwvalid.c
+++ b/drivers/acpi/acpica/hwvalid.c
@@ -90,6 +90,7 @@ static const struct acpi_port_info acpi_protected_ports[] = {
{"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP},
{"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP},
{"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP},
+ {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP},
{"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP},
{"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP},
{"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP},
@@ -151,7 +152,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
ACPI_ERROR((AE_INFO,
"Illegal I/O port address/length above 64K: 0x%p/%X",
ACPI_CAST_PTR(void, address), byte_width));
- return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
+ return_ACPI_STATUS(AE_LIMIT);
}
/* Exit if requested address is not within the protected port table */
@@ -178,11 +179,12 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
/* Port illegality may depend on the _OSI calls made by the BIOS */
if (acpi_gbl_osi_data >= port_info->osi_dependency) {
- ACPI_ERROR((AE_INFO,
- "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
- ACPI_CAST_PTR(void, address),
- byte_width, port_info->name,
- port_info->start, port_info->end));
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
+ ACPI_CAST_PTR(void, address),
+ byte_width, port_info->name,
+ port_info->start,
+ port_info->end));
return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
}
@@ -206,7 +208,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
* Value Where value is placed
* Width Number of bits
*
- * RETURN: Value read from port
+ * RETURN: Status and value read from port
*
* DESCRIPTION: Read data from an I/O port or register. This is a front-end
* to acpi_os_read_port that performs validation on both the port
@@ -217,14 +219,43 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
{
acpi_status status;
+ u32 one_byte;
+ u32 i;
+
+ /* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
- if (ACPI_FAILURE(status)) {
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_os_read_port(address, value, width);
return status;
}
- status = acpi_os_read_port(address, value, width);
- return status;
+ if (status != AE_AML_ILLEGAL_ADDRESS) {
+ return status;
+ }
+
+ /*
+ * There has been a protection violation within the request. Fall
+ * back to byte granularity port I/O and ignore the failing bytes.
+ * This provides Windows compatibility.
+ */
+ for (i = 0, *value = 0; i < width; i += 8) {
+
+ /* Validate and read one byte */
+
+ if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
+ status = acpi_os_read_port(address, &one_byte, 8);
+ if (ACPI_FAILURE(status)) {
+ return status;
+ }
+
+ *value |= (one_byte << i);
+ }
+
+ address++;
+ }
+
+ return AE_OK;
}
/******************************************************************************
@@ -235,7 +266,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
* Value Value to write
* Width Number of bits
*
- * RETURN: None
+ * RETURN: Status
*
* DESCRIPTION: Write data to an I/O port or register. This is a front-end
* to acpi_os_write_port that performs validation on both the port
@@ -246,12 +277,39 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
{
acpi_status status;
+ u32 i;
+
+ /* Validate the entire request and perform the I/O */
status = acpi_hw_validate_io_request(address, width);
- if (ACPI_FAILURE(status)) {
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_os_write_port(address, value, width);
return status;
}
- status = acpi_os_write_port(address, value, width);
- return status;
+ if (status != AE_AML_ILLEGAL_ADDRESS) {
+ return status;
+ }
+
+ /*
+ * There has been a protection violation within the request. Fall
+ * back to byte granularity port I/O and ignore the failing bytes.
+ * This provides Windows compatibility.
+ */
+ for (i = 0; i < width; i += 8) {
+
+ /* Validate and write one byte */
+
+ if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
+ status =
+ acpi_os_write_port(address, (value >> i) & 0xFF, 8);
+ if (ACPI_FAILURE(status)) {
+ return status;
+ }
+ }
+
+ address++;
+ }
+
+ return AE_OK;
}
diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c
index b6667ff059e5..88b5a2c4814d 100644
--- a/drivers/acpi/acpica/rscalc.c
+++ b/drivers/acpi/acpica/rscalc.c
@@ -543,6 +543,13 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
package_element = *top_object_list;
+ /* We must have a valid Package object */
+
+ if (!package_element ||
+ (package_element->common.type != ACPI_TYPE_PACKAGE)) {
+ return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ }
+
/*
* The sub_object_list will now point to an array of the
* four IRQ elements: Address, Pin, Source and source_index
diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c
index 663f692fffcf..a3c23d686d5f 100644
--- a/drivers/acpi/acpica/rscreate.c
+++ b/drivers/acpi/acpica/rscreate.c
@@ -191,8 +191,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
for (index = 0; index < number_of_elements; index++) {
- int source_name_index = 2;
- int source_index_index = 3;
/*
* Point user_prt past this current structure
@@ -261,27 +259,6 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
return_ACPI_STATUS(AE_BAD_DATA);
}
- /*
- * If BIOS erroneously reversed the _PRT source_name and source_index,
- * then reverse them back.
- */
- if ((sub_object_list[3])->common.type !=
- ACPI_TYPE_INTEGER) {
- if (acpi_gbl_enable_interpreter_slack) {
- source_name_index = 3;
- source_index_index = 2;
- printk(KERN_WARNING
- "ACPI: Handling Garbled _PRT entry\n");
- } else {
- ACPI_ERROR((AE_INFO,
- "(PRT[%X].source_index) Need Integer, found %s",
- index,
- acpi_ut_get_object_type_name
- (sub_object_list[3])));
- return_ACPI_STATUS(AE_BAD_DATA);
- }
- }
-
user_prt->pin = (u32) obj_desc->integer.value;
/*
@@ -304,7 +281,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
* 3) Third subobject: Dereference the PRT.source_name
* The name may be unresolved (slack mode), so allow a null object
*/
- obj_desc = sub_object_list[source_name_index];
+ obj_desc = sub_object_list[2];
if (obj_desc) {
switch (obj_desc->common.type) {
case ACPI_TYPE_LOCAL_REFERENCE:
@@ -378,7 +355,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
/* 4) Fourth subobject: Dereference the PRT.source_index */
- obj_desc = sub_object_list[source_index_index];
+ obj_desc = sub_object_list[3];
if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO,
"(PRT[%X].SourceIndex) Need Integer, found %s",