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