diff options
Diffstat (limited to 'drivers/acpi/acpica/evxface.c')
-rw-r--r-- | drivers/acpi/acpica/evxface.c | 474 |
1 files changed, 162 insertions, 312 deletions
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 44bef5744ebb..7587eb6c9584 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c | |||
@@ -54,86 +54,25 @@ ACPI_MODULE_NAME("evxface") | |||
54 | 54 | ||
55 | /******************************************************************************* | 55 | /******************************************************************************* |
56 | * | 56 | * |
57 | * FUNCTION: acpi_populate_handler_object | ||
58 | * | ||
59 | * PARAMETERS: handler_obj - Handler object to populate | ||
60 | * handler_type - The type of handler: | ||
61 | * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) | ||
62 | * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) | ||
63 | * ACPI_ALL_NOTIFY: both system and device | ||
64 | * handler - Address of the handler | ||
65 | * context - Value passed to the handler on each GPE | ||
66 | * next - Address of a handler object to link to | ||
67 | * | ||
68 | * RETURN: None | ||
69 | * | ||
70 | * DESCRIPTION: Populate a handler object. | ||
71 | * | ||
72 | ******************************************************************************/ | ||
73 | static void | ||
74 | acpi_populate_handler_object(struct acpi_object_notify_handler *handler_obj, | ||
75 | u32 handler_type, | ||
76 | acpi_notify_handler handler, void *context, | ||
77 | struct acpi_object_notify_handler *next) | ||
78 | { | ||
79 | handler_obj->handler_type = handler_type; | ||
80 | handler_obj->handler = handler; | ||
81 | handler_obj->context = context; | ||
82 | handler_obj->next = next; | ||
83 | } | ||
84 | |||
85 | /******************************************************************************* | ||
86 | * | ||
87 | * FUNCTION: acpi_add_handler_object | ||
88 | * | ||
89 | * PARAMETERS: parent_obj - Parent of the new object | ||
90 | * handler - Address of the handler | ||
91 | * context - Value passed to the handler on each GPE | ||
92 | * | ||
93 | * RETURN: Status | ||
94 | * | ||
95 | * DESCRIPTION: Create a new handler object and populate it. | ||
96 | * | ||
97 | ******************************************************************************/ | ||
98 | static acpi_status | ||
99 | acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj, | ||
100 | acpi_notify_handler handler, void *context) | ||
101 | { | ||
102 | struct acpi_object_notify_handler *handler_obj; | ||
103 | |||
104 | /* The parent must not be a defice notify handler object. */ | ||
105 | if (parent_obj->handler_type & ACPI_DEVICE_NOTIFY) | ||
106 | return AE_BAD_PARAMETER; | ||
107 | |||
108 | handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj)); | ||
109 | if (!handler_obj) | ||
110 | return AE_NO_MEMORY; | ||
111 | |||
112 | acpi_populate_handler_object(handler_obj, | ||
113 | ACPI_SYSTEM_NOTIFY, | ||
114 | handler, context, | ||
115 | parent_obj->next); | ||
116 | parent_obj->next = handler_obj; | ||
117 | |||
118 | return AE_OK; | ||
119 | } | ||
120 | |||
121 | |||
122 | /******************************************************************************* | ||
123 | * | ||
124 | * FUNCTION: acpi_install_notify_handler | 57 | * FUNCTION: acpi_install_notify_handler |
125 | * | 58 | * |
126 | * PARAMETERS: Device - The device for which notifies will be handled | 59 | * PARAMETERS: Device - The device for which notifies will be handled |
127 | * handler_type - The type of handler: | 60 | * handler_type - The type of handler: |
128 | * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) | 61 | * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) |
129 | * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) | 62 | * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) |
130 | * ACPI_ALL_NOTIFY: both system and device | 63 | * ACPI_ALL_NOTIFY: Both System and Device |
131 | * Handler - Address of the handler | 64 | * Handler - Address of the handler |
132 | * Context - Value passed to the handler on each GPE | 65 | * Context - Value passed to the handler on each GPE |
133 | * | 66 | * |
134 | * RETURN: Status | 67 | * RETURN: Status |
135 | * | 68 | * |
136 | * DESCRIPTION: Install a handler for notifies on an ACPI device | 69 | * DESCRIPTION: Install a handler for notifications on an ACPI Device, |
70 | * thermal_zone, or Processor object. | ||
71 | * | ||
72 | * NOTES: The Root namespace object may have only one handler for each | ||
73 | * type of notify (System/Device). Device/Thermal/Processor objects | ||
74 | * may have one device notify handler, and multiple system notify | ||
75 | * handlers. | ||
137 | * | 76 | * |
138 | ******************************************************************************/ | 77 | ******************************************************************************/ |
139 | acpi_status | 78 | acpi_status |
@@ -141,17 +80,19 @@ acpi_install_notify_handler(acpi_handle device, | |||
141 | u32 handler_type, | 80 | u32 handler_type, |
142 | acpi_notify_handler handler, void *context) | 81 | acpi_notify_handler handler, void *context) |
143 | { | 82 | { |
83 | struct acpi_namespace_node *node = | ||
84 | ACPI_CAST_PTR(struct acpi_namespace_node, device); | ||
144 | union acpi_operand_object *obj_desc; | 85 | union acpi_operand_object *obj_desc; |
145 | union acpi_operand_object *notify_obj; | 86 | union acpi_operand_object *handler_obj; |
146 | struct acpi_namespace_node *node; | ||
147 | acpi_status status; | 87 | acpi_status status; |
88 | u32 i; | ||
148 | 89 | ||
149 | ACPI_FUNCTION_TRACE(acpi_install_notify_handler); | 90 | ACPI_FUNCTION_TRACE(acpi_install_notify_handler); |
150 | 91 | ||
151 | /* Parameter validation */ | 92 | /* Parameter validation */ |
152 | 93 | ||
153 | if ((!device) || | 94 | if ((!device) || (!handler) || (!handler_type) || |
154 | (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { | 95 | (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { |
155 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 96 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
156 | } | 97 | } |
157 | 98 | ||
@@ -160,144 +101,112 @@ acpi_install_notify_handler(acpi_handle device, | |||
160 | return_ACPI_STATUS(status); | 101 | return_ACPI_STATUS(status); |
161 | } | 102 | } |
162 | 103 | ||
163 | /* Convert and validate the device handle */ | ||
164 | |||
165 | node = acpi_ns_validate_handle(device); | ||
166 | if (!node) { | ||
167 | status = AE_BAD_PARAMETER; | ||
168 | goto unlock_and_exit; | ||
169 | } | ||
170 | |||
171 | /* | 104 | /* |
172 | * Root Object: | 105 | * Root Object: |
173 | * Registering a notify handler on the root object indicates that the | 106 | * Registering a notify handler on the root object indicates that the |
174 | * caller wishes to receive notifications for all objects. Note that | 107 | * caller wishes to receive notifications for all objects. Note that |
175 | * only one <external> global handler can be regsitered (per notify type). | 108 | * only one global handler can be registered per notify type. |
109 | * Ensure that a handler is not already installed. | ||
176 | */ | 110 | */ |
177 | if (device == ACPI_ROOT_OBJECT) { | 111 | if (device == ACPI_ROOT_OBJECT) { |
112 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { | ||
113 | if (handler_type & (i + 1)) { | ||
114 | if (acpi_gbl_global_notify[i].handler) { | ||
115 | status = AE_ALREADY_EXISTS; | ||
116 | goto unlock_and_exit; | ||
117 | } | ||
178 | 118 | ||
179 | /* Make sure the handler is not already installed */ | 119 | acpi_gbl_global_notify[i].handler = handler; |
180 | 120 | acpi_gbl_global_notify[i].context = context; | |
181 | if (((handler_type & ACPI_SYSTEM_NOTIFY) && | 121 | } |
182 | acpi_gbl_system_notify.handler) || | ||
183 | ((handler_type & ACPI_DEVICE_NOTIFY) && | ||
184 | acpi_gbl_device_notify.handler)) { | ||
185 | status = AE_ALREADY_EXISTS; | ||
186 | goto unlock_and_exit; | ||
187 | } | ||
188 | |||
189 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | ||
190 | acpi_gbl_system_notify.node = node; | ||
191 | acpi_gbl_system_notify.handler = handler; | ||
192 | acpi_gbl_system_notify.context = context; | ||
193 | } | ||
194 | |||
195 | if (handler_type & ACPI_DEVICE_NOTIFY) { | ||
196 | acpi_gbl_device_notify.node = node; | ||
197 | acpi_gbl_device_notify.handler = handler; | ||
198 | acpi_gbl_device_notify.context = context; | ||
199 | } | 122 | } |
200 | 123 | ||
201 | /* Global notify handler installed */ | 124 | goto unlock_and_exit; /* Global notify handler installed, all done */ |
202 | } | 125 | } |
203 | 126 | ||
204 | /* | 127 | /* |
205 | * All Other Objects: | 128 | * All Other Objects: |
206 | * Caller will only receive notifications specific to the target object. | 129 | * Caller will only receive notifications specific to the target |
207 | * Note that only certain object types can receive notifications. | 130 | * object. Note that only certain object types are allowed to |
131 | * receive notifications. | ||
208 | */ | 132 | */ |
209 | else { | ||
210 | /* Notifies allowed on this object? */ | ||
211 | 133 | ||
212 | if (!acpi_ev_is_notify_object(node)) { | 134 | /* Are Notifies allowed on this object? */ |
213 | status = AE_TYPE; | ||
214 | goto unlock_and_exit; | ||
215 | } | ||
216 | 135 | ||
217 | /* Check for an existing internal object */ | 136 | if (!acpi_ev_is_notify_object(node)) { |
137 | status = AE_TYPE; | ||
138 | goto unlock_and_exit; | ||
139 | } | ||
218 | 140 | ||
219 | obj_desc = acpi_ns_get_attached_object(node); | 141 | /* Check for an existing internal object, might not exist */ |
220 | if (obj_desc) { | ||
221 | 142 | ||
222 | /* Object exists. */ | 143 | obj_desc = acpi_ns_get_attached_object(node); |
144 | if (!obj_desc) { | ||
223 | 145 | ||
224 | /* For a device notify, make sure there's no handler. */ | 146 | /* Create a new object */ |
225 | if ((handler_type & ACPI_DEVICE_NOTIFY) && | ||
226 | obj_desc->common_notify.device_notify) { | ||
227 | status = AE_ALREADY_EXISTS; | ||
228 | goto unlock_and_exit; | ||
229 | } | ||
230 | 147 | ||
231 | /* System notifies may have more handlers installed. */ | 148 | obj_desc = acpi_ut_create_internal_object(node->type); |
232 | notify_obj = obj_desc->common_notify.system_notify; | 149 | if (!obj_desc) { |
150 | status = AE_NO_MEMORY; | ||
151 | goto unlock_and_exit; | ||
152 | } | ||
233 | 153 | ||
234 | if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) { | 154 | /* Attach new object to the Node, remove local reference */ |
235 | struct acpi_object_notify_handler *parent_obj; | 155 | |
156 | status = acpi_ns_attach_object(device, obj_desc, node->type); | ||
157 | acpi_ut_remove_reference(obj_desc); | ||
158 | if (ACPI_FAILURE(status)) { | ||
159 | goto unlock_and_exit; | ||
160 | } | ||
161 | } | ||
236 | 162 | ||
237 | if (handler_type & ACPI_DEVICE_NOTIFY) { | 163 | /* Ensure that the handler is not already installed in the lists */ |
164 | |||
165 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { | ||
166 | if (handler_type & (i + 1)) { | ||
167 | handler_obj = obj_desc->common_notify.notify_list[i]; | ||
168 | while (handler_obj) { | ||
169 | if (handler_obj->notify.handler == handler) { | ||
238 | status = AE_ALREADY_EXISTS; | 170 | status = AE_ALREADY_EXISTS; |
239 | goto unlock_and_exit; | 171 | goto unlock_and_exit; |
240 | } | 172 | } |
241 | 173 | ||
242 | parent_obj = ¬ify_obj->notify; | 174 | handler_obj = handler_obj->notify.next[i]; |
243 | status = acpi_add_handler_object(parent_obj, | ||
244 | handler, | ||
245 | context); | ||
246 | goto unlock_and_exit; | ||
247 | } | ||
248 | } else { | ||
249 | /* Create a new object */ | ||
250 | |||
251 | obj_desc = acpi_ut_create_internal_object(node->type); | ||
252 | if (!obj_desc) { | ||
253 | status = AE_NO_MEMORY; | ||
254 | goto unlock_and_exit; | ||
255 | } | ||
256 | |||
257 | /* Attach new object to the Node */ | ||
258 | |||
259 | status = | ||
260 | acpi_ns_attach_object(device, obj_desc, node->type); | ||
261 | |||
262 | /* Remove local reference to the object */ | ||
263 | |||
264 | acpi_ut_remove_reference(obj_desc); | ||
265 | if (ACPI_FAILURE(status)) { | ||
266 | goto unlock_and_exit; | ||
267 | } | 175 | } |
268 | } | 176 | } |
177 | } | ||
269 | 178 | ||
270 | /* Install the handler */ | 179 | /* Create and populate a new notify handler object */ |
271 | 180 | ||
272 | notify_obj = | 181 | handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); |
273 | acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); | 182 | if (!handler_obj) { |
274 | if (!notify_obj) { | 183 | status = AE_NO_MEMORY; |
275 | status = AE_NO_MEMORY; | 184 | goto unlock_and_exit; |
276 | goto unlock_and_exit; | 185 | } |
277 | } | ||
278 | 186 | ||
279 | acpi_populate_handler_object(¬ify_obj->notify, | 187 | handler_obj->notify.node = node; |
280 | handler_type, | 188 | handler_obj->notify.handler_type = handler_type; |
281 | handler, context, | 189 | handler_obj->notify.handler = handler; |
282 | NULL); | 190 | handler_obj->notify.context = context; |
283 | 191 | ||
284 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | 192 | /* Install the handler at the list head(s) */ |
285 | obj_desc->common_notify.system_notify = notify_obj; | ||
286 | } | ||
287 | 193 | ||
288 | if (handler_type & ACPI_DEVICE_NOTIFY) { | 194 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { |
289 | obj_desc->common_notify.device_notify = notify_obj; | 195 | if (handler_type & (i + 1)) { |
290 | } | 196 | handler_obj->notify.next[i] = |
197 | obj_desc->common_notify.notify_list[i]; | ||
291 | 198 | ||
292 | if (handler_type == ACPI_ALL_NOTIFY) { | 199 | obj_desc->common_notify.notify_list[i] = handler_obj; |
200 | } | ||
201 | } | ||
293 | 202 | ||
294 | /* Extra ref if installed in both */ | 203 | /* Add an extra reference if handler was installed in both lists */ |
295 | 204 | ||
296 | acpi_ut_add_reference(notify_obj); | 205 | if (handler_type == ACPI_ALL_NOTIFY) { |
297 | } | 206 | acpi_ut_add_reference(handler_obj); |
298 | } | 207 | } |
299 | 208 | ||
300 | unlock_and_exit: | 209 | unlock_and_exit: |
301 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 210 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
302 | return_ACPI_STATUS(status); | 211 | return_ACPI_STATUS(status); |
303 | } | 212 | } |
@@ -308,11 +217,11 @@ ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) | |||
308 | * | 217 | * |
309 | * FUNCTION: acpi_remove_notify_handler | 218 | * FUNCTION: acpi_remove_notify_handler |
310 | * | 219 | * |
311 | * PARAMETERS: Device - The device for which notifies will be handled | 220 | * PARAMETERS: Device - The device for which the handler is installed |
312 | * handler_type - The type of handler: | 221 | * handler_type - The type of handler: |
313 | * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) | 222 | * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) |
314 | * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) | 223 | * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) |
315 | * ACPI_ALL_NOTIFY: both system and device | 224 | * ACPI_ALL_NOTIFY: Both System and Device |
316 | * Handler - Address of the handler | 225 | * Handler - Address of the handler |
317 | * | 226 | * |
318 | * RETURN: Status | 227 | * RETURN: Status |
@@ -324,165 +233,106 @@ acpi_status | |||
324 | acpi_remove_notify_handler(acpi_handle device, | 233 | acpi_remove_notify_handler(acpi_handle device, |
325 | u32 handler_type, acpi_notify_handler handler) | 234 | u32 handler_type, acpi_notify_handler handler) |
326 | { | 235 | { |
327 | union acpi_operand_object *notify_obj; | 236 | struct acpi_namespace_node *node = |
237 | ACPI_CAST_PTR(struct acpi_namespace_node, device); | ||
328 | union acpi_operand_object *obj_desc; | 238 | union acpi_operand_object *obj_desc; |
329 | struct acpi_namespace_node *node; | 239 | union acpi_operand_object *handler_obj; |
240 | union acpi_operand_object *previous_handler_obj; | ||
330 | acpi_status status; | 241 | acpi_status status; |
242 | u32 i; | ||
331 | 243 | ||
332 | ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); | 244 | ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); |
333 | 245 | ||
334 | /* Parameter validation */ | 246 | /* Parameter validation */ |
335 | 247 | ||
336 | if ((!device) || | 248 | if ((!device) || (!handler) || (!handler_type) || |
337 | (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { | 249 | (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { |
338 | status = AE_BAD_PARAMETER; | 250 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
339 | goto exit; | ||
340 | } | 251 | } |
341 | |||
342 | |||
343 | /* Make sure all deferred tasks are completed */ | 252 | /* Make sure all deferred tasks are completed */ |
344 | acpi_os_wait_events_complete(NULL); | 253 | |
254 | acpi_os_wait_events_complete(); | ||
345 | 255 | ||
346 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 256 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
347 | if (ACPI_FAILURE(status)) { | 257 | if (ACPI_FAILURE(status)) { |
348 | goto exit; | 258 | return_ACPI_STATUS(status); |
349 | } | ||
350 | |||
351 | /* Convert and validate the device handle */ | ||
352 | |||
353 | node = acpi_ns_validate_handle(device); | ||
354 | if (!node) { | ||
355 | status = AE_BAD_PARAMETER; | ||
356 | goto unlock_and_exit; | ||
357 | } | 259 | } |
358 | 260 | ||
359 | /* Root Object */ | 261 | /* Root Object. Global handlers are removed here */ |
360 | 262 | ||
361 | if (device == ACPI_ROOT_OBJECT) { | 263 | if (device == ACPI_ROOT_OBJECT) { |
362 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 264 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { |
363 | "Removing notify handler for namespace root object\n")); | 265 | if (handler_type & (i + 1)) { |
266 | if (!acpi_gbl_global_notify[i].handler || | ||
267 | (acpi_gbl_global_notify[i].handler != | ||
268 | handler)) { | ||
269 | status = AE_NOT_EXIST; | ||
270 | goto unlock_and_exit; | ||
271 | } | ||
364 | 272 | ||
365 | if (((handler_type & ACPI_SYSTEM_NOTIFY) && | 273 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
366 | !acpi_gbl_system_notify.handler) || | 274 | "Removing global notify handler\n")); |
367 | ((handler_type & ACPI_DEVICE_NOTIFY) && | ||
368 | !acpi_gbl_device_notify.handler)) { | ||
369 | status = AE_NOT_EXIST; | ||
370 | goto unlock_and_exit; | ||
371 | } | ||
372 | 275 | ||
373 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | 276 | acpi_gbl_global_notify[i].handler = NULL; |
374 | acpi_gbl_system_notify.node = NULL; | 277 | acpi_gbl_global_notify[i].context = NULL; |
375 | acpi_gbl_system_notify.handler = NULL; | 278 | } |
376 | acpi_gbl_system_notify.context = NULL; | ||
377 | } | 279 | } |
378 | 280 | ||
379 | if (handler_type & ACPI_DEVICE_NOTIFY) { | 281 | goto unlock_and_exit; |
380 | acpi_gbl_device_notify.node = NULL; | ||
381 | acpi_gbl_device_notify.handler = NULL; | ||
382 | acpi_gbl_device_notify.context = NULL; | ||
383 | } | ||
384 | } | 282 | } |
385 | 283 | ||
386 | /* All Other Objects */ | 284 | /* All other objects: Are Notifies allowed on this object? */ |
387 | 285 | ||
388 | else { | 286 | if (!acpi_ev_is_notify_object(node)) { |
389 | /* Notifies allowed on this object? */ | 287 | status = AE_TYPE; |
288 | goto unlock_and_exit; | ||
289 | } | ||
390 | 290 | ||
391 | if (!acpi_ev_is_notify_object(node)) { | 291 | /* Must have an existing internal object */ |
392 | status = AE_TYPE; | ||
393 | goto unlock_and_exit; | ||
394 | } | ||
395 | 292 | ||
396 | /* Check for an existing internal object */ | 293 | obj_desc = acpi_ns_get_attached_object(node); |
294 | if (!obj_desc) { | ||
295 | status = AE_NOT_EXIST; | ||
296 | goto unlock_and_exit; | ||
297 | } | ||
397 | 298 | ||
398 | obj_desc = acpi_ns_get_attached_object(node); | 299 | /* Internal object exists. Find the handler and remove it */ |
399 | if (!obj_desc) { | ||
400 | status = AE_NOT_EXIST; | ||
401 | goto unlock_and_exit; | ||
402 | } | ||
403 | 300 | ||
404 | /* Object exists - make sure there's an existing handler */ | 301 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { |
302 | if (handler_type & (i + 1)) { | ||
303 | handler_obj = obj_desc->common_notify.notify_list[i]; | ||
304 | previous_handler_obj = NULL; | ||
405 | 305 | ||
406 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | 306 | /* Attempt to find the handler in the handler list */ |
407 | struct acpi_object_notify_handler *handler_obj; | ||
408 | struct acpi_object_notify_handler *parent_obj; | ||
409 | 307 | ||
410 | notify_obj = obj_desc->common_notify.system_notify; | 308 | while (handler_obj && |
411 | if (!notify_obj) { | 309 | (handler_obj->notify.handler != handler)) { |
412 | status = AE_NOT_EXIST; | 310 | previous_handler_obj = handler_obj; |
413 | goto unlock_and_exit; | 311 | handler_obj = handler_obj->notify.next[i]; |
414 | } | ||
415 | |||
416 | handler_obj = ¬ify_obj->notify; | ||
417 | parent_obj = NULL; | ||
418 | while (handler_obj->handler != handler) { | ||
419 | if (handler_obj->next) { | ||
420 | parent_obj = handler_obj; | ||
421 | handler_obj = handler_obj->next; | ||
422 | } else { | ||
423 | break; | ||
424 | } | ||
425 | } | 312 | } |
426 | 313 | ||
427 | if (handler_obj->handler != handler) { | 314 | if (!handler_obj) { |
428 | status = AE_BAD_PARAMETER; | 315 | status = AE_NOT_EXIST; |
429 | goto unlock_and_exit; | 316 | goto unlock_and_exit; |
430 | } | 317 | } |
431 | 318 | ||
432 | /* | 319 | /* Remove the handler object from the list */ |
433 | * Remove the handler. There are three possible cases. | ||
434 | * First, we may need to remove a non-embedded object. | ||
435 | * Second, we may need to remove the embedded object's | ||
436 | * handler data, while non-embedded objects exist. | ||
437 | * Finally, we may need to remove the embedded object | ||
438 | * entirely along with its container. | ||
439 | */ | ||
440 | if (parent_obj) { | ||
441 | /* Non-embedded object is being removed. */ | ||
442 | parent_obj->next = handler_obj->next; | ||
443 | ACPI_FREE(handler_obj); | ||
444 | } else if (notify_obj->notify.next) { | ||
445 | /* | ||
446 | * The handler matches the embedded object, but | ||
447 | * there are more handler objects in the list. | ||
448 | * Replace the embedded object's data with the | ||
449 | * first next object's data and remove that | ||
450 | * object. | ||
451 | */ | ||
452 | parent_obj = ¬ify_obj->notify; | ||
453 | handler_obj = notify_obj->notify.next; | ||
454 | *parent_obj = *handler_obj; | ||
455 | ACPI_FREE(handler_obj); | ||
456 | } else { | ||
457 | /* No more handler objects in the list. */ | ||
458 | obj_desc->common_notify.system_notify = NULL; | ||
459 | acpi_ut_remove_reference(notify_obj); | ||
460 | } | ||
461 | } | ||
462 | 320 | ||
463 | if (handler_type & ACPI_DEVICE_NOTIFY) { | 321 | if (previous_handler_obj) { /* Handler is not at the list head */ |
464 | notify_obj = obj_desc->common_notify.device_notify; | 322 | previous_handler_obj->notify.next[i] = |
465 | if (!notify_obj) { | 323 | handler_obj->notify.next[i]; |
466 | status = AE_NOT_EXIST; | 324 | } else { /* Handler is at the list head */ |
467 | goto unlock_and_exit; | ||
468 | } | ||
469 | 325 | ||
470 | if (notify_obj->notify.handler != handler) { | 326 | obj_desc->common_notify.notify_list[i] = |
471 | status = AE_BAD_PARAMETER; | 327 | handler_obj->notify.next[i]; |
472 | goto unlock_and_exit; | ||
473 | } | 328 | } |
474 | 329 | ||
475 | /* Remove the handler */ | 330 | acpi_ut_remove_reference(handler_obj); |
476 | obj_desc->common_notify.device_notify = NULL; | ||
477 | acpi_ut_remove_reference(notify_obj); | ||
478 | } | 331 | } |
479 | } | 332 | } |
480 | 333 | ||
481 | unlock_and_exit: | 334 | unlock_and_exit: |
482 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 335 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
483 | exit: | ||
484 | if (ACPI_FAILURE(status)) | ||
485 | ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler")); | ||
486 | return_ACPI_STATUS(status); | 336 | return_ACPI_STATUS(status); |
487 | } | 337 | } |
488 | 338 | ||
@@ -492,7 +342,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler) | |||
492 | * | 342 | * |
493 | * FUNCTION: acpi_install_exception_handler | 343 | * FUNCTION: acpi_install_exception_handler |
494 | * | 344 | * |
495 | * PARAMETERS: Handler - Pointer to the handler function for the | 345 | * PARAMETERS: handler - Pointer to the handler function for the |
496 | * event | 346 | * event |
497 | * | 347 | * |
498 | * RETURN: Status | 348 | * RETURN: Status |
@@ -536,8 +386,8 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler) | |||
536 | * | 386 | * |
537 | * FUNCTION: acpi_install_global_event_handler | 387 | * FUNCTION: acpi_install_global_event_handler |
538 | * | 388 | * |
539 | * PARAMETERS: Handler - Pointer to the global event handler function | 389 | * PARAMETERS: handler - Pointer to the global event handler function |
540 | * Context - Value passed to the handler on each event | 390 | * context - Value passed to the handler on each event |
541 | * | 391 | * |
542 | * RETURN: Status | 392 | * RETURN: Status |
543 | * | 393 | * |
@@ -586,10 +436,10 @@ ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler) | |||
586 | * | 436 | * |
587 | * FUNCTION: acpi_install_fixed_event_handler | 437 | * FUNCTION: acpi_install_fixed_event_handler |
588 | * | 438 | * |
589 | * PARAMETERS: Event - Event type to enable. | 439 | * PARAMETERS: event - Event type to enable. |
590 | * Handler - Pointer to the handler function for the | 440 | * handler - Pointer to the handler function for the |
591 | * event | 441 | * event |
592 | * Context - Value passed to the handler on each GPE | 442 | * context - Value passed to the handler on each GPE |
593 | * | 443 | * |
594 | * RETURN: Status | 444 | * RETURN: Status |
595 | * | 445 | * |
@@ -656,8 +506,8 @@ ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler) | |||
656 | * | 506 | * |
657 | * FUNCTION: acpi_remove_fixed_event_handler | 507 | * FUNCTION: acpi_remove_fixed_event_handler |
658 | * | 508 | * |
659 | * PARAMETERS: Event - Event type to disable. | 509 | * PARAMETERS: event - Event type to disable. |
660 | * Handler - Address of the handler | 510 | * handler - Address of the handler |
661 | * | 511 | * |
662 | * RETURN: Status | 512 | * RETURN: Status |
663 | * | 513 | * |
@@ -713,10 +563,10 @@ ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler) | |||
713 | * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT | 563 | * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT |
714 | * defined GPEs) | 564 | * defined GPEs) |
715 | * gpe_number - The GPE number within the GPE block | 565 | * gpe_number - The GPE number within the GPE block |
716 | * Type - Whether this GPE should be treated as an | 566 | * type - Whether this GPE should be treated as an |
717 | * edge- or level-triggered interrupt. | 567 | * edge- or level-triggered interrupt. |
718 | * Address - Address of the handler | 568 | * address - Address of the handler |
719 | * Context - Value passed to the handler on each GPE | 569 | * context - Value passed to the handler on each GPE |
720 | * | 570 | * |
721 | * RETURN: Status | 571 | * RETURN: Status |
722 | * | 572 | * |
@@ -823,7 +673,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler) | |||
823 | * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT | 673 | * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT |
824 | * defined GPEs) | 674 | * defined GPEs) |
825 | * gpe_number - The event to remove a handler | 675 | * gpe_number - The event to remove a handler |
826 | * Address - Address of the handler | 676 | * address - Address of the handler |
827 | * | 677 | * |
828 | * RETURN: Status | 678 | * RETURN: Status |
829 | * | 679 | * |
@@ -849,7 +699,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device, | |||
849 | 699 | ||
850 | /* Make sure all deferred tasks are completed */ | 700 | /* Make sure all deferred tasks are completed */ |
851 | 701 | ||
852 | acpi_os_wait_events_complete(NULL); | 702 | acpi_os_wait_events_complete(); |
853 | 703 | ||
854 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | 704 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); |
855 | if (ACPI_FAILURE(status)) { | 705 | if (ACPI_FAILURE(status)) { |
@@ -919,8 +769,8 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) | |||
919 | * | 769 | * |
920 | * FUNCTION: acpi_acquire_global_lock | 770 | * FUNCTION: acpi_acquire_global_lock |
921 | * | 771 | * |
922 | * PARAMETERS: Timeout - How long the caller is willing to wait | 772 | * PARAMETERS: timeout - How long the caller is willing to wait |
923 | * Handle - Where the handle to the lock is returned | 773 | * handle - Where the handle to the lock is returned |
924 | * (if acquired) | 774 | * (if acquired) |
925 | * | 775 | * |
926 | * RETURN: Status | 776 | * RETURN: Status |
@@ -967,7 +817,7 @@ ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock) | |||
967 | * | 817 | * |
968 | * FUNCTION: acpi_release_global_lock | 818 | * FUNCTION: acpi_release_global_lock |
969 | * | 819 | * |
970 | * PARAMETERS: Handle - Returned from acpi_acquire_global_lock | 820 | * PARAMETERS: handle - Returned from acpi_acquire_global_lock |
971 | * | 821 | * |
972 | * RETURN: Status | 822 | * RETURN: Status |
973 | * | 823 | * |