summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Wu <zlinuxkernel@gmail.com>2013-05-29 06:31:30 +0000
committerSteven Rostedt <rostedt@goodmis.org>2013-09-11 21:21:12 -0400
commitfada392bc066180e40bde2d3d72c0fc03e3eeab6 (patch)
treeb34183b6af1cf1197c25fe3ca903fc2b10b592ae
parent2ff11e0bdfa0103f811e28bed83b098d75a42320 (diff)
downloadlinux-rt-fada392bc066180e40bde2d3d72c0fc03e3eeab6.tar.gz
ACPI: add _STA evaluation at do_acpi_find_child()
[ Upstream commit c7d9ca90aa9497f0b6e301ec67c52dd4b57a7852 ] Once do_acpi_find_child() has found the first matching handle, it makes the acpi_get_child() loop stop and return that handle. On some platforms, though, there are multiple devices with the same value of "_ADR" in the same namespace scope, and if one of them is enabled, the others will be disabled. For example: Address : 0x1FFFF ; path : SB_PCI0.SATA.DEV0 Address : 0x1FFFF ; path : SB_PCI0.SATA.DEV1 Address : 0x1FFFF ; path : SB_PCI0.SATA.DEV2 If DEV0 and DEV1 are disabled and DEV2 is enabled, the handle of DEV2 should be returned, but actually the function always returns the handle of DEV0. To address that issue, make do_acpi_find_child() evaluate _STA to check the device status. If a matching device object exists, but is disabled, acpi_get_child() will continue to walk the namespace in the hope of finding an enabled one. If one is found, its handle will be returned, but otherwise the function will return the handle of the disabled object found before (in case it is enabled going forward). [rjw: Changelog] Signed-off-by: Jeff Wu <zlinuxkernel@gmail.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--drivers/acpi/glue.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 6eff12fb0001..a166b9dc1384 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -91,13 +91,15 @@ static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle)
static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used,
void *addr_p, void **ret_p)
{
- unsigned long long addr;
+ unsigned long long addr, sta;
acpi_status status;
status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr);
if (ACPI_SUCCESS(status) && addr == *((u64 *)addr_p)) {
*ret_p = handle;
- return AE_CTRL_TERMINATE;
+ status = acpi_bus_get_status_handle(handle, &sta);
+ if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_ENABLED))
+ return AE_CTRL_TERMINATE;
}
return AE_OK;
}