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. |