1 From: Shaohua Li <shaohua.li@intel.com>
2 Subject: Fix duplicate notification handler register
3 Patch-mainline: submitted 2008-08-28
4 References: fate#304731,bnc#401740
6 Battery driver already registers notification handler. To avoid register
7 notification handler again, the patch introduced a notifier chain in
8 global system notifier handler and use it in dock driver, so we can
9 avoid register notification handler.
11 Signed-off-by: Shaohua Li <shaohua.li@intel.com>
12 Signed-off-by: Holger Macht <hmacht@suse.de>
16 drivers/acpi/bus.c | 15 +++++++++++++++
17 drivers/acpi/dock.c | 46 ++++++++++++++++++++++++----------------------
18 include/acpi/acpi_bus.h | 3 +++
19 3 files changed, 42 insertions(+), 22 deletions(-)
21 --- a/drivers/acpi/bus.c
22 +++ b/drivers/acpi/bus.c
23 @@ -496,6 +496,19 @@ static int acpi_bus_check_scope(struct a
27 +static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
28 +int register_acpi_bus_notifier(struct notifier_block *nb)
30 + return blocking_notifier_chain_register(&acpi_bus_notify_list, nb);
32 +EXPORT_SYMBOL_GPL(register_acpi_bus_notifier);
34 +void unregister_acpi_bus_notifier(struct notifier_block *nb)
36 + blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb);
38 +EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier);
43 @@ -506,6 +519,8 @@ static void acpi_bus_notify(acpi_handle
45 struct acpi_device *device = NULL;
47 + blocking_notifier_call_chain(&acpi_bus_notify_list,
48 + type, (void *)handle);
50 if (acpi_bus_get_device(handle, &device))
52 --- a/drivers/acpi/dock.c
53 +++ b/drivers/acpi/dock.c
54 @@ -748,6 +748,28 @@ static void dock_notify(acpi_handle hand
58 +static int acpi_dock_notifier_call(struct notifier_block *this,
59 + unsigned long event, void *data)
61 + struct dock_station *dock_station;
62 + acpi_handle handle = (acpi_handle)data;
64 + if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
65 + && event != ACPI_NOTIFY_EJECT_REQUEST)
67 + list_for_each_entry(dock_station, &dock_stations, sibiling) {
68 + if (dock_station->handle == handle) {
69 + dock_notify(handle, event, dock_station);
76 +static struct notifier_block dock_acpi_notifier = {
77 + .notifier_call = acpi_dock_notifier_call,
81 * find_dock_devices - find devices on the dock station
82 * @handle: the handle of the device we are examining
83 @@ -859,7 +881,6 @@ static DEVICE_ATTR(uid, S_IRUGO, show_do
84 static int dock_add(acpi_handle handle)
88 struct dock_dependent_device *dd;
89 struct dock_station *dock_station;
90 struct platform_device *dock_device;
91 @@ -954,23 +975,10 @@ static int dock_add(acpi_handle handle)
93 add_dock_dependent_device(dock_station, dd);
95 - /* register for dock events */
96 - status = acpi_install_notify_handler(dock_station->handle,
98 - dock_notify, dock_station);
100 - if (ACPI_FAILURE(status)) {
101 - printk(KERN_ERR PREFIX "Error installing notify handler\n");
106 dock_station_count++;
107 list_add(&dock_station->sibiling, &dock_stations);
112 dock_add_err_unregister:
113 device_remove_file(&dock_device->dev, &dev_attr_docked);
114 device_remove_file(&dock_device->dev, &dev_attr_undock);
115 @@ -988,7 +996,6 @@ dock_add_err_unregister:
116 static int dock_remove(struct dock_station *dock_station)
118 struct dock_dependent_device *dd, *tmp;
119 - acpi_status status;
120 struct platform_device *dock_device = dock_station->dock_device;
122 if (!dock_station_count)
123 @@ -999,13 +1006,6 @@ static int dock_remove(struct dock_stati
127 - /* remove dock notify handler */
128 - status = acpi_remove_notify_handler(dock_station->handle,
129 - ACPI_SYSTEM_NOTIFY,
131 - if (ACPI_FAILURE(status))
132 - printk(KERN_ERR "Error removing notify handler\n");
135 device_remove_file(&dock_device->dev, &dev_attr_docked);
136 device_remove_file(&dock_device->dev, &dev_attr_undock);
137 @@ -1067,6 +1067,7 @@ static int __init dock_init(void)
141 + register_acpi_bus_notifier(&dock_acpi_notifier);
142 printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
143 ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
145 @@ -1076,6 +1077,7 @@ static void __exit dock_exit(void)
147 struct dock_station *dock_station;
149 + unregister_acpi_bus_notifier(&dock_acpi_notifier);
150 list_for_each_entry(dock_station, &dock_stations, sibiling)
151 dock_remove(dock_station);
153 --- a/include/acpi/acpi_bus.h
154 +++ b/include/acpi/acpi_bus.h
155 @@ -327,6 +327,9 @@ int acpi_bus_get_private_data(acpi_handl
156 extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
157 extern int register_acpi_notifier(struct notifier_block *);
158 extern int unregister_acpi_notifier(struct notifier_block *);
160 +extern int register_acpi_bus_notifier(struct notifier_block *nb);
161 +extern void unregister_acpi_bus_notifier(struct notifier_block *nb);