diff options
author | Patrick Mochel <mochel@linux.intel.com> | 2006-12-07 07:56:31 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-12-15 23:38:34 -0500 |
commit | 1890a97ab3f66d1e99768439f8067608b9b97fe3 (patch) | |
tree | ae9cc1f49e51e1fad5305caceac72b7f1dc584af /drivers/acpi | |
parent | 5d9464a46918ced087c351a10f38cee95725f85b (diff) |
ACPI: change registration interface to follow driver model
ACPI device/driver registration Interfaces are modified
to follow Linux driver model.
Signed-off-by: Li Shaohua <shaohua.li@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/scan.c | 175 |
1 files changed, 29 insertions, 146 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 464746257d8e..b616e17de522 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -25,7 +25,7 @@ DEFINE_SPINLOCK(acpi_device_lock); | |||
25 | LIST_HEAD(acpi_wakeup_device_list); | 25 | LIST_HEAD(acpi_wakeup_device_list); |
26 | 26 | ||
27 | 27 | ||
28 | static void acpi_device_release(struct kobject *kobj) | 28 | static void acpi_device_release_legacy(struct kobject *kobj) |
29 | { | 29 | { |
30 | struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj); | 30 | struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj); |
31 | kfree(dev->pnp.cid_list); | 31 | kfree(dev->pnp.cid_list); |
@@ -75,7 +75,7 @@ static struct sysfs_ops acpi_device_sysfs_ops = { | |||
75 | 75 | ||
76 | static struct kobj_type ktype_acpi_ns = { | 76 | static struct kobj_type ktype_acpi_ns = { |
77 | .sysfs_ops = &acpi_device_sysfs_ops, | 77 | .sysfs_ops = &acpi_device_sysfs_ops, |
78 | .release = acpi_device_release, | 78 | .release = acpi_device_release_legacy, |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static int namespace_uevent(struct kset *kset, struct kobject *kobj, | 81 | static int namespace_uevent(struct kset *kset, struct kobject *kobj, |
@@ -222,6 +222,14 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) | |||
222 | /* -------------------------------------------------------------------------- | 222 | /* -------------------------------------------------------------------------- |
223 | ACPI Bus operations | 223 | ACPI Bus operations |
224 | -------------------------------------------------------------------------- */ | 224 | -------------------------------------------------------------------------- */ |
225 | static void acpi_device_release(struct device *dev) | ||
226 | { | ||
227 | struct acpi_device *acpi_dev = to_acpi_device(dev); | ||
228 | |||
229 | kfree(acpi_dev->pnp.cid_list); | ||
230 | kfree(acpi_dev); | ||
231 | } | ||
232 | |||
225 | static int acpi_device_suspend(struct device *dev, pm_message_t state) | 233 | static int acpi_device_suspend(struct device *dev, pm_message_t state) |
226 | { | 234 | { |
227 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 235 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
@@ -377,6 +385,14 @@ static void acpi_device_register(struct acpi_device *device, | |||
377 | printk(KERN_WARNING "%s: kobject_register error: %d\n", | 385 | printk(KERN_WARNING "%s: kobject_register error: %d\n", |
378 | __FUNCTION__, err); | 386 | __FUNCTION__, err); |
379 | create_sysfs_device_files(device); | 387 | create_sysfs_device_files(device); |
388 | |||
389 | if (device->parent) | ||
390 | device->dev.parent = &parent->dev; | ||
391 | device->dev.bus = &acpi_bus_type; | ||
392 | device_initialize(&device->dev); | ||
393 | sprintf(device->dev.bus_id, "%s", device->pnp.bus_id); | ||
394 | device->dev.release = &acpi_device_release; | ||
395 | device_add(&device->dev); | ||
380 | } | 396 | } |
381 | 397 | ||
382 | static void acpi_device_unregister(struct acpi_device *device, int type) | 398 | static void acpi_device_unregister(struct acpi_device *device, int type) |
@@ -395,20 +411,20 @@ static void acpi_device_unregister(struct acpi_device *device, int type) | |||
395 | acpi_detach_data(device->handle, acpi_bus_data_handler); | 411 | acpi_detach_data(device->handle, acpi_bus_data_handler); |
396 | remove_sysfs_device_files(device); | 412 | remove_sysfs_device_files(device); |
397 | kobject_unregister(&device->kobj); | 413 | kobject_unregister(&device->kobj); |
414 | |||
415 | device_unregister(&device->dev); | ||
398 | } | 416 | } |
399 | 417 | ||
400 | /* -------------------------------------------------------------------------- | 418 | /* -------------------------------------------------------------------------- |
401 | Driver Management | 419 | Driver Management |
402 | -------------------------------------------------------------------------- */ | 420 | -------------------------------------------------------------------------- */ |
403 | static LIST_HEAD(acpi_bus_drivers); | ||
404 | |||
405 | /** | 421 | /** |
406 | * acpi_bus_driver_init - add a device to a driver | 422 | * acpi_bus_driver_init - add a device to a driver |
407 | * @device: the device to add and initialize | 423 | * @device: the device to add and initialize |
408 | * @driver: driver for the device | 424 | * @driver: driver for the device |
409 | * | 425 | * |
410 | * Used to initialize a device via its device driver. Called whenever a | 426 | * Used to initialize a device via its device driver. Called whenever a |
411 | * driver is bound to a device. Invokes the driver's add() and start() ops. | 427 | * driver is bound to a device. Invokes the driver's add() ops. |
412 | */ | 428 | */ |
413 | static int | 429 | static int |
414 | acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) | 430 | acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver) |
@@ -459,57 +475,6 @@ static int acpi_start_single_object(struct acpi_device *device) | |||
459 | return result; | 475 | return result; |
460 | } | 476 | } |
461 | 477 | ||
462 | static void acpi_driver_attach(struct acpi_driver *drv) | ||
463 | { | ||
464 | struct list_head *node, *next; | ||
465 | |||
466 | |||
467 | spin_lock(&acpi_device_lock); | ||
468 | list_for_each_safe(node, next, &acpi_device_list) { | ||
469 | struct acpi_device *dev = | ||
470 | container_of(node, struct acpi_device, g_list); | ||
471 | |||
472 | if (dev->driver || !dev->status.present) | ||
473 | continue; | ||
474 | spin_unlock(&acpi_device_lock); | ||
475 | |||
476 | if (!acpi_bus_match(&(dev->dev), &(drv->drv))) { | ||
477 | if (!acpi_bus_driver_init(dev, drv)) { | ||
478 | acpi_start_single_object(dev); | ||
479 | atomic_inc(&drv->references); | ||
480 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
481 | "Found driver [%s] for device [%s]\n", | ||
482 | drv->name, dev->pnp.bus_id)); | ||
483 | } | ||
484 | } | ||
485 | spin_lock(&acpi_device_lock); | ||
486 | } | ||
487 | spin_unlock(&acpi_device_lock); | ||
488 | } | ||
489 | |||
490 | static void acpi_driver_detach(struct acpi_driver *drv) | ||
491 | { | ||
492 | struct list_head *node, *next; | ||
493 | |||
494 | |||
495 | spin_lock(&acpi_device_lock); | ||
496 | list_for_each_safe(node, next, &acpi_device_list) { | ||
497 | struct acpi_device *dev = | ||
498 | container_of(node, struct acpi_device, g_list); | ||
499 | |||
500 | if (dev->driver == drv) { | ||
501 | spin_unlock(&acpi_device_lock); | ||
502 | if (drv->ops.remove) | ||
503 | drv->ops.remove(dev, ACPI_BUS_REMOVAL_NORMAL); | ||
504 | spin_lock(&acpi_device_lock); | ||
505 | dev->driver = NULL; | ||
506 | dev->driver_data = NULL; | ||
507 | atomic_dec(&drv->references); | ||
508 | } | ||
509 | } | ||
510 | spin_unlock(&acpi_device_lock); | ||
511 | } | ||
512 | |||
513 | /** | 478 | /** |
514 | * acpi_bus_register_driver - register a driver with the ACPI bus | 479 | * acpi_bus_register_driver - register a driver with the ACPI bus |
515 | * @driver: driver being registered | 480 | * @driver: driver being registered |
@@ -520,16 +485,16 @@ static void acpi_driver_detach(struct acpi_driver *drv) | |||
520 | */ | 485 | */ |
521 | int acpi_bus_register_driver(struct acpi_driver *driver) | 486 | int acpi_bus_register_driver(struct acpi_driver *driver) |
522 | { | 487 | { |
488 | int ret; | ||
523 | 489 | ||
524 | if (acpi_disabled) | 490 | if (acpi_disabled) |
525 | return -ENODEV; | 491 | return -ENODEV; |
492 | driver->drv.name = driver->name; | ||
493 | driver->drv.bus = &acpi_bus_type; | ||
494 | driver->drv.owner = driver->owner; | ||
526 | 495 | ||
527 | spin_lock(&acpi_device_lock); | 496 | ret = driver_register(&driver->drv); |
528 | list_add_tail(&driver->node, &acpi_bus_drivers); | 497 | return ret; |
529 | spin_unlock(&acpi_device_lock); | ||
530 | acpi_driver_attach(driver); | ||
531 | |||
532 | return 0; | ||
533 | } | 498 | } |
534 | 499 | ||
535 | EXPORT_SYMBOL(acpi_bus_register_driver); | 500 | EXPORT_SYMBOL(acpi_bus_register_driver); |
@@ -543,52 +508,11 @@ EXPORT_SYMBOL(acpi_bus_register_driver); | |||
543 | */ | 508 | */ |
544 | void acpi_bus_unregister_driver(struct acpi_driver *driver) | 509 | void acpi_bus_unregister_driver(struct acpi_driver *driver) |
545 | { | 510 | { |
546 | acpi_driver_detach(driver); | 511 | driver_unregister(&driver->drv); |
547 | |||
548 | if (!atomic_read(&driver->references)) { | ||
549 | spin_lock(&acpi_device_lock); | ||
550 | list_del_init(&driver->node); | ||
551 | spin_unlock(&acpi_device_lock); | ||
552 | } | ||
553 | return; | ||
554 | } | 512 | } |
555 | 513 | ||
556 | EXPORT_SYMBOL(acpi_bus_unregister_driver); | 514 | EXPORT_SYMBOL(acpi_bus_unregister_driver); |
557 | 515 | ||
558 | /** | ||
559 | * acpi_bus_find_driver - check if there is a driver installed for the device | ||
560 | * @device: device that we are trying to find a supporting driver for | ||
561 | * | ||
562 | * Parses the list of registered drivers looking for a driver applicable for | ||
563 | * the specified device. | ||
564 | */ | ||
565 | static int acpi_bus_find_driver(struct acpi_device *device) | ||
566 | { | ||
567 | int result = 0; | ||
568 | struct list_head *node, *next; | ||
569 | |||
570 | |||
571 | spin_lock(&acpi_device_lock); | ||
572 | list_for_each_safe(node, next, &acpi_bus_drivers) { | ||
573 | struct acpi_driver *driver = | ||
574 | container_of(node, struct acpi_driver, node); | ||
575 | |||
576 | atomic_inc(&driver->references); | ||
577 | spin_unlock(&acpi_device_lock); | ||
578 | if (!acpi_bus_match(&(device->dev), &(driver->drv))) { | ||
579 | result = acpi_bus_driver_init(device, driver); | ||
580 | if (!result) | ||
581 | goto Done; | ||
582 | } | ||
583 | atomic_dec(&driver->references); | ||
584 | spin_lock(&acpi_device_lock); | ||
585 | } | ||
586 | spin_unlock(&acpi_device_lock); | ||
587 | |||
588 | Done: | ||
589 | return result; | ||
590 | } | ||
591 | |||
592 | /* -------------------------------------------------------------------------- | 516 | /* -------------------------------------------------------------------------- |
593 | Device Enumeration | 517 | Device Enumeration |
594 | -------------------------------------------------------------------------- */ | 518 | -------------------------------------------------------------------------- */ |
@@ -1033,32 +957,10 @@ static void acpi_device_get_debug_info(struct acpi_device *device, | |||
1033 | 957 | ||
1034 | static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) | 958 | static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) |
1035 | { | 959 | { |
1036 | int result = 0; | ||
1037 | struct acpi_driver *driver; | ||
1038 | |||
1039 | |||
1040 | if (!dev) | 960 | if (!dev) |
1041 | return -EINVAL; | 961 | return -EINVAL; |
1042 | 962 | ||
1043 | driver = dev->driver; | 963 | device_release_driver(&dev->dev); |
1044 | |||
1045 | if ((driver) && (driver->ops.remove)) { | ||
1046 | |||
1047 | if (driver->ops.stop) { | ||
1048 | result = driver->ops.stop(dev, ACPI_BUS_REMOVAL_EJECT); | ||
1049 | if (result) | ||
1050 | return result; | ||
1051 | } | ||
1052 | |||
1053 | result = dev->driver->ops.remove(dev, ACPI_BUS_REMOVAL_EJECT); | ||
1054 | if (result) { | ||
1055 | return result; | ||
1056 | } | ||
1057 | |||
1058 | atomic_dec(&dev->driver->references); | ||
1059 | dev->driver = NULL; | ||
1060 | acpi_driver_data(dev) = NULL; | ||
1061 | } | ||
1062 | 964 | ||
1063 | if (!rmdevice) | 965 | if (!rmdevice) |
1064 | return 0; | 966 | return 0; |
@@ -1193,17 +1095,6 @@ acpi_add_single_object(struct acpi_device **child, | |||
1193 | device->parent->ops.bind(device); | 1095 | device->parent->ops.bind(device); |
1194 | } | 1096 | } |
1195 | 1097 | ||
1196 | /* | ||
1197 | * Locate & Attach Driver | ||
1198 | * ---------------------- | ||
1199 | * If there's a hardware id (_HID) or compatible ids (_CID) we check | ||
1200 | * to see if there's a driver installed for this kind of device. Note | ||
1201 | * that drivers can install before or after a device is enumerated. | ||
1202 | * | ||
1203 | * TBD: Assumes LDM provides driver hot-plug capability. | ||
1204 | */ | ||
1205 | acpi_bus_find_driver(device); | ||
1206 | |||
1207 | end: | 1098 | end: |
1208 | if (!result) | 1099 | if (!result) |
1209 | *child = device; | 1100 | *child = device; |
@@ -1484,14 +1375,6 @@ static int __init acpi_scan_init(void) | |||
1484 | if (result) | 1375 | if (result) |
1485 | goto Done; | 1376 | goto Done; |
1486 | 1377 | ||
1487 | acpi_root->dev.bus = &acpi_bus_type; | ||
1488 | snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name); | ||
1489 | result = device_register(&acpi_root->dev); | ||
1490 | if (result) { | ||
1491 | /* We don't want to quit even if we failed to add suspend/resume */ | ||
1492 | printk(KERN_ERR PREFIX "Could not register device\n"); | ||
1493 | } | ||
1494 | |||
1495 | /* | 1378 | /* |
1496 | * Enumerate devices in the ACPI namespace. | 1379 | * Enumerate devices in the ACPI namespace. |
1497 | */ | 1380 | */ |