diff options
author | Patrick Mochel <patrick.mochel@intel.com> | 2006-05-10 10:33:00 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-05-15 02:44:47 -0400 |
commit | 5b3272655a8e8a9a6e2503bc5a88fc9d9c8292a4 (patch) | |
tree | a292396e87e1bdafdca199ab1c1843302ccf00f6 /drivers/acpi | |
parent | d8c3291c73b958243b33f8509d4507e76dafd055 (diff) |
ACPI: create acpi_device_suspend()/acpi_device_resume()
updated and tested by Konstantin Karasyov
http://bugzilla.kernel.org/show_bug.cgi?id=5000
Signed-off-by: Patrick Mochel <patrick.mochel@intel.com>
Signed-off-by: Konstantin Karasyov <konstantin.karasyov @intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/scan.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a0ab828b2cc5..19ae9ff10210 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -1371,6 +1371,108 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) | |||
1371 | return_VALUE(result); | 1371 | return_VALUE(result); |
1372 | } | 1372 | } |
1373 | 1373 | ||
1374 | |||
1375 | static struct acpi_device * to_acpi_dev(struct device * dev) | ||
1376 | { | ||
1377 | return container_of(dev, struct acpi_device, dev); | ||
1378 | } | ||
1379 | |||
1380 | |||
1381 | static int root_suspend(struct acpi_device * acpi_dev) | ||
1382 | { | ||
1383 | struct acpi_device * dev, * next; | ||
1384 | int result; | ||
1385 | |||
1386 | spin_lock(&acpi_device_lock); | ||
1387 | list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { | ||
1388 | if (dev->driver && dev->driver->ops.suspend) { | ||
1389 | spin_unlock(&acpi_device_lock); | ||
1390 | |||
1391 | /* TBD: What suspend state should be passed | ||
1392 | * to device? | ||
1393 | */ | ||
1394 | result = dev->driver->ops.suspend(dev, 0); | ||
1395 | if (result) { | ||
1396 | printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", | ||
1397 | acpi_device_name(dev), | ||
1398 | acpi_device_bid(dev), result); | ||
1399 | } | ||
1400 | spin_lock(&acpi_device_lock); | ||
1401 | } | ||
1402 | } | ||
1403 | spin_unlock(&acpi_device_lock); | ||
1404 | return 0; | ||
1405 | } | ||
1406 | |||
1407 | |||
1408 | static int acpi_device_suspend(struct device * dev, pm_message_t state) | ||
1409 | { | ||
1410 | struct acpi_device * acpi_dev = to_acpi_dev(dev); | ||
1411 | |||
1412 | /* | ||
1413 | * For now, we should only register 1 generic device - | ||
1414 | * the ACPI root device - and from there, we walk the | ||
1415 | * tree of ACPI devices to suspend each one using the | ||
1416 | * ACPI driver methods. | ||
1417 | */ | ||
1418 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||
1419 | root_suspend(acpi_dev); | ||
1420 | return 0; | ||
1421 | } | ||
1422 | |||
1423 | |||
1424 | |||
1425 | static int root_resume(struct acpi_device * acpi_dev) | ||
1426 | { | ||
1427 | struct acpi_device * dev, * next; | ||
1428 | int result; | ||
1429 | |||
1430 | spin_lock(&acpi_device_lock); | ||
1431 | list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { | ||
1432 | if (dev->driver && dev->driver->ops.resume) { | ||
1433 | spin_unlock(&acpi_device_lock); | ||
1434 | |||
1435 | /* TBD: What suspend state should be passed | ||
1436 | * to device? | ||
1437 | */ | ||
1438 | result = dev->driver->ops.resume(dev, 0); | ||
1439 | if (result) { | ||
1440 | printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", | ||
1441 | acpi_device_name(dev), | ||
1442 | acpi_device_bid(dev), result); | ||
1443 | } | ||
1444 | spin_lock(&acpi_device_lock); | ||
1445 | } | ||
1446 | } | ||
1447 | spin_unlock(&acpi_device_lock); | ||
1448 | return 0; | ||
1449 | } | ||
1450 | |||
1451 | |||
1452 | static int acpi_device_resume(struct device * dev) | ||
1453 | { | ||
1454 | struct acpi_device * acpi_dev = to_acpi_dev(dev); | ||
1455 | |||
1456 | /* | ||
1457 | * For now, we should only register 1 generic device - | ||
1458 | * the ACPI root device - and from there, we walk the | ||
1459 | * tree of ACPI devices to resume each one using the | ||
1460 | * ACPI driver methods. | ||
1461 | */ | ||
1462 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||
1463 | root_resume(acpi_dev); | ||
1464 | return 0; | ||
1465 | } | ||
1466 | |||
1467 | |||
1468 | struct bus_type acpi_bus_type = { | ||
1469 | .name = "acpi", | ||
1470 | .suspend = acpi_device_suspend, | ||
1471 | .resume = acpi_device_resume, | ||
1472 | }; | ||
1473 | |||
1474 | |||
1475 | |||
1374 | static int __init acpi_scan_init(void) | 1476 | static int __init acpi_scan_init(void) |
1375 | { | 1477 | { |
1376 | int result; | 1478 | int result; |
@@ -1383,6 +1485,12 @@ static int __init acpi_scan_init(void) | |||
1383 | 1485 | ||
1384 | kset_register(&acpi_namespace_kset); | 1486 | kset_register(&acpi_namespace_kset); |
1385 | 1487 | ||
1488 | result = bus_register(&acpi_bus_type); | ||
1489 | if (result) { | ||
1490 | /* We don't want to quit even if we failed to add suspend/resume */ | ||
1491 | printk(KERN_ERR PREFIX "Could not register bus type\n"); | ||
1492 | } | ||
1493 | |||
1386 | /* | 1494 | /* |
1387 | * Create the root device in the bus's device tree | 1495 | * Create the root device in the bus's device tree |
1388 | */ | 1496 | */ |
@@ -1392,6 +1500,16 @@ static int __init acpi_scan_init(void) | |||
1392 | goto Done; | 1500 | goto Done; |
1393 | 1501 | ||
1394 | result = acpi_start_single_object(acpi_root); | 1502 | result = acpi_start_single_object(acpi_root); |
1503 | if (result) | ||
1504 | goto Done; | ||
1505 | |||
1506 | acpi_root->dev.bus = &acpi_bus_type; | ||
1507 | snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name); | ||
1508 | result = device_register(&acpi_root->dev); | ||
1509 | if (result) { | ||
1510 | /* We don't want to quit even if we failed to add suspend/resume */ | ||
1511 | printk(KERN_ERR PREFIX "Could not register device\n"); | ||
1512 | } | ||
1395 | 1513 | ||
1396 | /* | 1514 | /* |
1397 | * Enumerate devices in the ACPI namespace. | 1515 | * Enumerate devices in the ACPI namespace. |