This source file includes following definitions.
- ACPI_MODULE_NAME
- acpi_ev_address_space_dispatch
- acpi_ev_detach_region
- acpi_ev_attach_region
- acpi_ev_execute_reg_method
- acpi_ev_execute_reg_methods
- acpi_ev_reg_run
- acpi_ev_orphan_ec_reg_method
1
2
3
4
5
6
7
8
9
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acevents.h"
13 #include "acnamesp.h"
14 #include "acinterp.h"
15
16 #define _COMPONENT ACPI_EVENTS
17 ACPI_MODULE_NAME("evregion")
18
19 extern u8 acpi_gbl_default_address_spaces[];
20
21
22
23 static void
24 acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node);
25
26 static acpi_status
27 acpi_ev_reg_run(acpi_handle obj_handle,
28 u32 level, void *context, void **return_value);
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 acpi_status acpi_ev_initialize_op_regions(void)
44 {
45 acpi_status status;
46 u32 i;
47
48 ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
49
50 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
51 if (ACPI_FAILURE(status)) {
52 return_ACPI_STATUS(status);
53 }
54
55
56
57 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
58
59
60
61
62
63 if (acpi_ev_has_default_handler(acpi_gbl_root_node,
64 acpi_gbl_default_address_spaces
65 [i])) {
66 acpi_ev_execute_reg_methods(acpi_gbl_root_node,
67 acpi_gbl_default_address_spaces
68 [i], ACPI_REG_CONNECT);
69 }
70 }
71
72 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
73 return_ACPI_STATUS(status);
74 }
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 acpi_status
102 acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
103 union acpi_operand_object *field_obj,
104 u32 function,
105 u32 region_offset, u32 bit_width, u64 *value)
106 {
107 acpi_status status;
108 acpi_adr_space_handler handler;
109 acpi_adr_space_setup region_setup;
110 union acpi_operand_object *handler_desc;
111 union acpi_operand_object *region_obj2;
112 void *region_context = NULL;
113 struct acpi_connection_info *context;
114 acpi_physical_address address;
115
116 ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
117
118 region_obj2 = acpi_ns_get_secondary_object(region_obj);
119 if (!region_obj2) {
120 return_ACPI_STATUS(AE_NOT_EXIST);
121 }
122
123
124
125 handler_desc = region_obj->region.handler;
126 if (!handler_desc) {
127 ACPI_ERROR((AE_INFO,
128 "No handler for Region [%4.4s] (%p) [%s]",
129 acpi_ut_get_node_name(region_obj->region.node),
130 region_obj,
131 acpi_ut_get_region_name(region_obj->region.
132 space_id)));
133
134 return_ACPI_STATUS(AE_NOT_EXIST);
135 }
136
137 context = handler_desc->address_space.context;
138
139
140
141
142
143 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
144
145
146
147 region_setup = handler_desc->address_space.setup;
148 if (!region_setup) {
149
150
151
152 ACPI_ERROR((AE_INFO,
153 "No init routine for region(%p) [%s]",
154 region_obj,
155 acpi_ut_get_region_name(region_obj->region.
156 space_id)));
157 return_ACPI_STATUS(AE_NOT_EXIST);
158 }
159
160
161
162
163
164
165 acpi_ex_exit_interpreter();
166
167 status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
168 context, ®ion_context);
169
170
171
172 acpi_ex_enter_interpreter();
173
174
175
176 if (ACPI_FAILURE(status)) {
177 ACPI_EXCEPTION((AE_INFO, status,
178 "During region initialization: [%s]",
179 acpi_ut_get_region_name(region_obj->
180 region.
181 space_id)));
182 return_ACPI_STATUS(status);
183 }
184
185
186
187 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
188 region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
189
190
191
192
193
194 if (!(region_obj2->extra.region_context)) {
195 region_obj2->extra.region_context =
196 region_context;
197 }
198 }
199 }
200
201
202
203 handler = handler_desc->address_space.handler;
204 address = (region_obj->region.address + region_offset);
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220 if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
221 context && field_obj) {
222
223
224
225 context->connection = field_obj->field.resource_buffer;
226 context->length = field_obj->field.resource_length;
227 context->access_length = field_obj->field.access_length;
228 }
229 if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
230 context && field_obj) {
231
232
233
234 context->connection = field_obj->field.resource_buffer;
235 context->length = field_obj->field.resource_length;
236 context->access_length = field_obj->field.access_length;
237 address = field_obj->field.pin_number_index;
238 bit_width = field_obj->field.bit_length;
239 }
240
241 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
242 "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
243 ®ion_obj->region.handler->address_space, handler,
244 ACPI_FORMAT_UINT64(address),
245 acpi_ut_get_region_name(region_obj->region.
246 space_id)));
247
248 if (!(handler_desc->address_space.handler_flags &
249 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
250
251
252
253
254
255 acpi_ex_exit_interpreter();
256 }
257
258
259
260 status = handler(function, address, bit_width, value, context,
261 region_obj2->extra.region_context);
262
263 if (ACPI_FAILURE(status)) {
264 ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
265 acpi_ut_get_region_name(region_obj->region.
266 space_id)));
267
268
269
270
271
272 if ((region_obj->region.space_id == ACPI_ADR_SPACE_EC) &&
273 (status == AE_TIME)) {
274 ACPI_ERROR((AE_INFO,
275 "Timeout from EC hardware or EC device driver"));
276 }
277 }
278
279 if (!(handler_desc->address_space.handler_flags &
280 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
281
282
283
284
285 acpi_ex_enter_interpreter();
286 }
287
288 return_ACPI_STATUS(status);
289 }
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305 void
306 acpi_ev_detach_region(union acpi_operand_object *region_obj,
307 u8 acpi_ns_is_locked)
308 {
309 union acpi_operand_object *handler_obj;
310 union acpi_operand_object *obj_desc;
311 union acpi_operand_object *start_desc;
312 union acpi_operand_object **last_obj_ptr;
313 acpi_adr_space_setup region_setup;
314 void **region_context;
315 union acpi_operand_object *region_obj2;
316 acpi_status status;
317
318 ACPI_FUNCTION_TRACE(ev_detach_region);
319
320 region_obj2 = acpi_ns_get_secondary_object(region_obj);
321 if (!region_obj2) {
322 return_VOID;
323 }
324 region_context = ®ion_obj2->extra.region_context;
325
326
327
328 handler_obj = region_obj->region.handler;
329 if (!handler_obj) {
330
331
332
333 return_VOID;
334 }
335
336
337
338 obj_desc = handler_obj->address_space.region_list;
339 start_desc = obj_desc;
340 last_obj_ptr = &handler_obj->address_space.region_list;
341
342 while (obj_desc) {
343
344
345
346 if (obj_desc == region_obj) {
347 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
348 "Removing Region %p from address handler %p\n",
349 region_obj, handler_obj));
350
351
352
353 *last_obj_ptr = obj_desc->region.next;
354 obj_desc->region.next = NULL;
355
356 if (acpi_ns_is_locked) {
357 status =
358 acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
359 if (ACPI_FAILURE(status)) {
360 return_VOID;
361 }
362 }
363
364
365
366 status =
367 acpi_ev_execute_reg_method(region_obj,
368 ACPI_REG_DISCONNECT);
369 if (ACPI_FAILURE(status)) {
370 ACPI_EXCEPTION((AE_INFO, status,
371 "from region _REG, [%s]",
372 acpi_ut_get_region_name
373 (region_obj->region.space_id)));
374 }
375
376 if (acpi_ns_is_locked) {
377 status =
378 acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
379 if (ACPI_FAILURE(status)) {
380 return_VOID;
381 }
382 }
383
384
385
386
387
388 if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
389 region_setup = handler_obj->address_space.setup;
390 status =
391 region_setup(region_obj,
392 ACPI_REGION_DEACTIVATE,
393 handler_obj->address_space.
394 context, region_context);
395
396
397
398
399
400 if (region_context) {
401 *region_context = NULL;
402 }
403
404
405
406 if (ACPI_FAILURE(status)) {
407 ACPI_EXCEPTION((AE_INFO, status,
408 "from region handler - deactivate, [%s]",
409 acpi_ut_get_region_name
410 (region_obj->region.
411 space_id)));
412 }
413
414 region_obj->region.flags &=
415 ~(AOPOBJ_SETUP_COMPLETE);
416 }
417
418
419
420
421
422
423
424
425
426
427 region_obj->region.handler = NULL;
428 acpi_ut_remove_reference(handler_obj);
429
430 return_VOID;
431 }
432
433
434
435 last_obj_ptr = &obj_desc->region.next;
436 obj_desc = obj_desc->region.next;
437
438
439
440 if (obj_desc == start_desc) {
441 ACPI_ERROR((AE_INFO,
442 "Circular handler list in region object %p",
443 region_obj));
444 return_VOID;
445 }
446 }
447
448
449
450 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
451 "Cannot remove region %p from address handler %p\n",
452 region_obj, handler_obj));
453
454 return_VOID;
455 }
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472 acpi_status
473 acpi_ev_attach_region(union acpi_operand_object *handler_obj,
474 union acpi_operand_object *region_obj,
475 u8 acpi_ns_is_locked)
476 {
477
478 ACPI_FUNCTION_TRACE(ev_attach_region);
479
480
481
482 if (region_obj->region.handler) {
483 return_ACPI_STATUS(AE_ALREADY_EXISTS);
484 }
485
486 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
487 "Adding Region [%4.4s] %p to address handler %p [%s]\n",
488 acpi_ut_get_node_name(region_obj->region.node),
489 region_obj, handler_obj,
490 acpi_ut_get_region_name(region_obj->region.
491 space_id)));
492
493
494
495 region_obj->region.next = handler_obj->address_space.region_list;
496 handler_obj->address_space.region_list = region_obj;
497 region_obj->region.handler = handler_obj;
498 acpi_ut_add_reference(handler_obj);
499
500 return_ACPI_STATUS(AE_OK);
501 }
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516 acpi_status
517 acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
518 {
519 struct acpi_evaluate_info *info;
520 union acpi_operand_object *args[3];
521 union acpi_operand_object *region_obj2;
522 const acpi_name *reg_name_ptr =
523 ACPI_CAST_PTR(acpi_name, METHOD_NAME__REG);
524 struct acpi_namespace_node *method_node;
525 struct acpi_namespace_node *node;
526 acpi_status status;
527
528 ACPI_FUNCTION_TRACE(ev_execute_reg_method);
529
530 if (!acpi_gbl_namespace_initialized ||
531 region_obj->region.handler == NULL) {
532 return_ACPI_STATUS(AE_OK);
533 }
534
535 region_obj2 = acpi_ns_get_secondary_object(region_obj);
536 if (!region_obj2) {
537 return_ACPI_STATUS(AE_NOT_EXIST);
538 }
539
540
541
542
543
544
545 node = region_obj->region.node->parent;
546 status =
547 acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
548 &method_node);
549 if (ACPI_SUCCESS(status)) {
550
551
552
553
554
555 region_obj2->extra.method_REG = method_node;
556 }
557 if (region_obj2->extra.method_REG == NULL) {
558 return_ACPI_STATUS(AE_OK);
559 }
560
561
562
563 if ((function == ACPI_REG_CONNECT &&
564 region_obj->common.flags & AOPOBJ_REG_CONNECTED) ||
565 (function == ACPI_REG_DISCONNECT &&
566 !(region_obj->common.flags & AOPOBJ_REG_CONNECTED))) {
567 return_ACPI_STATUS(AE_OK);
568 }
569
570
571
572 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
573 if (!info) {
574 return_ACPI_STATUS(AE_NO_MEMORY);
575 }
576
577 info->prefix_node = region_obj2->extra.method_REG;
578 info->relative_pathname = NULL;
579 info->parameters = args;
580 info->flags = ACPI_IGNORE_RETURN_VALUE;
581
582
583
584
585
586
587
588
589
590
591
592 args[0] =
593 acpi_ut_create_integer_object((u64)region_obj->region.space_id);
594 if (!args[0]) {
595 status = AE_NO_MEMORY;
596 goto cleanup1;
597 }
598
599 args[1] = acpi_ut_create_integer_object((u64)function);
600 if (!args[1]) {
601 status = AE_NO_MEMORY;
602 goto cleanup2;
603 }
604
605 args[2] = NULL;
606
607
608
609 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
610 (ACPI_TYPE_METHOD, info->prefix_node, NULL));
611
612 status = acpi_ns_evaluate(info);
613 acpi_ut_remove_reference(args[1]);
614
615 if (ACPI_FAILURE(status)) {
616 goto cleanup2;
617 }
618
619 if (function == ACPI_REG_CONNECT) {
620 region_obj->common.flags |= AOPOBJ_REG_CONNECTED;
621 } else {
622 region_obj->common.flags &= ~AOPOBJ_REG_CONNECTED;
623 }
624
625 cleanup2:
626 acpi_ut_remove_reference(args[0]);
627
628 cleanup1:
629 ACPI_FREE(info);
630 return_ACPI_STATUS(status);
631 }
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648 void
649 acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
650 acpi_adr_space_type space_id, u32 function)
651 {
652 struct acpi_reg_walk_info info;
653
654 ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
655
656
657
658
659
660
661
662
663 if ((space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
664 (space_id == ACPI_ADR_SPACE_SYSTEM_IO) ||
665 (space_id == ACPI_ADR_SPACE_DATA_TABLE)) {
666 return_VOID;
667 }
668
669 info.space_id = space_id;
670 info.function = function;
671 info.reg_run_count = 0;
672
673 ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
674 " Running _REG methods for SpaceId %s\n",
675 acpi_ut_get_region_name(info.space_id)));
676
677
678
679
680
681
682
683 (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
684 ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, NULL,
685 &info, NULL);
686
687
688
689 if (space_id == ACPI_ADR_SPACE_EC) {
690 acpi_ev_orphan_ec_reg_method(node);
691 }
692
693 ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
694 " Executed %u _REG methods for SpaceId %s\n",
695 info.reg_run_count,
696 acpi_ut_get_region_name(info.space_id)));
697
698 return_VOID;
699 }
700
701
702
703
704
705
706
707
708
709
710
711 static acpi_status
712 acpi_ev_reg_run(acpi_handle obj_handle,
713 u32 level, void *context, void **return_value)
714 {
715 union acpi_operand_object *obj_desc;
716 struct acpi_namespace_node *node;
717 acpi_status status;
718 struct acpi_reg_walk_info *info;
719
720 info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context);
721
722
723
724 node = acpi_ns_validate_handle(obj_handle);
725 if (!node) {
726 return (AE_BAD_PARAMETER);
727 }
728
729
730
731
732
733 if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
734 return (AE_OK);
735 }
736
737
738
739 obj_desc = acpi_ns_get_attached_object(node);
740 if (!obj_desc) {
741
742
743
744 return (AE_OK);
745 }
746
747
748
749 if (obj_desc->region.space_id != info->space_id) {
750
751
752
753 return (AE_OK);
754 }
755
756 info->reg_run_count++;
757 status = acpi_ev_execute_reg_method(obj_desc, info->function);
758 return (status);
759 }
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786 static void
787 acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
788 {
789 acpi_handle reg_method;
790 struct acpi_namespace_node *next_node;
791 acpi_status status;
792 struct acpi_object_list args;
793 union acpi_object objects[2];
794
795 ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method);
796
797 if (!ec_device_node) {
798 return_VOID;
799 }
800
801
802
803 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
804
805
806
807 status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, ®_method);
808 if (ACPI_FAILURE(status)) {
809 goto exit;
810 }
811
812
813
814
815
816
817
818
819 next_node = acpi_ns_get_next_node(ec_device_node, NULL);
820 while (next_node) {
821 if ((next_node->type == ACPI_TYPE_REGION) &&
822 (next_node->object) &&
823 (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) {
824 goto exit;
825 }
826
827 next_node = acpi_ns_get_next_node(ec_device_node, next_node);
828 }
829
830
831
832 args.count = 2;
833 args.pointer = objects;
834 objects[0].type = ACPI_TYPE_INTEGER;
835 objects[0].integer.value = ACPI_ADR_SPACE_EC;
836 objects[1].type = ACPI_TYPE_INTEGER;
837 objects[1].integer.value = ACPI_REG_CONNECT;
838
839 status = acpi_evaluate_object(reg_method, NULL, &args, NULL);
840
841 exit:
842
843
844 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
845 return_VOID;
846 }