1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: evrgnini- ACPI address_space (op_region) init |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
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("evrgnini" ) |
18 | |
19 | /******************************************************************************* |
20 | * |
21 | * FUNCTION: acpi_ev_system_memory_region_setup |
22 | * |
23 | * PARAMETERS: handle - Region we are interested in |
24 | * function - Start or stop |
25 | * handler_context - Address space handler context |
26 | * region_context - Region specific context |
27 | * |
28 | * RETURN: Status |
29 | * |
30 | * DESCRIPTION: Setup a system_memory operation region |
31 | * |
32 | ******************************************************************************/ |
33 | acpi_status |
34 | acpi_ev_system_memory_region_setup(acpi_handle handle, |
35 | u32 function, |
36 | void *handler_context, void **region_context) |
37 | { |
38 | union acpi_operand_object *region_desc = |
39 | (union acpi_operand_object *)handle; |
40 | struct acpi_mem_space_context *local_region_context; |
41 | struct acpi_mem_mapping *mm; |
42 | |
43 | ACPI_FUNCTION_TRACE(ev_system_memory_region_setup); |
44 | |
45 | if (function == ACPI_REGION_DEACTIVATE) { |
46 | if (*region_context) { |
47 | local_region_context = |
48 | (struct acpi_mem_space_context *)*region_context; |
49 | |
50 | /* Delete memory mappings if present */ |
51 | |
52 | while (local_region_context->first_mm) { |
53 | mm = local_region_context->first_mm; |
54 | local_region_context->first_mm = mm->next_mm; |
55 | acpi_os_unmap_memory(logical_address: mm->logical_address, |
56 | size: mm->length); |
57 | ACPI_FREE(mm); |
58 | } |
59 | ACPI_FREE(local_region_context); |
60 | *region_context = NULL; |
61 | } |
62 | return_ACPI_STATUS(AE_OK); |
63 | } |
64 | |
65 | /* Create a new context */ |
66 | |
67 | local_region_context = |
68 | ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context)); |
69 | if (!(local_region_context)) { |
70 | return_ACPI_STATUS(AE_NO_MEMORY); |
71 | } |
72 | |
73 | /* Save the region length and address for use in the handler */ |
74 | |
75 | local_region_context->length = region_desc->region.length; |
76 | local_region_context->address = region_desc->region.address; |
77 | |
78 | *region_context = local_region_context; |
79 | return_ACPI_STATUS(AE_OK); |
80 | } |
81 | |
82 | /******************************************************************************* |
83 | * |
84 | * FUNCTION: acpi_ev_io_space_region_setup |
85 | * |
86 | * PARAMETERS: handle - Region we are interested in |
87 | * function - Start or stop |
88 | * handler_context - Address space handler context |
89 | * region_context - Region specific context |
90 | * |
91 | * RETURN: Status |
92 | * |
93 | * DESCRIPTION: Setup a IO operation region |
94 | * |
95 | ******************************************************************************/ |
96 | |
97 | acpi_status |
98 | acpi_ev_io_space_region_setup(acpi_handle handle, |
99 | u32 function, |
100 | void *handler_context, void **region_context) |
101 | { |
102 | ACPI_FUNCTION_TRACE(ev_io_space_region_setup); |
103 | |
104 | if (function == ACPI_REGION_DEACTIVATE) { |
105 | *region_context = NULL; |
106 | } else { |
107 | *region_context = handler_context; |
108 | } |
109 | |
110 | return_ACPI_STATUS(AE_OK); |
111 | } |
112 | |
113 | /******************************************************************************* |
114 | * |
115 | * FUNCTION: acpi_ev_pci_config_region_setup |
116 | * |
117 | * PARAMETERS: handle - Region we are interested in |
118 | * function - Start or stop |
119 | * handler_context - Address space handler context |
120 | * region_context - Region specific context |
121 | * |
122 | * RETURN: Status |
123 | * |
124 | * DESCRIPTION: Setup a PCI_Config operation region |
125 | * |
126 | * MUTEX: Assumes namespace is not locked |
127 | * |
128 | ******************************************************************************/ |
129 | |
130 | acpi_status |
131 | acpi_ev_pci_config_region_setup(acpi_handle handle, |
132 | u32 function, |
133 | void *handler_context, void **region_context) |
134 | { |
135 | acpi_status status = AE_OK; |
136 | u64 pci_value; |
137 | struct acpi_pci_id *pci_id = *region_context; |
138 | union acpi_operand_object *handler_obj; |
139 | struct acpi_namespace_node *parent_node; |
140 | struct acpi_namespace_node *pci_root_node; |
141 | struct acpi_namespace_node *pci_device_node; |
142 | union acpi_operand_object *region_obj = |
143 | (union acpi_operand_object *)handle; |
144 | |
145 | ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); |
146 | |
147 | handler_obj = region_obj->region.handler; |
148 | if (!handler_obj) { |
149 | /* |
150 | * No installed handler. This shouldn't happen because the dispatch |
151 | * routine checks before we get here, but we check again just in case. |
152 | */ |
153 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, |
154 | "Attempting to init a region %p, with no handler\n" , |
155 | region_obj)); |
156 | return_ACPI_STATUS(AE_NOT_EXIST); |
157 | } |
158 | |
159 | *region_context = NULL; |
160 | if (function == ACPI_REGION_DEACTIVATE) { |
161 | if (pci_id) { |
162 | ACPI_FREE(pci_id); |
163 | } |
164 | return_ACPI_STATUS(status); |
165 | } |
166 | |
167 | parent_node = region_obj->region.node->parent; |
168 | |
169 | /* |
170 | * Get the _SEG and _BBN values from the device upon which the handler |
171 | * is installed. |
172 | * |
173 | * We need to get the _SEG and _BBN objects relative to the PCI BUS device. |
174 | * This is the device the handler has been registered to handle. |
175 | */ |
176 | |
177 | /* |
178 | * If the address_space.Node is still pointing to the root, we need |
179 | * to scan upward for a PCI Root bridge and re-associate the op_region |
180 | * handlers with that device. |
181 | */ |
182 | if (handler_obj->address_space.node == acpi_gbl_root_node) { |
183 | |
184 | /* Start search from the parent object */ |
185 | |
186 | pci_root_node = parent_node; |
187 | while (pci_root_node != acpi_gbl_root_node) { |
188 | |
189 | /* Get the _HID/_CID in order to detect a root_bridge */ |
190 | |
191 | if (acpi_ev_is_pci_root_bridge(node: pci_root_node)) { |
192 | |
193 | /* Install a handler for this PCI root bridge */ |
194 | |
195 | status = acpi_install_address_space_handler(device: (acpi_handle)pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); |
196 | if (ACPI_FAILURE(status)) { |
197 | if (status == AE_SAME_HANDLER) { |
198 | /* |
199 | * It is OK if the handler is already installed on the |
200 | * root bridge. Still need to return a context object |
201 | * for the new PCI_Config operation region, however. |
202 | */ |
203 | } else { |
204 | ACPI_EXCEPTION((AE_INFO, status, |
205 | "Could not install PciConfig handler " |
206 | "for Root Bridge %4.4s" , |
207 | acpi_ut_get_node_name |
208 | (pci_root_node))); |
209 | } |
210 | } |
211 | break; |
212 | } |
213 | |
214 | pci_root_node = pci_root_node->parent; |
215 | } |
216 | |
217 | /* PCI root bridge not found, use namespace root node */ |
218 | } else { |
219 | pci_root_node = handler_obj->address_space.node; |
220 | } |
221 | |
222 | /* |
223 | * If this region is now initialized, we are done. |
224 | * (install_address_space_handler could have initialized it) |
225 | */ |
226 | if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { |
227 | return_ACPI_STATUS(AE_OK); |
228 | } |
229 | |
230 | /* Region is still not initialized. Create a new context */ |
231 | |
232 | pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); |
233 | if (!pci_id) { |
234 | return_ACPI_STATUS(AE_NO_MEMORY); |
235 | } |
236 | |
237 | /* |
238 | * For PCI_Config space access, we need the segment, bus, device and |
239 | * function numbers. Acquire them here. |
240 | * |
241 | * Find the parent device object. (This allows the operation region to be |
242 | * within a subscope under the device, such as a control method.) |
243 | */ |
244 | pci_device_node = region_obj->region.node; |
245 | while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) { |
246 | pci_device_node = pci_device_node->parent; |
247 | } |
248 | |
249 | if (!pci_device_node) { |
250 | ACPI_FREE(pci_id); |
251 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
252 | } |
253 | |
254 | /* |
255 | * Get the PCI device and function numbers from the _ADR object |
256 | * contained in the parent's scope. |
257 | */ |
258 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, |
259 | device_node: pci_device_node, value: &pci_value); |
260 | |
261 | /* |
262 | * The default is zero, and since the allocation above zeroed the data, |
263 | * just do nothing on failure. |
264 | */ |
265 | if (ACPI_SUCCESS(status)) { |
266 | pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value)); |
267 | pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value)); |
268 | } |
269 | |
270 | /* The PCI segment number comes from the _SEG method */ |
271 | |
272 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, |
273 | device_node: pci_root_node, value: &pci_value); |
274 | if (ACPI_SUCCESS(status)) { |
275 | pci_id->segment = ACPI_LOWORD(pci_value); |
276 | } |
277 | |
278 | /* The PCI bus number comes from the _BBN method */ |
279 | |
280 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, |
281 | device_node: pci_root_node, value: &pci_value); |
282 | if (ACPI_SUCCESS(status)) { |
283 | pci_id->bus = ACPI_LOWORD(pci_value); |
284 | } |
285 | |
286 | /* Complete/update the PCI ID for this device */ |
287 | |
288 | status = |
289 | acpi_hw_derive_pci_id(pci_id, root_pci_device: pci_root_node, |
290 | pci_region: region_obj->region.node); |
291 | if (ACPI_FAILURE(status)) { |
292 | ACPI_FREE(pci_id); |
293 | return_ACPI_STATUS(status); |
294 | } |
295 | |
296 | *region_context = pci_id; |
297 | return_ACPI_STATUS(AE_OK); |
298 | } |
299 | |
300 | /******************************************************************************* |
301 | * |
302 | * FUNCTION: acpi_ev_is_pci_root_bridge |
303 | * |
304 | * PARAMETERS: node - Device node being examined |
305 | * |
306 | * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge |
307 | * |
308 | * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by |
309 | * examining the _HID and _CID for the device. |
310 | * |
311 | ******************************************************************************/ |
312 | |
313 | u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) |
314 | { |
315 | acpi_status status; |
316 | struct acpi_pnp_device_id *hid; |
317 | struct acpi_pnp_device_id_list *cid; |
318 | u32 i; |
319 | u8 match; |
320 | |
321 | /* Get the _HID and check for a PCI Root Bridge */ |
322 | |
323 | status = acpi_ut_execute_HID(device_node: node, return_id: &hid); |
324 | if (ACPI_FAILURE(status)) { |
325 | return (FALSE); |
326 | } |
327 | |
328 | match = acpi_ut_is_pci_root_bridge(id: hid->string); |
329 | ACPI_FREE(hid); |
330 | |
331 | if (match) { |
332 | return (TRUE); |
333 | } |
334 | |
335 | /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ |
336 | |
337 | status = acpi_ut_execute_CID(device_node: node, return_cid_list: &cid); |
338 | if (ACPI_FAILURE(status)) { |
339 | return (FALSE); |
340 | } |
341 | |
342 | /* Check all _CIDs in the returned list */ |
343 | |
344 | for (i = 0; i < cid->count; i++) { |
345 | if (acpi_ut_is_pci_root_bridge(id: cid->ids[i].string)) { |
346 | ACPI_FREE(cid); |
347 | return (TRUE); |
348 | } |
349 | } |
350 | |
351 | ACPI_FREE(cid); |
352 | return (FALSE); |
353 | } |
354 | |
355 | /******************************************************************************* |
356 | * |
357 | * FUNCTION: acpi_ev_pci_bar_region_setup |
358 | * |
359 | * PARAMETERS: handle - Region we are interested in |
360 | * function - Start or stop |
361 | * handler_context - Address space handler context |
362 | * region_context - Region specific context |
363 | * |
364 | * RETURN: Status |
365 | * |
366 | * DESCRIPTION: Setup a pci_BAR operation region |
367 | * |
368 | * MUTEX: Assumes namespace is not locked |
369 | * |
370 | ******************************************************************************/ |
371 | |
372 | acpi_status |
373 | acpi_ev_pci_bar_region_setup(acpi_handle handle, |
374 | u32 function, |
375 | void *handler_context, void **region_context) |
376 | { |
377 | ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup); |
378 | |
379 | return_ACPI_STATUS(AE_OK); |
380 | } |
381 | |
382 | /******************************************************************************* |
383 | * |
384 | * FUNCTION: acpi_ev_cmos_region_setup |
385 | * |
386 | * PARAMETERS: handle - Region we are interested in |
387 | * function - Start or stop |
388 | * handler_context - Address space handler context |
389 | * region_context - Region specific context |
390 | * |
391 | * RETURN: Status |
392 | * |
393 | * DESCRIPTION: Setup a CMOS operation region |
394 | * |
395 | * MUTEX: Assumes namespace is not locked |
396 | * |
397 | ******************************************************************************/ |
398 | |
399 | acpi_status |
400 | acpi_ev_cmos_region_setup(acpi_handle handle, |
401 | u32 function, |
402 | void *handler_context, void **region_context) |
403 | { |
404 | ACPI_FUNCTION_TRACE(ev_cmos_region_setup); |
405 | |
406 | return_ACPI_STATUS(AE_OK); |
407 | } |
408 | |
409 | /******************************************************************************* |
410 | * |
411 | * FUNCTION: acpi_ev_data_table_region_setup |
412 | * |
413 | * PARAMETERS: handle - Region we are interested in |
414 | * function - Start or stop |
415 | * handler_context - Address space handler context |
416 | * region_context - Region specific context |
417 | * |
418 | * RETURN: Status |
419 | * |
420 | * DESCRIPTION: Setup a data_table_region |
421 | * |
422 | * MUTEX: Assumes namespace is not locked |
423 | * |
424 | ******************************************************************************/ |
425 | |
426 | acpi_status |
427 | acpi_ev_data_table_region_setup(acpi_handle handle, |
428 | u32 function, |
429 | void *handler_context, void **region_context) |
430 | { |
431 | union acpi_operand_object *region_desc = |
432 | (union acpi_operand_object *)handle; |
433 | struct acpi_data_table_mapping *local_region_context; |
434 | |
435 | ACPI_FUNCTION_TRACE(ev_data_table_region_setup); |
436 | |
437 | if (function == ACPI_REGION_DEACTIVATE) { |
438 | if (*region_context) { |
439 | ACPI_FREE(*region_context); |
440 | *region_context = NULL; |
441 | } |
442 | return_ACPI_STATUS(AE_OK); |
443 | } |
444 | |
445 | /* Create a new context */ |
446 | |
447 | local_region_context = |
448 | ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_data_table_mapping)); |
449 | if (!(local_region_context)) { |
450 | return_ACPI_STATUS(AE_NO_MEMORY); |
451 | } |
452 | |
453 | /* Save the data table pointer for use in the handler */ |
454 | |
455 | local_region_context->pointer = region_desc->region.pointer; |
456 | |
457 | *region_context = local_region_context; |
458 | return_ACPI_STATUS(AE_OK); |
459 | } |
460 | |
461 | /******************************************************************************* |
462 | * |
463 | * FUNCTION: acpi_ev_default_region_setup |
464 | * |
465 | * PARAMETERS: handle - Region we are interested in |
466 | * function - Start or stop |
467 | * handler_context - Address space handler context |
468 | * region_context - Region specific context |
469 | * |
470 | * RETURN: Status |
471 | * |
472 | * DESCRIPTION: Default region initialization |
473 | * |
474 | ******************************************************************************/ |
475 | |
476 | acpi_status |
477 | acpi_ev_default_region_setup(acpi_handle handle, |
478 | u32 function, |
479 | void *handler_context, void **region_context) |
480 | { |
481 | ACPI_FUNCTION_TRACE(ev_default_region_setup); |
482 | |
483 | if (function == ACPI_REGION_DEACTIVATE) { |
484 | *region_context = NULL; |
485 | } else { |
486 | *region_context = handler_context; |
487 | } |
488 | |
489 | return_ACPI_STATUS(AE_OK); |
490 | } |
491 | |
492 | /******************************************************************************* |
493 | * |
494 | * FUNCTION: acpi_ev_initialize_region |
495 | * |
496 | * PARAMETERS: region_obj - Region we are initializing |
497 | * |
498 | * RETURN: Status |
499 | * |
500 | * DESCRIPTION: Initializes the region, finds any _REG methods and saves them |
501 | * for execution at a later time |
502 | * |
503 | * Get the appropriate address space handler for a newly |
504 | * created region. |
505 | * |
506 | * This also performs address space specific initialization. For |
507 | * example, PCI regions must have an _ADR object that contains |
508 | * a PCI address in the scope of the definition. This address is |
509 | * required to perform an access to PCI config space. |
510 | * |
511 | * MUTEX: Interpreter should be unlocked, because we may run the _REG |
512 | * method for this region. |
513 | * |
514 | * NOTE: Possible incompliance: |
515 | * There is a behavior conflict in automatic _REG execution: |
516 | * 1. When the interpreter is evaluating a method, we can only |
517 | * automatically run _REG for the following case: |
518 | * operation_region (OPR1, 0x80, 0x1000010, 0x4) |
519 | * 2. When the interpreter is loading a table, we can also |
520 | * automatically run _REG for the following case: |
521 | * operation_region (OPR1, 0x80, 0x1000010, 0x4) |
522 | * Though this may not be compliant to the de-facto standard, the |
523 | * logic is kept in order not to trigger regressions. And keeping |
524 | * this logic should be taken care by the caller of this function. |
525 | * |
526 | ******************************************************************************/ |
527 | |
528 | acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj) |
529 | { |
530 | union acpi_operand_object *handler_obj; |
531 | union acpi_operand_object *obj_desc; |
532 | acpi_adr_space_type space_id; |
533 | struct acpi_namespace_node *node; |
534 | |
535 | ACPI_FUNCTION_TRACE(ev_initialize_region); |
536 | |
537 | if (!region_obj) { |
538 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
539 | } |
540 | |
541 | if (region_obj->common.flags & AOPOBJ_OBJECT_INITIALIZED) { |
542 | return_ACPI_STATUS(AE_OK); |
543 | } |
544 | |
545 | region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; |
546 | |
547 | node = region_obj->region.node->parent; |
548 | space_id = region_obj->region.space_id; |
549 | |
550 | /* |
551 | * The following loop depends upon the root Node having no parent |
552 | * ie: acpi_gbl_root_node->Parent being set to NULL |
553 | */ |
554 | while (node) { |
555 | |
556 | /* Check to see if a handler exists */ |
557 | |
558 | handler_obj = NULL; |
559 | obj_desc = acpi_ns_get_attached_object(node); |
560 | if (obj_desc) { |
561 | |
562 | /* Can only be a handler if the object exists */ |
563 | |
564 | switch (node->type) { |
565 | case ACPI_TYPE_DEVICE: |
566 | case ACPI_TYPE_PROCESSOR: |
567 | case ACPI_TYPE_THERMAL: |
568 | |
569 | handler_obj = obj_desc->common_notify.handler; |
570 | break; |
571 | |
572 | default: |
573 | |
574 | /* Ignore other objects */ |
575 | |
576 | break; |
577 | } |
578 | |
579 | handler_obj = |
580 | acpi_ev_find_region_handler(space_id, handler_obj); |
581 | if (handler_obj) { |
582 | |
583 | /* Found correct handler */ |
584 | |
585 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, |
586 | "Found handler %p for region %p in obj %p\n" , |
587 | handler_obj, region_obj, |
588 | obj_desc)); |
589 | |
590 | (void)acpi_ev_attach_region(handler_obj, |
591 | region_obj, FALSE); |
592 | |
593 | /* |
594 | * Tell all users that this region is usable by |
595 | * running the _REG method |
596 | */ |
597 | acpi_ex_exit_interpreter(); |
598 | (void)acpi_ev_execute_reg_method(region_obj, |
599 | ACPI_REG_CONNECT); |
600 | acpi_ex_enter_interpreter(); |
601 | return_ACPI_STATUS(AE_OK); |
602 | } |
603 | } |
604 | |
605 | /* This node does not have the handler we need; Pop up one level */ |
606 | |
607 | node = node->parent; |
608 | } |
609 | |
610 | /* |
611 | * If we get here, there is no handler for this region. This is not |
612 | * fatal because many regions get created before a handler is installed |
613 | * for said region. |
614 | */ |
615 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, |
616 | "No handler for RegionType %s(%X) (RegionObj %p)\n" , |
617 | acpi_ut_get_region_name(space_id), space_id, |
618 | region_obj)); |
619 | |
620 | return_ACPI_STATUS(AE_OK); |
621 | } |
622 | |