]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
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 | |
5 | ||
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. | |
10 | ||
11 | Signed-off-by: Shaohua Li <shaohua.li@intel.com> | |
12 | Signed-off-by: Holger Macht <hmacht@suse.de> | |
13 | --- | |
14 | ||
15 | --- | |
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(-) | |
20 | ||
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 | |
24 | return 0; | |
25 | } | |
26 | ||
27 | +static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); | |
28 | +int register_acpi_bus_notifier(struct notifier_block *nb) | |
29 | +{ | |
30 | + return blocking_notifier_chain_register(&acpi_bus_notify_list, nb); | |
31 | +} | |
32 | +EXPORT_SYMBOL_GPL(register_acpi_bus_notifier); | |
33 | + | |
34 | +void unregister_acpi_bus_notifier(struct notifier_block *nb) | |
35 | +{ | |
36 | + blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb); | |
37 | +} | |
38 | +EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier); | |
39 | + | |
40 | /** | |
41 | * acpi_bus_notify | |
42 | * --------------- | |
43 | @@ -506,6 +519,8 @@ static void acpi_bus_notify(acpi_handle | |
44 | int result = 0; | |
45 | struct acpi_device *device = NULL; | |
46 | ||
47 | + blocking_notifier_call_chain(&acpi_bus_notify_list, | |
48 | + type, (void *)handle); | |
49 | ||
50 | if (acpi_bus_get_device(handle, &device)) | |
51 | return; | |
52 | --- a/drivers/acpi/dock.c | |
53 | +++ b/drivers/acpi/dock.c | |
54 | @@ -748,6 +748,28 @@ static void dock_notify(acpi_handle hand | |
55 | } | |
56 | } | |
57 | ||
58 | +static int acpi_dock_notifier_call(struct notifier_block *this, | |
59 | + unsigned long event, void *data) | |
60 | +{ | |
61 | + struct dock_station *dock_station; | |
62 | + acpi_handle handle = (acpi_handle)data; | |
63 | + | |
64 | + if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK | |
65 | + && event != ACPI_NOTIFY_EJECT_REQUEST) | |
66 | + return 0; | |
67 | + list_for_each_entry(dock_station, &dock_stations, sibiling) { | |
68 | + if (dock_station->handle == handle) { | |
69 | + dock_notify(handle, event, dock_station); | |
70 | + return 0 ; | |
71 | + } | |
72 | + } | |
73 | + return 0; | |
74 | +} | |
75 | + | |
76 | +static struct notifier_block dock_acpi_notifier = { | |
77 | + .notifier_call = acpi_dock_notifier_call, | |
78 | +}; | |
79 | + | |
80 | /** | |
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) | |
85 | { | |
86 | int ret; | |
87 | - acpi_status status; | |
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) | |
92 | } | |
93 | add_dock_dependent_device(dock_station, dd); | |
94 | ||
95 | - /* register for dock events */ | |
96 | - status = acpi_install_notify_handler(dock_station->handle, | |
97 | - ACPI_SYSTEM_NOTIFY, | |
98 | - dock_notify, dock_station); | |
99 | - | |
100 | - if (ACPI_FAILURE(status)) { | |
101 | - printk(KERN_ERR PREFIX "Error installing notify handler\n"); | |
102 | - ret = -ENODEV; | |
103 | - goto dock_add_err; | |
104 | - } | |
105 | - | |
106 | dock_station_count++; | |
107 | list_add(&dock_station->sibiling, &dock_stations); | |
108 | return 0; | |
109 | ||
110 | -dock_add_err: | |
111 | - kfree(dd); | |
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) | |
117 | { | |
118 | struct dock_dependent_device *dd, *tmp; | |
119 | - acpi_status status; | |
120 | struct platform_device *dock_device = dock_station->dock_device; | |
121 | ||
122 | if (!dock_station_count) | |
123 | @@ -999,13 +1006,6 @@ static int dock_remove(struct dock_stati | |
124 | list) | |
125 | kfree(dd); | |
126 | ||
127 | - /* remove dock notify handler */ | |
128 | - status = acpi_remove_notify_handler(dock_station->handle, | |
129 | - ACPI_SYSTEM_NOTIFY, | |
130 | - dock_notify); | |
131 | - if (ACPI_FAILURE(status)) | |
132 | - printk(KERN_ERR "Error removing notify handler\n"); | |
133 | - | |
134 | /* cleanup sysfs */ | |
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) | |
138 | return 0; | |
139 | } | |
140 | ||
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); | |
144 | return 0; | |
145 | @@ -1076,6 +1077,7 @@ static void __exit dock_exit(void) | |
146 | { | |
147 | struct dock_station *dock_station; | |
148 | ||
149 | + unregister_acpi_bus_notifier(&dock_acpi_notifier); | |
150 | list_for_each_entry(dock_station, &dock_stations, sibiling) | |
151 | dock_remove(dock_station); | |
152 | } | |
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 *); | |
159 | + | |
160 | +extern int register_acpi_bus_notifier(struct notifier_block *nb); | |
161 | +extern void unregister_acpi_bus_notifier(struct notifier_block *nb); | |
162 | /* | |
163 | * External Functions | |
164 | */ |