@@ -216,6 +216,72 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
216
216
217
217
ACPI_EXPORT_SYMBOL (acpi_remove_fixed_event_handler )
218
218
219
+ /*******************************************************************************
220
+ *
221
+ * FUNCTION: acpi_populate_handler_object
222
+ *
223
+ * PARAMETERS: handler_obj - Handler object to populate
224
+ * handler_type - The type of handler:
225
+ * ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
226
+ * ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
227
+ * ACPI_ALL_NOTIFY: both system and device
228
+ * handler - Address of the handler
229
+ * context - Value passed to the handler on each GPE
230
+ * next - Address of a handler object to link to
231
+ *
232
+ * RETURN: None
233
+ *
234
+ * DESCRIPTION: Populate a handler object.
235
+ *
236
+ ******************************************************************************/
237
+ static void
238
+ acpi_populate_handler_object (struct acpi_object_notify_handler * handler_obj ,
239
+ u32 handler_type ,
240
+ acpi_notify_handler handler , void * context ,
241
+ struct acpi_object_notify_handler * next )
242
+ {
243
+ handler_obj -> handler_type = handler_type ;
244
+ handler_obj -> handler = handler ;
245
+ handler_obj -> context = context ;
246
+ handler_obj -> next = next ;
247
+ }
248
+
249
+ /*******************************************************************************
250
+ *
251
+ * FUNCTION: acpi_add_handler_object
252
+ *
253
+ * PARAMETERS: parent_obj - Parent of the new object
254
+ * handler - Address of the handler
255
+ * context - Value passed to the handler on each GPE
256
+ *
257
+ * RETURN: Status
258
+ *
259
+ * DESCRIPTION: Create a new handler object and populate it.
260
+ *
261
+ ******************************************************************************/
262
+ static acpi_status
263
+ acpi_add_handler_object (struct acpi_object_notify_handler * parent_obj ,
264
+ acpi_notify_handler handler , void * context )
265
+ {
266
+ struct acpi_object_notify_handler * handler_obj ;
267
+
268
+ /* The parent must not be a defice notify handler object. */
269
+ if (parent_obj -> handler_type & ACPI_DEVICE_NOTIFY )
270
+ return AE_BAD_PARAMETER ;
271
+
272
+ handler_obj = ACPI_ALLOCATE_ZEROED (sizeof (* handler_obj ));
273
+ if (!handler_obj )
274
+ return AE_NO_MEMORY ;
275
+
276
+ acpi_populate_handler_object (handler_obj ,
277
+ ACPI_SYSTEM_NOTIFY ,
278
+ handler , context ,
279
+ parent_obj -> next );
280
+ parent_obj -> next = handler_obj ;
281
+
282
+ return AE_OK ;
283
+ }
284
+
219
285
/*******************************************************************************
220
286
*
221
287
* FUNCTION: acpi_install_notify_handler
@@ -316,15 +382,32 @@ acpi_install_notify_handler(acpi_handle device,
316
382
obj_desc = acpi_ns_get_attached_object (node );
317
383
if (obj_desc ) {
318
384
319
- /* Object exists - make sure there's no handler */
385
+ /* Object exists. */
320
386
321
- if (((handler_type & ACPI_SYSTEM_NOTIFY ) &&
322
- obj_desc -> common_notify .system_notify ) ||
323
- ((handler_type & ACPI_DEVICE_NOTIFY ) &&
324
- obj_desc -> common_notify .device_notify )) {
387
+ /* For a device notify, make sure there's no handler. */
388
+ if ((handler_type & ACPI_DEVICE_NOTIFY ) &&
389
+ obj_desc -> common_notify .device_notify ) {
325
390
status = AE_ALREADY_EXISTS ;
326
391
goto unlock_and_exit ;
327
392
}
393
+
394
+ /* System notifies may have more handlers installed. */
395
+ notify_obj = obj_desc -> common_notify .system_notify ;
396
+
397
+ if ((handler_type & ACPI_SYSTEM_NOTIFY ) && notify_obj ) {
398
+ struct acpi_object_notify_handler * parent_obj ;
399
+
400
+ if (handler_type & ACPI_DEVICE_NOTIFY ) {
401
+ status = AE_ALREADY_EXISTS ;
402
+ goto unlock_and_exit ;
403
+ }
404
+
405
+ parent_obj = & notify_obj -> notify ;
406
+ status = acpi_add_handler_object (parent_obj ,
407
+ handler ,
408
+ context );
409
+ goto unlock_and_exit ;
410
+ }
328
411
} else {
329
412
/* Create a new object */
330
413
@@ -356,9 +439,10 @@ acpi_install_notify_handler(acpi_handle device,
356
439
goto unlock_and_exit ;
357
440
}
358
441
359
- notify_obj -> notify .node = node ;
360
- notify_obj -> notify .handler = handler ;
361
- notify_obj -> notify .context = context ;
442
+ acpi_populate_handler_object (& notify_obj -> notify ,
443
+ handler_type ,
444
+ handler , context ,
445
+ NULL );
362
446
363
447
if (handler_type & ACPI_SYSTEM_NOTIFY ) {
364
448
obj_desc -> common_notify .system_notify = notify_obj ;
@@ -418,6 +502,10 @@ acpi_remove_notify_handler(acpi_handle device,
418
502
goto exit ;
419
503
}
420
504
505
+
506
+ /* Make sure all deferred tasks are completed */
507
+ acpi_os_wait_events_complete (NULL );
508
+
421
509
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE );
422
510
if (ACPI_FAILURE (status )) {
423
511
goto exit ;
@@ -445,15 +533,6 @@ acpi_remove_notify_handler(acpi_handle device,
445
533
goto unlock_and_exit ;
446
534
}
447
535
448
- /* Make sure all deferred tasks are completed */
449
-
450
- (void )acpi_ut_release_mutex (ACPI_MTX_NAMESPACE );
451
- acpi_os_wait_events_complete (NULL );
452
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE );
453
- if (ACPI_FAILURE (status )) {
454
- goto exit ;
455
- }
456
-
457
536
if (handler_type & ACPI_SYSTEM_NOTIFY ) {
458
537
acpi_gbl_system_notify .node = NULL ;
459
538
acpi_gbl_system_notify .handler = NULL ;
@@ -488,28 +567,60 @@ acpi_remove_notify_handler(acpi_handle device,
488
567
/* Object exists - make sure there's an existing handler */
489
568
490
569
if (handler_type & ACPI_SYSTEM_NOTIFY ) {
570
+ struct acpi_object_notify_handler * handler_obj ;
571
+ struct acpi_object_notify_handler * parent_obj ;
572
+
491
573
notify_obj = obj_desc -> common_notify .system_notify ;
492
574
if (!notify_obj ) {
493
575
status = AE_NOT_EXIST ;
494
576
goto unlock_and_exit ;
495
577
}
496
578
497
- if (notify_obj -> notify .handler != handler ) {
579
+ handler_obj = & notify_obj -> notify ;
580
+ parent_obj = NULL ;
581
+ while (handler_obj -> handler != handler ) {
582
+ if (handler_obj -> next ) {
583
+ parent_obj = handler_obj ;
584
+ handler_obj = handler_obj -> next ;
585
+ } else {
586
+ break ;
587
+ }
588
+ }
589
+
590
+ if (handler_obj -> handler != handler ) {
498
591
status = AE_BAD_PARAMETER ;
499
592
goto unlock_and_exit ;
500
593
}
501
- /* Make sure all deferred tasks are completed */
502
594
503
- (void )acpi_ut_release_mutex (ACPI_MTX_NAMESPACE );
504
- acpi_os_wait_events_complete (NULL );
505
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE );
506
- if (ACPI_FAILURE (status )) {
507
- goto exit ;
595
+ /*
596
+ * Remove the handler. There are three possible cases.
597
+ * First, we may need to remove a non-embedded object.
598
+ * Second, we may need to remove the embedded object's
599
+ * handler data, while non-embedded objects exist.
600
+ * Finally, we may need to remove the embedded object
601
+ * entirely along with its container.
602
+ */
603
+ if (parent_obj ) {
604
+ /* Non-embedded object is being removed. */
605
+ parent_obj -> next = handler_obj -> next ;
606
+ ACPI_FREE (handler_obj );
607
+ } else if (notify_obj -> notify .next ) {
608
+ /*
609
+ * The handler matches the embedded object, but
610
+ * there are more handler objects in the list.
611
+ * Replace the embedded object's data with the
612
+ * first next object's data and remove that
613
+ * object.
614
+ */
615
+ parent_obj = & notify_obj -> notify ;
616
+ handler_obj = notify_obj -> notify .next ;
617
+ * parent_obj = * handler_obj ;
618
+ ACPI_FREE (handler_obj );
619
+ } else {
620
+ /* No more handler objects in the list. */
621
+ obj_desc -> common_notify .system_notify = NULL ;
622
+ acpi_ut_remove_reference (notify_obj );
508
623
}
509
-
510
- /* Remove the handler */
511
- obj_desc -> common_notify .system_notify = NULL ;
512
- acpi_ut_remove_reference (notify_obj );
513
624
}
514
625
515
626
if (handler_type & ACPI_DEVICE_NOTIFY ) {
@@ -523,14 +634,6 @@ acpi_remove_notify_handler(acpi_handle device,
523
634
status = AE_BAD_PARAMETER ;
524
635
goto unlock_and_exit ;
525
636
}
526
- /* Make sure all deferred tasks are completed */
527
-
528
- (void )acpi_ut_release_mutex (ACPI_MTX_NAMESPACE );
529
- acpi_os_wait_events_complete (NULL );
530
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE );
531
- if (ACPI_FAILURE (status )) {
532
- goto exit ;
533
- }
534
637
535
638
/* Remove the handler */
536
639
obj_desc -> common_notify .device_notify = NULL ;
0 commit comments