aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2009-09-21 15:29:56 -0400
committerLen Brown <len.brown@intel.com>2009-09-25 14:24:30 -0400
commit51a85faf2d4ffecd8384b3f501f9f7ee2b05ee53 (patch)
tree6ca93c9b1a14da2fb140a74f3f3b23976b5ecd0b /drivers/acpi
parent859ac9a4be0c753cece0e30a2e4a65fd2cdcaeee (diff)
ACPI: use acpi_walk_namespace() to enumerate devices
acpi_bus_scan() currently walks the namespace manually. This patch changes it to use acpi_walk_namespace() instead. Besides removing some complicated code, this means we take advantage of the namespace locking done by acpi_walk_namespace(). The locking isn't so important at boot-time, but I hope to eventually use this same path to handle hot-addition of devices, when it will be important. Note that acpi_walk_namespace() does not actually visit the starting node first, so we need to do that by hand first. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/scan.c196
1 files changed, 74 insertions, 122 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 0b5aaf059c9b..ed2b5f9a9815 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1393,123 +1393,92 @@ end:
1393 return result; 1393 return result;
1394} 1394}
1395 1395
1396static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops) 1396static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
1397 void *context, void **return_value)
1397{ 1398{
1398 acpi_status status = AE_OK; 1399 acpi_status status = AE_OK;
1399 struct acpi_device *parent = NULL; 1400 struct acpi_device *device = NULL;
1400 struct acpi_device *child = NULL;
1401 acpi_handle phandle = NULL;
1402 acpi_handle chandle = NULL;
1403 acpi_object_type type = 0; 1401 acpi_object_type type = 0;
1404 u32 level = 1; 1402 struct acpi_bus_ops *ops = context;
1405 int ret;
1406 1403
1407 /* 1404 status = acpi_get_type(handle, &type);
1408 * We must have an acpi_device for the starting node already, and 1405 if (ACPI_FAILURE(status))
1409 * we scan its children. 1406 return AE_OK;
1410 */
1411 phandle = handle;
1412 ret = acpi_bus_get_device(phandle, &parent);
1413 if (ret)
1414 return ret;
1415 1407
1416 /* 1408 /*
1417 * Parse through the ACPI namespace, identify all 'devices', and 1409 * We're only interested in objects that we consider 'devices'.
1418 * create a new 'struct acpi_device' for each.
1419 */ 1410 */
1420 while ((level > 0) && parent) { 1411 switch (type) {
1412 case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */
1413 case ACPI_TYPE_DEVICE:
1414 type = ACPI_BUS_TYPE_DEVICE;
1415 break;
1416 case ACPI_TYPE_PROCESSOR:
1417 type = ACPI_BUS_TYPE_PROCESSOR;
1418 break;
1419 case ACPI_TYPE_THERMAL:
1420 type = ACPI_BUS_TYPE_THERMAL;
1421 break;
1422 case ACPI_TYPE_POWER:
1423 type = ACPI_BUS_TYPE_POWER;
1424 break;
1425 default:
1426 return AE_OK;
1427 }
1421 1428
1422 status = acpi_get_next_object(ACPI_TYPE_ANY, phandle, 1429 if (ops->acpi_op_add)
1423 chandle, &chandle); 1430 status = acpi_add_single_object(&device, handle, type, ops);
1431 else
1432 status = acpi_bus_get_device(handle, &device);
1424 1433
1425 /* 1434 if (ACPI_FAILURE(status))
1426 * If this scope is exhausted then move our way back up. 1435 return AE_CTRL_DEPTH;
1427 */
1428 if (ACPI_FAILURE(status)) {
1429 level--;
1430 chandle = phandle;
1431 acpi_get_parent(phandle, &phandle);
1432 if (parent->parent)
1433 parent = parent->parent;
1434 continue;
1435 }
1436 1436
1437 status = acpi_get_type(chandle, &type); 1437 if (ops->acpi_op_start && !(ops->acpi_op_add)) {
1438 status = acpi_start_single_object(device);
1438 if (ACPI_FAILURE(status)) 1439 if (ACPI_FAILURE(status))
1439 continue; 1440 return AE_CTRL_DEPTH;
1440 1441 }
1441 /*
1442 * If this is a scope object then parse it (depth-first).
1443 */
1444 if (type == ACPI_TYPE_LOCAL_SCOPE) {
1445 level++;
1446 phandle = chandle;
1447 chandle = NULL;
1448 continue;
1449 }
1450 1442
1451 /* 1443 /*
1452 * We're only interested in objects that we consider 'devices'. 1444 * If the device is present, enabled, and functioning then
1453 */ 1445 * parse its scope (depth-first). Note that we need to
1454 switch (type) { 1446 * represent absent devices to facilitate PnP notifications
1455 case ACPI_TYPE_DEVICE: 1447 * -- but only the subtree head (not all of its children,
1456 type = ACPI_BUS_TYPE_DEVICE; 1448 * which will be enumerated when the parent is inserted).
1457 break; 1449 *
1458 case ACPI_TYPE_PROCESSOR: 1450 * TBD: Need notifications and other detection mechanisms
1459 type = ACPI_BUS_TYPE_PROCESSOR; 1451 * in place before we can fully implement this.
1460 break; 1452 *
1461 case ACPI_TYPE_THERMAL: 1453 * When the device is not present but functional, it is also
1462 type = ACPI_BUS_TYPE_THERMAL; 1454 * necessary to scan the children of this device.
1463 break; 1455 */
1464 case ACPI_TYPE_POWER: 1456 if (!device->status.present && !device->status.functional)
1465 type = ACPI_BUS_TYPE_POWER; 1457 return AE_CTRL_DEPTH;
1466 break;
1467 default:
1468 continue;
1469 }
1470 1458
1471 if (ops->acpi_op_add) 1459 if (!*return_value)
1472 status = acpi_add_single_object(&child, chandle, type, 1460 *return_value = device;
1473 ops); 1461 return AE_OK;
1474 else 1462}
1475 status = acpi_bus_get_device(chandle, &child);
1476 1463
1477 if (ACPI_FAILURE(status)) 1464static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
1478 continue; 1465 struct acpi_device **child)
1466{
1467 acpi_status status;
1468 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
1469 void *device = NULL;
1479 1470
1480 if (ops->acpi_op_start && !(ops->acpi_op_add)) { 1471 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1481 status = acpi_start_single_object(child); 1472 printk(KERN_INFO PREFIX "Enumerating devices from [%s]\n",
1482 if (ACPI_FAILURE(status)) 1473 (char *) buffer.pointer);
1483 continue;
1484 }
1485 1474
1486 /* 1475 status = acpi_bus_check_add(handle, 0, ops, &device);
1487 * If the device is present, enabled, and functioning then 1476 if (ACPI_SUCCESS(status))
1488 * parse its scope (depth-first). Note that we need to 1477 acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
1489 * represent absent devices to facilitate PnP notifications 1478 acpi_bus_check_add, ops, &device);
1490 * -- but only the subtree head (not all of its children,
1491 * which will be enumerated when the parent is inserted).
1492 *
1493 * TBD: Need notifications and other detection mechanisms
1494 * in place before we can fully implement this.
1495 */
1496 /*
1497 * When the device is not present but functional, it is also
1498 * necessary to scan the children of this device.
1499 */
1500 if (child->status.present || (!child->status.present &&
1501 child->status.functional)) {
1502 status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
1503 NULL, NULL);
1504 if (ACPI_SUCCESS(status)) {
1505 level++;
1506 phandle = chandle;
1507 chandle = NULL;
1508 parent = child;
1509 }
1510 }
1511 }
1512 1479
1480 if (child)
1481 *child = device;
1513 return 0; 1482 return 0;
1514} 1483}
1515 1484
@@ -1517,33 +1486,25 @@ int
1517acpi_bus_add(struct acpi_device **child, 1486acpi_bus_add(struct acpi_device **child,
1518 struct acpi_device *parent, acpi_handle handle, int type) 1487 struct acpi_device *parent, acpi_handle handle, int type)
1519{ 1488{
1520 int result;
1521 struct acpi_bus_ops ops; 1489 struct acpi_bus_ops ops;
1522 1490
1523 memset(&ops, 0, sizeof(ops)); 1491 memset(&ops, 0, sizeof(ops));
1524 ops.acpi_op_add = 1; 1492 ops.acpi_op_add = 1;
1525 1493
1526 result = acpi_add_single_object(child, handle, type, &ops); 1494 acpi_bus_scan(handle, &ops, child);
1527 if (!result) 1495 return 0;
1528 result = acpi_bus_scan((*child)->handle, &ops);
1529
1530 return result;
1531} 1496}
1532EXPORT_SYMBOL(acpi_bus_add); 1497EXPORT_SYMBOL(acpi_bus_add);
1533 1498
1534int acpi_bus_start(struct acpi_device *device) 1499int acpi_bus_start(struct acpi_device *device)
1535{ 1500{
1536 int result;
1537 struct acpi_bus_ops ops; 1501 struct acpi_bus_ops ops;
1538 1502
1539 memset(&ops, 0, sizeof(ops)); 1503 memset(&ops, 0, sizeof(ops));
1540 ops.acpi_op_start = 1; 1504 ops.acpi_op_start = 1;
1541 1505
1542 result = acpi_start_single_object(device); 1506 acpi_bus_scan(device->handle, &ops, NULL);
1543 if (!result) 1507 return 0;
1544 result = acpi_bus_scan(device->handle, &ops);
1545
1546 return result;
1547} 1508}
1548EXPORT_SYMBOL(acpi_bus_start); 1509EXPORT_SYMBOL(acpi_bus_start);
1549 1510
@@ -1646,17 +1607,9 @@ int __init acpi_scan_init(void)
1646 } 1607 }
1647 1608
1648 /* 1609 /*
1649 * Create the root device in the bus's device tree
1650 */
1651 result = acpi_add_single_object(&acpi_root, ACPI_ROOT_OBJECT,
1652 ACPI_BUS_TYPE_DEVICE, &ops);
1653 if (result)
1654 goto Done;
1655
1656 /*
1657 * Enumerate devices in the ACPI namespace. 1610 * Enumerate devices in the ACPI namespace.
1658 */ 1611 */
1659 result = acpi_bus_scan(acpi_root->handle, &ops); 1612 result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
1660 1613
1661 if (!result) 1614 if (!result)
1662 result = acpi_bus_scan_fixed(); 1615 result = acpi_bus_scan_fixed();
@@ -1664,6 +1617,5 @@ int __init acpi_scan_init(void)
1664 if (result) 1617 if (result)
1665 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); 1618 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
1666 1619
1667Done:
1668 return result; 1620 return result;
1669} 1621}