diff options
author | Shaohua Li <shaohua.li@intel.com> | 2008-08-27 22:04:29 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-09-23 23:04:43 -0400 |
commit | 6bd00a61ab63d4ceb635ae0316353c11c900b8d8 (patch) | |
tree | 249e417279df1448f1ad43c135c22990b5dde2cb | |
parent | db350b084dc2cf816288643861ce07b0562dd723 (diff) |
ACPI: introduce notifier change to avoid duplicates
The battery driver already registers notification handler.
To avoid registering notification handler again,
introduce a notifier chain in global system notifier handler
and use it in dock driver.
Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/bus.c | 15 | ||||
-rw-r--r-- | drivers/acpi/dock.c | 46 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 3 |
3 files changed, 42 insertions, 22 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index ccae305ee55d..0dc44945725e 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -496,6 +496,19 @@ static int acpi_bus_check_scope(struct acpi_device *device) | |||
496 | return 0; | 496 | return 0; |
497 | } | 497 | } |
498 | 498 | ||
499 | static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); | ||
500 | int register_acpi_bus_notifier(struct notifier_block *nb) | ||
501 | { | ||
502 | return blocking_notifier_chain_register(&acpi_bus_notify_list, nb); | ||
503 | } | ||
504 | EXPORT_SYMBOL_GPL(register_acpi_bus_notifier); | ||
505 | |||
506 | void unregister_acpi_bus_notifier(struct notifier_block *nb) | ||
507 | { | ||
508 | blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb); | ||
509 | } | ||
510 | EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier); | ||
511 | |||
499 | /** | 512 | /** |
500 | * acpi_bus_notify | 513 | * acpi_bus_notify |
501 | * --------------- | 514 | * --------------- |
@@ -506,6 +519,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) | |||
506 | int result = 0; | 519 | int result = 0; |
507 | struct acpi_device *device = NULL; | 520 | struct acpi_device *device = NULL; |
508 | 521 | ||
522 | blocking_notifier_call_chain(&acpi_bus_notify_list, | ||
523 | type, (void *)handle); | ||
509 | 524 | ||
510 | if (acpi_bus_get_device(handle, &device)) | 525 | if (acpi_bus_get_device(handle, &device)) |
511 | return; | 526 | return; |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 799a0fdbb62d..2563bc62987d 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -748,6 +748,28 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) | |||
748 | } | 748 | } |
749 | } | 749 | } |
750 | 750 | ||
751 | static int acpi_dock_notifier_call(struct notifier_block *this, | ||
752 | unsigned long event, void *data) | ||
753 | { | ||
754 | struct dock_station *dock_station; | ||
755 | acpi_handle handle = (acpi_handle)data; | ||
756 | |||
757 | if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK | ||
758 | && event != ACPI_NOTIFY_EJECT_REQUEST) | ||
759 | return 0; | ||
760 | list_for_each_entry(dock_station, &dock_stations, sibiling) { | ||
761 | if (dock_station->handle == handle) { | ||
762 | dock_notify(handle, event, dock_station); | ||
763 | return 0 ; | ||
764 | } | ||
765 | } | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | static struct notifier_block dock_acpi_notifier = { | ||
770 | .notifier_call = acpi_dock_notifier_call, | ||
771 | }; | ||
772 | |||
751 | /** | 773 | /** |
752 | * find_dock_devices - find devices on the dock station | 774 | * find_dock_devices - find devices on the dock station |
753 | * @handle: the handle of the device we are examining | 775 | * @handle: the handle of the device we are examining |
@@ -861,7 +883,6 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); | |||
861 | static int dock_add(acpi_handle handle) | 883 | static int dock_add(acpi_handle handle) |
862 | { | 884 | { |
863 | int ret; | 885 | int ret; |
864 | acpi_status status; | ||
865 | struct dock_dependent_device *dd; | 886 | struct dock_dependent_device *dd; |
866 | struct dock_station *dock_station; | 887 | struct dock_station *dock_station; |
867 | struct platform_device *dock_device; | 888 | struct platform_device *dock_device; |
@@ -956,23 +977,10 @@ static int dock_add(acpi_handle handle) | |||
956 | } | 977 | } |
957 | add_dock_dependent_device(dock_station, dd); | 978 | add_dock_dependent_device(dock_station, dd); |
958 | 979 | ||
959 | /* register for dock events */ | ||
960 | status = acpi_install_notify_handler(dock_station->handle, | ||
961 | ACPI_SYSTEM_NOTIFY, | ||
962 | dock_notify, dock_station); | ||
963 | |||
964 | if (ACPI_FAILURE(status)) { | ||
965 | printk(KERN_ERR PREFIX "Error installing notify handler\n"); | ||
966 | ret = -ENODEV; | ||
967 | goto dock_add_err; | ||
968 | } | ||
969 | |||
970 | dock_station_count++; | 980 | dock_station_count++; |
971 | list_add(&dock_station->sibiling, &dock_stations); | 981 | list_add(&dock_station->sibiling, &dock_stations); |
972 | return 0; | 982 | return 0; |
973 | 983 | ||
974 | dock_add_err: | ||
975 | kfree(dd); | ||
976 | dock_add_err_unregister: | 984 | dock_add_err_unregister: |
977 | device_remove_file(&dock_device->dev, &dev_attr_docked); | 985 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
978 | device_remove_file(&dock_device->dev, &dev_attr_undock); | 986 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
@@ -990,7 +998,6 @@ dock_add_err_unregister: | |||
990 | static int dock_remove(struct dock_station *dock_station) | 998 | static int dock_remove(struct dock_station *dock_station) |
991 | { | 999 | { |
992 | struct dock_dependent_device *dd, *tmp; | 1000 | struct dock_dependent_device *dd, *tmp; |
993 | acpi_status status; | ||
994 | struct platform_device *dock_device = dock_station->dock_device; | 1001 | struct platform_device *dock_device = dock_station->dock_device; |
995 | 1002 | ||
996 | if (!dock_station_count) | 1003 | if (!dock_station_count) |
@@ -1001,13 +1008,6 @@ static int dock_remove(struct dock_station *dock_station) | |||
1001 | list) | 1008 | list) |
1002 | kfree(dd); | 1009 | kfree(dd); |
1003 | 1010 | ||
1004 | /* remove dock notify handler */ | ||
1005 | status = acpi_remove_notify_handler(dock_station->handle, | ||
1006 | ACPI_SYSTEM_NOTIFY, | ||
1007 | dock_notify); | ||
1008 | if (ACPI_FAILURE(status)) | ||
1009 | printk(KERN_ERR "Error removing notify handler\n"); | ||
1010 | |||
1011 | /* cleanup sysfs */ | 1011 | /* cleanup sysfs */ |
1012 | device_remove_file(&dock_device->dev, &dev_attr_docked); | 1012 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
1013 | device_remove_file(&dock_device->dev, &dev_attr_undock); | 1013 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
@@ -1069,6 +1069,7 @@ static int __init dock_init(void) | |||
1069 | return 0; | 1069 | return 0; |
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | register_acpi_bus_notifier(&dock_acpi_notifier); | ||
1072 | printk(KERN_INFO PREFIX "%s: %d docks/bays found\n", | 1073 | printk(KERN_INFO PREFIX "%s: %d docks/bays found\n", |
1073 | ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); | 1074 | ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); |
1074 | return 0; | 1075 | return 0; |
@@ -1078,6 +1079,7 @@ static void __exit dock_exit(void) | |||
1078 | { | 1079 | { |
1079 | struct dock_station *dock_station; | 1080 | struct dock_station *dock_station; |
1080 | 1081 | ||
1082 | unregister_acpi_bus_notifier(&dock_acpi_notifier); | ||
1081 | list_for_each_entry(dock_station, &dock_stations, sibiling) | 1083 | list_for_each_entry(dock_station, &dock_stations, sibiling) |
1082 | dock_remove(dock_station); | 1084 | dock_remove(dock_station); |
1083 | } | 1085 | } |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index a5ac0bc7f52e..f74f882609f8 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -327,6 +327,9 @@ int acpi_bus_get_private_data(acpi_handle, void **); | |||
327 | extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); | 327 | extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); |
328 | extern int register_acpi_notifier(struct notifier_block *); | 328 | extern int register_acpi_notifier(struct notifier_block *); |
329 | extern int unregister_acpi_notifier(struct notifier_block *); | 329 | extern int unregister_acpi_notifier(struct notifier_block *); |
330 | |||
331 | extern int register_acpi_bus_notifier(struct notifier_block *nb); | ||
332 | extern void unregister_acpi_bus_notifier(struct notifier_block *nb); | ||
330 | /* | 333 | /* |
331 | * External Functions | 334 | * External Functions |
332 | */ | 335 | */ |