diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f2e283426be9..f205b368894b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -662,6 +662,33 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver); | |||
662 | /* -------------------------------------------------------------------------- | 662 | /* -------------------------------------------------------------------------- |
663 | Device Enumeration | 663 | Device Enumeration |
664 | -------------------------------------------------------------------------- */ | 664 | -------------------------------------------------------------------------- */ |
665 | static struct acpi_device *acpi_bus_get_parent(acpi_handle handle) | ||
666 | { | ||
667 | acpi_status status; | ||
668 | int ret; | ||
669 | struct acpi_device *device; | ||
670 | |||
671 | /* | ||
672 | * Fixed hardware devices do not appear in the namespace and do not | ||
673 | * have handles, but we fabricate acpi_devices for them, so we have | ||
674 | * to deal with them specially. | ||
675 | */ | ||
676 | if (handle == NULL) | ||
677 | return acpi_root; | ||
678 | |||
679 | do { | ||
680 | status = acpi_get_parent(handle, &handle); | ||
681 | if (status == AE_NULL_ENTRY) | ||
682 | return NULL; | ||
683 | if (ACPI_FAILURE(status)) | ||
684 | return acpi_root; | ||
685 | |||
686 | ret = acpi_bus_get_device(handle, &device); | ||
687 | if (ret == 0) | ||
688 | return device; | ||
689 | } while (1); | ||
690 | } | ||
691 | |||
665 | acpi_status | 692 | acpi_status |
666 | acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) | 693 | acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) |
667 | { | 694 | { |
@@ -1217,10 +1244,9 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) | |||
1217 | return 0; | 1244 | return 0; |
1218 | } | 1245 | } |
1219 | 1246 | ||
1220 | static int | 1247 | static int acpi_add_single_object(struct acpi_device **child, |
1221 | acpi_add_single_object(struct acpi_device **child, | 1248 | acpi_handle handle, int type, |
1222 | struct acpi_device *parent, acpi_handle handle, int type, | 1249 | struct acpi_bus_ops *ops) |
1223 | struct acpi_bus_ops *ops) | ||
1224 | { | 1250 | { |
1225 | int result; | 1251 | int result; |
1226 | struct acpi_device *device; | 1252 | struct acpi_device *device; |
@@ -1234,7 +1260,7 @@ acpi_add_single_object(struct acpi_device **child, | |||
1234 | 1260 | ||
1235 | device->device_type = type; | 1261 | device->device_type = type; |
1236 | device->handle = handle; | 1262 | device->handle = handle; |
1237 | device->parent = parent; | 1263 | device->parent = acpi_bus_get_parent(handle); |
1238 | device->bus_ops = *ops; /* workround for not call .start */ | 1264 | device->bus_ops = *ops; /* workround for not call .start */ |
1239 | 1265 | ||
1240 | acpi_device_get_busid(device); | 1266 | acpi_device_get_busid(device); |
@@ -1434,8 +1460,8 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops) | |||
1434 | } | 1460 | } |
1435 | 1461 | ||
1436 | if (ops->acpi_op_add) | 1462 | if (ops->acpi_op_add) |
1437 | status = acpi_add_single_object(&child, parent, | 1463 | status = acpi_add_single_object(&child, chandle, type, |
1438 | chandle, type, ops); | 1464 | ops); |
1439 | else | 1465 | else |
1440 | status = acpi_bus_get_device(chandle, &child); | 1466 | status = acpi_bus_get_device(chandle, &child); |
1441 | 1467 | ||
@@ -1488,7 +1514,7 @@ acpi_bus_add(struct acpi_device **child, | |||
1488 | memset(&ops, 0, sizeof(ops)); | 1514 | memset(&ops, 0, sizeof(ops)); |
1489 | ops.acpi_op_add = 1; | 1515 | ops.acpi_op_add = 1; |
1490 | 1516 | ||
1491 | result = acpi_add_single_object(child, parent, handle, type, &ops); | 1517 | result = acpi_add_single_object(child, handle, type, &ops); |
1492 | if (!result) | 1518 | if (!result) |
1493 | result = acpi_bus_scan(*child, &ops); | 1519 | result = acpi_bus_scan(*child, &ops); |
1494 | 1520 | ||
@@ -1584,15 +1610,13 @@ static int acpi_bus_scan_fixed(void) | |||
1584 | * Enumerate all fixed-feature devices. | 1610 | * Enumerate all fixed-feature devices. |
1585 | */ | 1611 | */ |
1586 | if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { | 1612 | if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) { |
1587 | result = acpi_add_single_object(&device, acpi_root, | 1613 | result = acpi_add_single_object(&device, NULL, |
1588 | NULL, | ||
1589 | ACPI_BUS_TYPE_POWER_BUTTON, | 1614 | ACPI_BUS_TYPE_POWER_BUTTON, |
1590 | &ops); | 1615 | &ops); |
1591 | } | 1616 | } |
1592 | 1617 | ||
1593 | if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { | 1618 | if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { |
1594 | result = acpi_add_single_object(&device, acpi_root, | 1619 | result = acpi_add_single_object(&device, NULL, |
1595 | NULL, | ||
1596 | ACPI_BUS_TYPE_SLEEP_BUTTON, | 1620 | ACPI_BUS_TYPE_SLEEP_BUTTON, |
1597 | &ops); | 1621 | &ops); |
1598 | } | 1622 | } |
@@ -1618,7 +1642,7 @@ int __init acpi_scan_init(void) | |||
1618 | /* | 1642 | /* |
1619 | * Create the root device in the bus's device tree | 1643 | * Create the root device in the bus's device tree |
1620 | */ | 1644 | */ |
1621 | result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, | 1645 | result = acpi_add_single_object(&acpi_root, ACPI_ROOT_OBJECT, |
1622 | ACPI_BUS_TYPE_SYSTEM, &ops); | 1646 | ACPI_BUS_TYPE_SYSTEM, &ops); |
1623 | if (result) | 1647 | if (result) |
1624 | goto Done; | 1648 | goto Done; |