diff options
Diffstat (limited to 'drivers/acpi/scan.c')
| -rw-r--r-- | drivers/acpi/scan.c | 178 |
1 files changed, 129 insertions, 49 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a0ab828b2cc5..f8316a05ede7 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -142,7 +142,7 @@ static void acpi_device_register(struct acpi_device *device, | |||
| 142 | create_sysfs_device_files(device); | 142 | create_sysfs_device_files(device); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static int acpi_device_unregister(struct acpi_device *device, int type) | 145 | static void acpi_device_unregister(struct acpi_device *device, int type) |
| 146 | { | 146 | { |
| 147 | spin_lock(&acpi_device_lock); | 147 | spin_lock(&acpi_device_lock); |
| 148 | if (device->parent) { | 148 | if (device->parent) { |
| @@ -158,7 +158,6 @@ static int acpi_device_unregister(struct acpi_device *device, int type) | |||
| 158 | acpi_detach_data(device->handle, acpi_bus_data_handler); | 158 | acpi_detach_data(device->handle, acpi_bus_data_handler); |
| 159 | remove_sysfs_device_files(device); | 159 | remove_sysfs_device_files(device); |
| 160 | kobject_unregister(&device->kobj); | 160 | kobject_unregister(&device->kobj); |
| 161 | return 0; | ||
| 162 | } | 161 | } |
| 163 | 162 | ||
| 164 | void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) | 163 | void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) |
| @@ -234,12 +233,9 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) | |||
| 234 | 233 | ||
| 235 | int acpi_match_ids(struct acpi_device *device, char *ids) | 234 | int acpi_match_ids(struct acpi_device *device, char *ids) |
| 236 | { | 235 | { |
| 237 | int error = 0; | ||
| 238 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 239 | |||
| 240 | if (device->flags.hardware_id) | 236 | if (device->flags.hardware_id) |
| 241 | if (strstr(ids, device->pnp.hardware_id)) | 237 | if (strstr(ids, device->pnp.hardware_id)) |
| 242 | goto Done; | 238 | return 0; |
| 243 | 239 | ||
| 244 | if (device->flags.compatible_ids) { | 240 | if (device->flags.compatible_ids) { |
| 245 | struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; | 241 | struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; |
| @@ -248,15 +244,10 @@ int acpi_match_ids(struct acpi_device *device, char *ids) | |||
| 248 | /* compare multiple _CID entries against driver ids */ | 244 | /* compare multiple _CID entries against driver ids */ |
| 249 | for (i = 0; i < cid_list->count; i++) { | 245 | for (i = 0; i < cid_list->count; i++) { |
| 250 | if (strstr(ids, cid_list->id[i].value)) | 246 | if (strstr(ids, cid_list->id[i].value)) |
| 251 | goto Done; | 247 | return 0; |
| 252 | } | 248 | } |
| 253 | } | 249 | } |
| 254 | error = -ENOENT; | 250 | return -ENOENT; |
| 255 | |||
| 256 | Done: | ||
| 257 | if (buffer.pointer) | ||
| 258 | acpi_os_free(buffer.pointer); | ||
| 259 | return error; | ||
| 260 | } | 251 | } |
| 261 | 252 | ||
| 262 | static acpi_status | 253 | static acpi_status |
| @@ -441,10 +432,7 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) | |||
| 441 | islockable = device->flags.lockable; | 432 | islockable = device->flags.lockable; |
| 442 | handle = device->handle; | 433 | handle = device->handle; |
| 443 | 434 | ||
| 444 | if (type == ACPI_TYPE_PROCESSOR) | 435 | result = acpi_bus_trim(device, 1); |
| 445 | result = acpi_bus_trim(device, 0); | ||
| 446 | else | ||
| 447 | result = acpi_bus_trim(device, 1); | ||
| 448 | 436 | ||
| 449 | if (!result) | 437 | if (!result) |
| 450 | result = acpi_eject_operation(handle, islockable); | 438 | result = acpi_eject_operation(handle, islockable); |
| @@ -471,7 +459,6 @@ static int acpi_bus_get_perf_flags(struct acpi_device *device) | |||
| 471 | -------------------------------------------------------------------------- */ | 459 | -------------------------------------------------------------------------- */ |
| 472 | 460 | ||
| 473 | static LIST_HEAD(acpi_bus_drivers); | 461 | static LIST_HEAD(acpi_bus_drivers); |
| 474 | static DECLARE_MUTEX(acpi_bus_drivers_lock); | ||
| 475 | 462 | ||
| 476 | /** | 463 | /** |
| 477 | * acpi_bus_match - match device IDs to driver's supported IDs | 464 | * acpi_bus_match - match device IDs to driver's supported IDs |
| @@ -548,10 +535,9 @@ static int acpi_start_single_object(struct acpi_device *device) | |||
| 548 | return_VALUE(result); | 535 | return_VALUE(result); |
| 549 | } | 536 | } |
| 550 | 537 | ||
| 551 | static int acpi_driver_attach(struct acpi_driver *drv) | 538 | static void acpi_driver_attach(struct acpi_driver *drv) |
| 552 | { | 539 | { |
| 553 | struct list_head *node, *next; | 540 | struct list_head *node, *next; |
| 554 | int count = 0; | ||
| 555 | 541 | ||
| 556 | ACPI_FUNCTION_TRACE("acpi_driver_attach"); | 542 | ACPI_FUNCTION_TRACE("acpi_driver_attach"); |
| 557 | 543 | ||
| @@ -568,7 +554,6 @@ static int acpi_driver_attach(struct acpi_driver *drv) | |||
| 568 | if (!acpi_bus_driver_init(dev, drv)) { | 554 | if (!acpi_bus_driver_init(dev, drv)) { |
| 569 | acpi_start_single_object(dev); | 555 | acpi_start_single_object(dev); |
| 570 | atomic_inc(&drv->references); | 556 | atomic_inc(&drv->references); |
| 571 | count++; | ||
| 572 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 557 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 573 | "Found driver [%s] for device [%s]\n", | 558 | "Found driver [%s] for device [%s]\n", |
| 574 | drv->name, dev->pnp.bus_id)); | 559 | drv->name, dev->pnp.bus_id)); |
| @@ -577,10 +562,9 @@ static int acpi_driver_attach(struct acpi_driver *drv) | |||
| 577 | spin_lock(&acpi_device_lock); | 562 | spin_lock(&acpi_device_lock); |
| 578 | } | 563 | } |
| 579 | spin_unlock(&acpi_device_lock); | 564 | spin_unlock(&acpi_device_lock); |
| 580 | return_VALUE(count); | ||
| 581 | } | 565 | } |
| 582 | 566 | ||
| 583 | static int acpi_driver_detach(struct acpi_driver *drv) | 567 | static void acpi_driver_detach(struct acpi_driver *drv) |
| 584 | { | 568 | { |
| 585 | struct list_head *node, *next; | 569 | struct list_head *node, *next; |
| 586 | 570 | ||
| @@ -602,7 +586,6 @@ static int acpi_driver_detach(struct acpi_driver *drv) | |||
| 602 | } | 586 | } |
| 603 | } | 587 | } |
| 604 | spin_unlock(&acpi_device_lock); | 588 | spin_unlock(&acpi_device_lock); |
| 605 | return_VALUE(0); | ||
| 606 | } | 589 | } |
| 607 | 590 | ||
| 608 | /** | 591 | /** |
| @@ -610,28 +593,22 @@ static int acpi_driver_detach(struct acpi_driver *drv) | |||
| 610 | * @driver: driver being registered | 593 | * @driver: driver being registered |
| 611 | * | 594 | * |
| 612 | * Registers a driver with the ACPI bus. Searches the namespace for all | 595 | * Registers a driver with the ACPI bus. Searches the namespace for all |
| 613 | * devices that match the driver's criteria and binds. Returns the | 596 | * devices that match the driver's criteria and binds. Returns zero for |
| 614 | * number of devices that were claimed by the driver, or a negative | 597 | * success or a negative error status for failure. |
| 615 | * error status for failure. | ||
| 616 | */ | 598 | */ |
| 617 | int acpi_bus_register_driver(struct acpi_driver *driver) | 599 | int acpi_bus_register_driver(struct acpi_driver *driver) |
| 618 | { | 600 | { |
| 619 | int count; | ||
| 620 | |||
| 621 | ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); | 601 | ACPI_FUNCTION_TRACE("acpi_bus_register_driver"); |
| 622 | 602 | ||
| 623 | if (acpi_disabled) | 603 | if (acpi_disabled) |
| 624 | return_VALUE(-ENODEV); | 604 | return_VALUE(-ENODEV); |
| 625 | 605 | ||
| 626 | if (!driver) | ||
| 627 | return_VALUE(-EINVAL); | ||
| 628 | |||
| 629 | spin_lock(&acpi_device_lock); | 606 | spin_lock(&acpi_device_lock); |
| 630 | list_add_tail(&driver->node, &acpi_bus_drivers); | 607 | list_add_tail(&driver->node, &acpi_bus_drivers); |
| 631 | spin_unlock(&acpi_device_lock); | 608 | spin_unlock(&acpi_device_lock); |
| 632 | count = acpi_driver_attach(driver); | 609 | acpi_driver_attach(driver); |
| 633 | 610 | ||
| 634 | return_VALUE(count); | 611 | return_VALUE(0); |
| 635 | } | 612 | } |
| 636 | 613 | ||
| 637 | EXPORT_SYMBOL(acpi_bus_register_driver); | 614 | EXPORT_SYMBOL(acpi_bus_register_driver); |
| @@ -643,23 +620,16 @@ EXPORT_SYMBOL(acpi_bus_register_driver); | |||
| 643 | * Unregisters a driver with the ACPI bus. Searches the namespace for all | 620 | * Unregisters a driver with the ACPI bus. Searches the namespace for all |
| 644 | * devices that match the driver's criteria and unbinds. | 621 | * devices that match the driver's criteria and unbinds. |
| 645 | */ | 622 | */ |
| 646 | int acpi_bus_unregister_driver(struct acpi_driver *driver) | 623 | void acpi_bus_unregister_driver(struct acpi_driver *driver) |
| 647 | { | 624 | { |
| 648 | int error = 0; | 625 | acpi_driver_detach(driver); |
| 649 | 626 | ||
| 650 | ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver"); | 627 | if (!atomic_read(&driver->references)) { |
| 651 | 628 | spin_lock(&acpi_device_lock); | |
| 652 | if (driver) { | 629 | list_del_init(&driver->node); |
| 653 | acpi_driver_detach(driver); | 630 | spin_unlock(&acpi_device_lock); |
| 654 | 631 | } | |
| 655 | if (!atomic_read(&driver->references)) { | 632 | return; |
| 656 | spin_lock(&acpi_device_lock); | ||
| 657 | list_del_init(&driver->node); | ||
| 658 | spin_unlock(&acpi_device_lock); | ||
| 659 | } | ||
| 660 | } else | ||
| 661 | error = -EINVAL; | ||
| 662 | return_VALUE(error); | ||
| 663 | } | 633 | } |
| 664 | 634 | ||
| 665 | EXPORT_SYMBOL(acpi_bus_unregister_driver); | 635 | EXPORT_SYMBOL(acpi_bus_unregister_driver); |
| @@ -1371,6 +1341,100 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) | |||
| 1371 | return_VALUE(result); | 1341 | return_VALUE(result); |
| 1372 | } | 1342 | } |
| 1373 | 1343 | ||
| 1344 | |||
| 1345 | static inline struct acpi_device * to_acpi_dev(struct device * dev) | ||
| 1346 | { | ||
| 1347 | return container_of(dev, struct acpi_device, dev); | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | |||
| 1351 | static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) | ||
| 1352 | { | ||
| 1353 | struct acpi_device * dev, * next; | ||
| 1354 | int result; | ||
| 1355 | |||
| 1356 | spin_lock(&acpi_device_lock); | ||
| 1357 | list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { | ||
| 1358 | if (dev->driver && dev->driver->ops.suspend) { | ||
| 1359 | spin_unlock(&acpi_device_lock); | ||
| 1360 | result = dev->driver->ops.suspend(dev, 0); | ||
| 1361 | if (result) { | ||
| 1362 | printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", | ||
| 1363 | acpi_device_name(dev), | ||
| 1364 | acpi_device_bid(dev), result); | ||
| 1365 | } | ||
| 1366 | spin_lock(&acpi_device_lock); | ||
| 1367 | } | ||
| 1368 | } | ||
| 1369 | spin_unlock(&acpi_device_lock); | ||
| 1370 | return 0; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | |||
| 1374 | static int acpi_device_suspend(struct device * dev, pm_message_t state) | ||
| 1375 | { | ||
| 1376 | struct acpi_device * acpi_dev = to_acpi_dev(dev); | ||
| 1377 | |||
| 1378 | /* | ||
| 1379 | * For now, we should only register 1 generic device - | ||
| 1380 | * the ACPI root device - and from there, we walk the | ||
| 1381 | * tree of ACPI devices to suspend each one using the | ||
| 1382 | * ACPI driver methods. | ||
| 1383 | */ | ||
| 1384 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||
| 1385 | root_suspend(acpi_dev, state); | ||
| 1386 | return 0; | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | |||
| 1390 | |||
| 1391 | static int root_resume(struct acpi_device * acpi_dev) | ||
| 1392 | { | ||
| 1393 | struct acpi_device * dev, * next; | ||
| 1394 | int result; | ||
| 1395 | |||
| 1396 | spin_lock(&acpi_device_lock); | ||
| 1397 | list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { | ||
| 1398 | if (dev->driver && dev->driver->ops.resume) { | ||
| 1399 | spin_unlock(&acpi_device_lock); | ||
| 1400 | result = dev->driver->ops.resume(dev, 0); | ||
| 1401 | if (result) { | ||
| 1402 | printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", | ||
| 1403 | acpi_device_name(dev), | ||
| 1404 | acpi_device_bid(dev), result); | ||
| 1405 | } | ||
| 1406 | spin_lock(&acpi_device_lock); | ||
| 1407 | } | ||
| 1408 | } | ||
| 1409 | spin_unlock(&acpi_device_lock); | ||
| 1410 | return 0; | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | |||
| 1414 | static int acpi_device_resume(struct device * dev) | ||
| 1415 | { | ||
| 1416 | struct acpi_device * acpi_dev = to_acpi_dev(dev); | ||
| 1417 | |||
| 1418 | /* | ||
| 1419 | * For now, we should only register 1 generic device - | ||
| 1420 | * the ACPI root device - and from there, we walk the | ||
| 1421 | * tree of ACPI devices to resume each one using the | ||
| 1422 | * ACPI driver methods. | ||
| 1423 | */ | ||
| 1424 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||
| 1425 | root_resume(acpi_dev); | ||
| 1426 | return 0; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | |||
| 1430 | struct bus_type acpi_bus_type = { | ||
| 1431 | .name = "acpi", | ||
| 1432 | .suspend = acpi_device_suspend, | ||
| 1433 | .resume = acpi_device_resume, | ||
| 1434 | }; | ||
| 1435 | |||
| 1436 | |||
| 1437 | |||
| 1374 | static int __init acpi_scan_init(void) | 1438 | static int __init acpi_scan_init(void) |
| 1375 | { | 1439 | { |
| 1376 | int result; | 1440 | int result; |
| @@ -1383,6 +1447,12 @@ static int __init acpi_scan_init(void) | |||
| 1383 | 1447 | ||
| 1384 | kset_register(&acpi_namespace_kset); | 1448 | kset_register(&acpi_namespace_kset); |
| 1385 | 1449 | ||
| 1450 | result = bus_register(&acpi_bus_type); | ||
| 1451 | if (result) { | ||
| 1452 | /* We don't want to quit even if we failed to add suspend/resume */ | ||
| 1453 | printk(KERN_ERR PREFIX "Could not register bus type\n"); | ||
| 1454 | } | ||
| 1455 | |||
| 1386 | /* | 1456 | /* |
| 1387 | * Create the root device in the bus's device tree | 1457 | * Create the root device in the bus's device tree |
| 1388 | */ | 1458 | */ |
| @@ -1392,6 +1462,16 @@ static int __init acpi_scan_init(void) | |||
| 1392 | goto Done; | 1462 | goto Done; |
| 1393 | 1463 | ||
| 1394 | result = acpi_start_single_object(acpi_root); | 1464 | result = acpi_start_single_object(acpi_root); |
| 1465 | if (result) | ||
| 1466 | goto Done; | ||
| 1467 | |||
| 1468 | acpi_root->dev.bus = &acpi_bus_type; | ||
| 1469 | snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name); | ||
| 1470 | result = device_register(&acpi_root->dev); | ||
| 1471 | if (result) { | ||
| 1472 | /* We don't want to quit even if we failed to add suspend/resume */ | ||
| 1473 | printk(KERN_ERR PREFIX "Could not register device\n"); | ||
| 1474 | } | ||
| 1395 | 1475 | ||
| 1396 | /* | 1476 | /* |
| 1397 | * Enumerate devices in the ACPI namespace. | 1477 | * Enumerate devices in the ACPI namespace. |
