Commit | Line | Data |
---|---|---|
99575102 LZ |
1 | /******************************************************************************* |
2 | * | |
3 | * Module Name: dbcmds - Miscellaneous debug commands and output routines | |
4 | * | |
5 | ******************************************************************************/ | |
6 | ||
7 | /* | |
c8100dc4 | 8 | * Copyright (C) 2000 - 2016, Intel Corp. |
99575102 LZ |
9 | * All rights reserved. |
10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions, and the following disclaimer, | |
16 | * without modification. | |
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | |
18 | * substantially similar to the "NO WARRANTY" disclaimer below | |
19 | * ("Disclaimer") and any redistribution must be conditioned upon | |
20 | * including a substantially similar Disclaimer requirement for further | |
21 | * binary redistribution. | |
22 | * 3. Neither the names of the above-listed copyright holders nor the names | |
23 | * of any contributors may be used to endorse or promote products derived | |
24 | * from this software without specific prior written permission. | |
25 | * | |
26 | * Alternatively, this software may be distributed under the terms of the | |
27 | * GNU General Public License ("GPL") version 2 as published by the Free | |
28 | * Software Foundation. | |
29 | * | |
30 | * NO WARRANTY | |
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | |
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
41 | * POSSIBILITY OF SUCH DAMAGES. | |
42 | */ | |
43 | ||
44 | #include <acpi/acpi.h> | |
45 | #include "accommon.h" | |
46 | #include "acevents.h" | |
47 | #include "acdebug.h" | |
48 | #include "acnamesp.h" | |
49 | #include "acresrc.h" | |
50 | #include "actables.h" | |
51 | ||
52 | #define _COMPONENT ACPI_CA_DEBUGGER | |
53 | ACPI_MODULE_NAME("dbcmds") | |
54 | ||
55 | /* Local prototypes */ | |
56 | static void | |
57 | acpi_dm_compare_aml_resources(u8 *aml1_buffer, | |
58 | acpi_rsdesc_size aml1_buffer_length, | |
59 | u8 *aml2_buffer, | |
60 | acpi_rsdesc_size aml2_buffer_length); | |
61 | ||
62 | static acpi_status | |
63 | acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name); | |
64 | ||
65 | static acpi_status | |
66 | acpi_db_resource_callback(struct acpi_resource *resource, void *context); | |
67 | ||
68 | static acpi_status | |
69 | acpi_db_device_resources(acpi_handle obj_handle, | |
70 | u32 nesting_level, void *context, void **return_value); | |
71 | ||
72 | static void acpi_db_do_one_sleep_state(u8 sleep_state); | |
73 | ||
74 | static char *acpi_db_trace_method_name = NULL; | |
75 | ||
76 | /******************************************************************************* | |
77 | * | |
78 | * FUNCTION: acpi_db_convert_to_node | |
79 | * | |
80 | * PARAMETERS: in_string - String to convert | |
81 | * | |
82 | * RETURN: Pointer to a NS node | |
83 | * | |
84 | * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or | |
85 | * alphanumeric strings. | |
86 | * | |
87 | ******************************************************************************/ | |
88 | ||
89 | struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string) | |
90 | { | |
91 | struct acpi_namespace_node *node; | |
92 | acpi_size address; | |
93 | ||
94 | if ((*in_string >= 0x30) && (*in_string <= 0x39)) { | |
95 | ||
96 | /* Numeric argument, convert */ | |
97 | ||
98 | address = strtoul(in_string, NULL, 16); | |
99 | node = ACPI_TO_POINTER(address); | |
100 | if (!acpi_os_readable(node, sizeof(struct acpi_namespace_node))) { | |
101 | acpi_os_printf("Address %p is invalid", node); | |
102 | return (NULL); | |
103 | } | |
104 | ||
105 | /* Make sure pointer is valid NS node */ | |
106 | ||
107 | if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { | |
108 | acpi_os_printf | |
109 | ("Address %p is not a valid namespace node [%s]\n", | |
110 | node, acpi_ut_get_descriptor_name(node)); | |
111 | return (NULL); | |
112 | } | |
113 | } else { | |
114 | /* | |
115 | * Alpha argument: The parameter is a name string that must be | |
116 | * resolved to a Namespace object. | |
117 | */ | |
118 | node = acpi_db_local_ns_lookup(in_string); | |
119 | if (!node) { | |
120 | acpi_os_printf | |
121 | ("Could not find [%s] in namespace, defaulting to root node\n", | |
122 | in_string); | |
123 | node = acpi_gbl_root_node; | |
124 | } | |
125 | } | |
126 | ||
127 | return (node); | |
128 | } | |
129 | ||
130 | /******************************************************************************* | |
131 | * | |
132 | * FUNCTION: acpi_db_sleep | |
133 | * | |
134 | * PARAMETERS: object_arg - Desired sleep state (0-5). NULL means | |
135 | * invoke all possible sleep states. | |
136 | * | |
137 | * RETURN: Status | |
138 | * | |
139 | * DESCRIPTION: Simulate sleep/wake sequences | |
140 | * | |
141 | ******************************************************************************/ | |
142 | ||
143 | acpi_status acpi_db_sleep(char *object_arg) | |
144 | { | |
145 | u8 sleep_state; | |
146 | u32 i; | |
147 | ||
148 | ACPI_FUNCTION_TRACE(acpi_db_sleep); | |
149 | ||
150 | /* Null input (no arguments) means to invoke all sleep states */ | |
151 | ||
152 | if (!object_arg) { | |
153 | acpi_os_printf("Invoking all possible sleep states, 0-%d\n", | |
154 | ACPI_S_STATES_MAX); | |
155 | ||
156 | for (i = 0; i <= ACPI_S_STATES_MAX; i++) { | |
157 | acpi_db_do_one_sleep_state((u8)i); | |
158 | } | |
159 | ||
160 | return_ACPI_STATUS(AE_OK); | |
161 | } | |
162 | ||
163 | /* Convert argument to binary and invoke the sleep state */ | |
164 | ||
165 | sleep_state = (u8)strtoul(object_arg, NULL, 0); | |
166 | acpi_db_do_one_sleep_state(sleep_state); | |
167 | return_ACPI_STATUS(AE_OK); | |
168 | } | |
169 | ||
170 | /******************************************************************************* | |
171 | * | |
172 | * FUNCTION: acpi_db_do_one_sleep_state | |
173 | * | |
174 | * PARAMETERS: sleep_state - Desired sleep state (0-5) | |
175 | * | |
176 | * RETURN: None | |
177 | * | |
178 | * DESCRIPTION: Simulate a sleep/wake sequence | |
179 | * | |
180 | ******************************************************************************/ | |
181 | ||
182 | static void acpi_db_do_one_sleep_state(u8 sleep_state) | |
183 | { | |
184 | acpi_status status; | |
185 | u8 sleep_type_a; | |
186 | u8 sleep_type_b; | |
187 | ||
188 | /* Validate parameter */ | |
189 | ||
190 | if (sleep_state > ACPI_S_STATES_MAX) { | |
191 | acpi_os_printf("Sleep state %d out of range (%d max)\n", | |
192 | sleep_state, ACPI_S_STATES_MAX); | |
193 | return; | |
194 | } | |
195 | ||
196 | acpi_os_printf("\n---- Invoking sleep state S%d (%s):\n", | |
197 | sleep_state, acpi_gbl_sleep_state_names[sleep_state]); | |
198 | ||
199 | /* Get the values for the sleep type registers (for display only) */ | |
200 | ||
201 | status = | |
202 | acpi_get_sleep_type_data(sleep_state, &sleep_type_a, &sleep_type_b); | |
203 | if (ACPI_FAILURE(status)) { | |
204 | acpi_os_printf("Could not evaluate [%s] method, %s\n", | |
205 | acpi_gbl_sleep_state_names[sleep_state], | |
206 | acpi_format_exception(status)); | |
207 | return; | |
208 | } | |
209 | ||
210 | acpi_os_printf | |
211 | ("Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n", | |
212 | sleep_state, sleep_type_a, sleep_type_b); | |
213 | ||
214 | /* Invoke the various sleep/wake interfaces */ | |
215 | ||
216 | acpi_os_printf("**** Sleep: Prepare to sleep (S%d) ****\n", | |
217 | sleep_state); | |
218 | status = acpi_enter_sleep_state_prep(sleep_state); | |
219 | if (ACPI_FAILURE(status)) { | |
220 | goto error_exit; | |
221 | } | |
222 | ||
223 | acpi_os_printf("**** Sleep: Going to sleep (S%d) ****\n", sleep_state); | |
224 | status = acpi_enter_sleep_state(sleep_state); | |
225 | if (ACPI_FAILURE(status)) { | |
226 | goto error_exit; | |
227 | } | |
228 | ||
229 | acpi_os_printf("**** Wake: Prepare to return from sleep (S%d) ****\n", | |
230 | sleep_state); | |
231 | status = acpi_leave_sleep_state_prep(sleep_state); | |
232 | if (ACPI_FAILURE(status)) { | |
233 | goto error_exit; | |
234 | } | |
235 | ||
236 | acpi_os_printf("**** Wake: Return from sleep (S%d) ****\n", | |
237 | sleep_state); | |
238 | status = acpi_leave_sleep_state(sleep_state); | |
239 | if (ACPI_FAILURE(status)) { | |
240 | goto error_exit; | |
241 | } | |
242 | ||
243 | return; | |
244 | ||
245 | error_exit: | |
246 | ACPI_EXCEPTION((AE_INFO, status, "During invocation of sleep state S%d", | |
247 | sleep_state)); | |
248 | } | |
249 | ||
250 | /******************************************************************************* | |
251 | * | |
252 | * FUNCTION: acpi_db_display_locks | |
253 | * | |
254 | * PARAMETERS: None | |
255 | * | |
256 | * RETURN: None | |
257 | * | |
258 | * DESCRIPTION: Display information about internal mutexes. | |
259 | * | |
260 | ******************************************************************************/ | |
261 | ||
262 | void acpi_db_display_locks(void) | |
263 | { | |
264 | u32 i; | |
265 | ||
266 | for (i = 0; i < ACPI_MAX_MUTEX; i++) { | |
267 | acpi_os_printf("%26s : %s\n", acpi_ut_get_mutex_name(i), | |
268 | acpi_gbl_mutex_info[i].thread_id == | |
269 | ACPI_MUTEX_NOT_ACQUIRED ? "Locked" : "Unlocked"); | |
270 | } | |
271 | } | |
272 | ||
273 | /******************************************************************************* | |
274 | * | |
275 | * FUNCTION: acpi_db_display_table_info | |
276 | * | |
277 | * PARAMETERS: table_arg - Name of table to be displayed | |
278 | * | |
279 | * RETURN: None | |
280 | * | |
281 | * DESCRIPTION: Display information about loaded tables. Current | |
282 | * implementation displays all loaded tables. | |
283 | * | |
284 | ******************************************************************************/ | |
285 | ||
286 | void acpi_db_display_table_info(char *table_arg) | |
287 | { | |
288 | u32 i; | |
289 | struct acpi_table_desc *table_desc; | |
290 | acpi_status status; | |
291 | ||
292 | /* Header */ | |
293 | ||
294 | acpi_os_printf("Idx ID Status Type " | |
295 | "TableHeader (Sig, Address, Length, Misc)\n"); | |
296 | ||
297 | /* Walk the entire root table list */ | |
298 | ||
299 | for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { | |
300 | table_desc = &acpi_gbl_root_table_list.tables[i]; | |
301 | ||
302 | /* Index and Table ID */ | |
303 | ||
304 | acpi_os_printf("%3u %.2u ", i, table_desc->owner_id); | |
305 | ||
306 | /* Decode the table flags */ | |
307 | ||
308 | if (!(table_desc->flags & ACPI_TABLE_IS_LOADED)) { | |
309 | acpi_os_printf("NotLoaded "); | |
310 | } else { | |
311 | acpi_os_printf(" Loaded "); | |
312 | } | |
313 | ||
314 | switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { | |
315 | case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: | |
316 | ||
317 | acpi_os_printf("External/virtual "); | |
318 | break; | |
319 | ||
320 | case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: | |
321 | ||
322 | acpi_os_printf("Internal/physical "); | |
323 | break; | |
324 | ||
325 | case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: | |
326 | ||
327 | acpi_os_printf("Internal/virtual "); | |
328 | break; | |
329 | ||
330 | default: | |
331 | ||
332 | acpi_os_printf("INVALID TYPE "); | |
333 | break; | |
334 | } | |
335 | ||
336 | /* Make sure that the table is mapped */ | |
337 | ||
338 | status = acpi_tb_validate_table(table_desc); | |
339 | if (ACPI_FAILURE(status)) { | |
340 | return; | |
341 | } | |
342 | ||
343 | /* Dump the table header */ | |
344 | ||
345 | if (table_desc->pointer) { | |
346 | acpi_tb_print_table_header(table_desc->address, | |
347 | table_desc->pointer); | |
348 | } else { | |
349 | /* If the pointer is null, the table has been unloaded */ | |
350 | ||
351 | ACPI_INFO((AE_INFO, "%4.4s - Table has been unloaded", | |
352 | table_desc->signature.ascii)); | |
353 | } | |
354 | } | |
355 | } | |
356 | ||
357 | /******************************************************************************* | |
358 | * | |
359 | * FUNCTION: acpi_db_unload_acpi_table | |
360 | * | |
361 | * PARAMETERS: object_name - Namespace pathname for an object that | |
362 | * is owned by the table to be unloaded | |
363 | * | |
364 | * RETURN: None | |
365 | * | |
366 | * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned | |
367 | * by the table. | |
368 | * | |
369 | ******************************************************************************/ | |
370 | ||
371 | void acpi_db_unload_acpi_table(char *object_name) | |
372 | { | |
373 | struct acpi_namespace_node *node; | |
374 | acpi_status status; | |
375 | ||
376 | /* Translate name to an Named object */ | |
377 | ||
378 | node = acpi_db_convert_to_node(object_name); | |
379 | if (!node) { | |
380 | return; | |
381 | } | |
382 | ||
383 | status = acpi_unload_parent_table(ACPI_CAST_PTR(acpi_handle, node)); | |
384 | if (ACPI_SUCCESS(status)) { | |
385 | acpi_os_printf("Parent of [%s] (%p) unloaded and uninstalled\n", | |
386 | object_name, node); | |
387 | } else { | |
388 | acpi_os_printf("%s, while unloading parent table of [%s]\n", | |
389 | acpi_format_exception(status), object_name); | |
390 | } | |
391 | } | |
392 | ||
393 | /******************************************************************************* | |
394 | * | |
395 | * FUNCTION: acpi_db_send_notify | |
396 | * | |
397 | * PARAMETERS: name - Name of ACPI object where to send notify | |
398 | * value - Value of the notify to send. | |
399 | * | |
400 | * RETURN: None | |
401 | * | |
402 | * DESCRIPTION: Send an ACPI notification. The value specified is sent to the | |
403 | * named object as an ACPI notify. | |
404 | * | |
405 | ******************************************************************************/ | |
406 | ||
407 | void acpi_db_send_notify(char *name, u32 value) | |
408 | { | |
409 | struct acpi_namespace_node *node; | |
410 | acpi_status status; | |
411 | ||
412 | /* Translate name to an Named object */ | |
413 | ||
414 | node = acpi_db_convert_to_node(name); | |
415 | if (!node) { | |
416 | return; | |
417 | } | |
418 | ||
419 | /* Dispatch the notify if legal */ | |
420 | ||
421 | if (acpi_ev_is_notify_object(node)) { | |
422 | status = acpi_ev_queue_notify_request(node, value); | |
423 | if (ACPI_FAILURE(status)) { | |
424 | acpi_os_printf("Could not queue notify\n"); | |
425 | } | |
426 | } else { | |
427 | acpi_os_printf("Named object [%4.4s] Type %s, " | |
428 | "must be Device/Thermal/Processor type\n", | |
429 | acpi_ut_get_node_name(node), | |
430 | acpi_ut_get_type_name(node->type)); | |
431 | } | |
432 | } | |
433 | ||
434 | /******************************************************************************* | |
435 | * | |
436 | * FUNCTION: acpi_db_display_interfaces | |
437 | * | |
438 | * PARAMETERS: action_arg - Null, "install", or "remove" | |
439 | * interface_name_arg - Name for install/remove options | |
440 | * | |
441 | * RETURN: None | |
442 | * | |
443 | * DESCRIPTION: Display or modify the global _OSI interface list | |
444 | * | |
445 | ******************************************************************************/ | |
446 | ||
447 | void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg) | |
448 | { | |
449 | struct acpi_interface_info *next_interface; | |
450 | char *sub_string; | |
451 | acpi_status status; | |
452 | ||
453 | /* If no arguments, just display current interface list */ | |
454 | ||
455 | if (!action_arg) { | |
456 | (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, | |
457 | ACPI_WAIT_FOREVER); | |
458 | ||
459 | next_interface = acpi_gbl_supported_interfaces; | |
460 | while (next_interface) { | |
461 | if (!(next_interface->flags & ACPI_OSI_INVALID)) { | |
462 | acpi_os_printf("%s\n", next_interface->name); | |
463 | } | |
464 | ||
465 | next_interface = next_interface->next; | |
466 | } | |
467 | ||
468 | acpi_os_release_mutex(acpi_gbl_osi_mutex); | |
469 | return; | |
470 | } | |
471 | ||
472 | /* If action_arg exists, so must interface_name_arg */ | |
473 | ||
474 | if (!interface_name_arg) { | |
475 | acpi_os_printf("Missing Interface Name argument\n"); | |
476 | return; | |
477 | } | |
478 | ||
479 | /* Uppercase the action for match below */ | |
480 | ||
481 | acpi_ut_strupr(action_arg); | |
482 | ||
483 | /* install - install an interface */ | |
484 | ||
485 | sub_string = strstr("INSTALL", action_arg); | |
486 | if (sub_string) { | |
487 | status = acpi_install_interface(interface_name_arg); | |
488 | if (ACPI_FAILURE(status)) { | |
489 | acpi_os_printf("%s, while installing \"%s\"\n", | |
490 | acpi_format_exception(status), | |
491 | interface_name_arg); | |
492 | } | |
493 | return; | |
494 | } | |
495 | ||
496 | /* remove - remove an interface */ | |
497 | ||
498 | sub_string = strstr("REMOVE", action_arg); | |
499 | if (sub_string) { | |
500 | status = acpi_remove_interface(interface_name_arg); | |
501 | if (ACPI_FAILURE(status)) { | |
502 | acpi_os_printf("%s, while removing \"%s\"\n", | |
503 | acpi_format_exception(status), | |
504 | interface_name_arg); | |
505 | } | |
506 | return; | |
507 | } | |
508 | ||
509 | /* Invalid action_arg */ | |
510 | ||
511 | acpi_os_printf("Invalid action argument: %s\n", action_arg); | |
512 | return; | |
513 | } | |
514 | ||
515 | /******************************************************************************* | |
516 | * | |
517 | * FUNCTION: acpi_db_display_template | |
518 | * | |
519 | * PARAMETERS: buffer_arg - Buffer name or address | |
520 | * | |
521 | * RETURN: None | |
522 | * | |
523 | * DESCRIPTION: Dump a buffer that contains a resource template | |
524 | * | |
525 | ******************************************************************************/ | |
526 | ||
527 | void acpi_db_display_template(char *buffer_arg) | |
528 | { | |
529 | struct acpi_namespace_node *node; | |
530 | acpi_status status; | |
531 | struct acpi_buffer return_buffer; | |
532 | ||
533 | /* Translate buffer_arg to an Named object */ | |
534 | ||
535 | node = acpi_db_convert_to_node(buffer_arg); | |
536 | if (!node || (node == acpi_gbl_root_node)) { | |
537 | acpi_os_printf("Invalid argument: %s\n", buffer_arg); | |
538 | return; | |
539 | } | |
540 | ||
541 | /* We must have a buffer object */ | |
542 | ||
543 | if (node->type != ACPI_TYPE_BUFFER) { | |
544 | acpi_os_printf | |
545 | ("Not a Buffer object, cannot be a template: %s\n", | |
546 | buffer_arg); | |
547 | return; | |
548 | } | |
549 | ||
550 | return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; | |
551 | return_buffer.pointer = acpi_gbl_db_buffer; | |
552 | ||
553 | /* Attempt to convert the raw buffer to a resource list */ | |
554 | ||
555 | status = acpi_rs_create_resource_list(node->object, &return_buffer); | |
556 | ||
557 | acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); | |
558 | acpi_dbg_level |= ACPI_LV_RESOURCES; | |
559 | ||
560 | if (ACPI_FAILURE(status)) { | |
561 | acpi_os_printf | |
562 | ("Could not convert Buffer to a resource list: %s, %s\n", | |
563 | buffer_arg, acpi_format_exception(status)); | |
564 | goto dump_buffer; | |
565 | } | |
566 | ||
567 | /* Now we can dump the resource list */ | |
568 | ||
569 | acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource, | |
570 | return_buffer.pointer)); | |
571 | ||
572 | dump_buffer: | |
573 | acpi_os_printf("\nRaw data buffer:\n"); | |
574 | acpi_ut_debug_dump_buffer((u8 *)node->object->buffer.pointer, | |
575 | node->object->buffer.length, | |
576 | DB_BYTE_DISPLAY, ACPI_UINT32_MAX); | |
577 | ||
578 | acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); | |
579 | return; | |
580 | } | |
581 | ||
582 | /******************************************************************************* | |
583 | * | |
584 | * FUNCTION: acpi_dm_compare_aml_resources | |
585 | * | |
586 | * PARAMETERS: aml1_buffer - Contains first resource list | |
587 | * aml1_buffer_length - Length of first resource list | |
588 | * aml2_buffer - Contains second resource list | |
589 | * aml2_buffer_length - Length of second resource list | |
590 | * | |
591 | * RETURN: None | |
592 | * | |
593 | * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in | |
594 | * order to isolate a miscompare to an individual resource) | |
595 | * | |
596 | ******************************************************************************/ | |
597 | ||
598 | static void | |
599 | acpi_dm_compare_aml_resources(u8 *aml1_buffer, | |
600 | acpi_rsdesc_size aml1_buffer_length, | |
601 | u8 *aml2_buffer, | |
602 | acpi_rsdesc_size aml2_buffer_length) | |
603 | { | |
604 | u8 *aml1; | |
605 | u8 *aml2; | |
606 | u8 *aml1_end; | |
607 | u8 *aml2_end; | |
608 | acpi_rsdesc_size aml1_length; | |
609 | acpi_rsdesc_size aml2_length; | |
610 | acpi_rsdesc_size offset = 0; | |
611 | u8 resource_type; | |
612 | u32 count = 0; | |
613 | u32 i; | |
614 | ||
615 | /* Compare overall buffer sizes (may be different due to size rounding) */ | |
616 | ||
617 | if (aml1_buffer_length != aml2_buffer_length) { | |
618 | acpi_os_printf("**** Buffer length mismatch in converted " | |
619 | "AML: Original %X, New %X ****\n", | |
620 | aml1_buffer_length, aml2_buffer_length); | |
621 | } | |
622 | ||
623 | aml1 = aml1_buffer; | |
624 | aml2 = aml2_buffer; | |
625 | aml1_end = aml1_buffer + aml1_buffer_length; | |
626 | aml2_end = aml2_buffer + aml2_buffer_length; | |
627 | ||
628 | /* Walk the descriptor lists, comparing each descriptor */ | |
629 | ||
630 | while ((aml1 < aml1_end) && (aml2 < aml2_end)) { | |
631 | ||
632 | /* Get the lengths of each descriptor */ | |
633 | ||
634 | aml1_length = acpi_ut_get_descriptor_length(aml1); | |
635 | aml2_length = acpi_ut_get_descriptor_length(aml2); | |
636 | resource_type = acpi_ut_get_resource_type(aml1); | |
637 | ||
638 | /* Check for descriptor length match */ | |
639 | ||
640 | if (aml1_length != aml2_length) { | |
641 | acpi_os_printf | |
642 | ("**** Length mismatch in descriptor [%.2X] type %2.2X, " | |
643 | "Offset %8.8X Len1 %X, Len2 %X ****\n", count, | |
644 | resource_type, offset, aml1_length, aml2_length); | |
645 | } | |
646 | ||
647 | /* Check for descriptor byte match */ | |
648 | ||
649 | else if (memcmp(aml1, aml2, aml1_length)) { | |
650 | acpi_os_printf | |
651 | ("**** Data mismatch in descriptor [%.2X] type %2.2X, " | |
652 | "Offset %8.8X ****\n", count, resource_type, | |
653 | offset); | |
654 | ||
655 | for (i = 0; i < aml1_length; i++) { | |
656 | if (aml1[i] != aml2[i]) { | |
657 | acpi_os_printf | |
658 | ("Mismatch at byte offset %.2X: is %2.2X, " | |
659 | "should be %2.2X\n", i, aml2[i], | |
660 | aml1[i]); | |
661 | } | |
662 | } | |
663 | } | |
664 | ||
665 | /* Exit on end_tag descriptor */ | |
666 | ||
667 | if (resource_type == ACPI_RESOURCE_NAME_END_TAG) { | |
668 | return; | |
669 | } | |
670 | ||
671 | /* Point to next descriptor in each buffer */ | |
672 | ||
673 | count++; | |
674 | offset += aml1_length; | |
675 | aml1 += aml1_length; | |
676 | aml2 += aml2_length; | |
677 | } | |
678 | } | |
679 | ||
680 | /******************************************************************************* | |
681 | * | |
682 | * FUNCTION: acpi_dm_test_resource_conversion | |
683 | * | |
684 | * PARAMETERS: node - Parent device node | |
685 | * name - resource method name (_CRS) | |
686 | * | |
687 | * RETURN: Status | |
688 | * | |
689 | * DESCRIPTION: Compare the original AML with a conversion of the AML to | |
690 | * internal resource list, then back to AML. | |
691 | * | |
692 | ******************************************************************************/ | |
693 | ||
694 | static acpi_status | |
695 | acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name) | |
696 | { | |
697 | acpi_status status; | |
698 | struct acpi_buffer return_buffer; | |
699 | struct acpi_buffer resource_buffer; | |
700 | struct acpi_buffer new_aml; | |
701 | union acpi_object *original_aml; | |
702 | ||
703 | acpi_os_printf("Resource Conversion Comparison:\n"); | |
704 | ||
705 | new_aml.length = ACPI_ALLOCATE_LOCAL_BUFFER; | |
706 | return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | |
707 | resource_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | |
708 | ||
709 | /* Get the original _CRS AML resource template */ | |
710 | ||
711 | status = acpi_evaluate_object(node, name, NULL, &return_buffer); | |
712 | if (ACPI_FAILURE(status)) { | |
713 | acpi_os_printf("Could not obtain %s: %s\n", | |
714 | name, acpi_format_exception(status)); | |
715 | return (status); | |
716 | } | |
717 | ||
718 | /* Get the AML resource template, converted to internal resource structs */ | |
719 | ||
720 | status = acpi_get_current_resources(node, &resource_buffer); | |
721 | if (ACPI_FAILURE(status)) { | |
722 | acpi_os_printf("AcpiGetCurrentResources failed: %s\n", | |
723 | acpi_format_exception(status)); | |
724 | goto exit1; | |
725 | } | |
726 | ||
727 | /* Convert internal resource list to external AML resource template */ | |
728 | ||
729 | status = acpi_rs_create_aml_resources(&resource_buffer, &new_aml); | |
730 | if (ACPI_FAILURE(status)) { | |
731 | acpi_os_printf("AcpiRsCreateAmlResources failed: %s\n", | |
732 | acpi_format_exception(status)); | |
733 | goto exit2; | |
734 | } | |
735 | ||
736 | /* Compare original AML to the newly created AML resource list */ | |
737 | ||
738 | original_aml = return_buffer.pointer; | |
739 | ||
740 | acpi_dm_compare_aml_resources(original_aml->buffer.pointer, | |
741 | (acpi_rsdesc_size) original_aml->buffer. | |
742 | length, new_aml.pointer, | |
743 | (acpi_rsdesc_size) new_aml.length); | |
744 | ||
745 | /* Cleanup and exit */ | |
746 | ||
747 | ACPI_FREE(new_aml.pointer); | |
748 | exit2: | |
749 | ACPI_FREE(resource_buffer.pointer); | |
750 | exit1: | |
751 | ACPI_FREE(return_buffer.pointer); | |
752 | return (status); | |
753 | } | |
754 | ||
755 | /******************************************************************************* | |
756 | * | |
757 | * FUNCTION: acpi_db_resource_callback | |
758 | * | |
759 | * PARAMETERS: acpi_walk_resource_callback | |
760 | * | |
761 | * RETURN: Status | |
762 | * | |
763 | * DESCRIPTION: Simple callback to exercise acpi_walk_resources and | |
764 | * acpi_walk_resource_buffer. | |
765 | * | |
766 | ******************************************************************************/ | |
767 | ||
768 | static acpi_status | |
769 | acpi_db_resource_callback(struct acpi_resource *resource, void *context) | |
770 | { | |
771 | ||
772 | return (AE_OK); | |
773 | } | |
774 | ||
775 | /******************************************************************************* | |
776 | * | |
777 | * FUNCTION: acpi_db_device_resources | |
778 | * | |
779 | * PARAMETERS: acpi_walk_callback | |
780 | * | |
781 | * RETURN: Status | |
782 | * | |
783 | * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object. | |
784 | * | |
785 | ******************************************************************************/ | |
786 | ||
787 | static acpi_status | |
788 | acpi_db_device_resources(acpi_handle obj_handle, | |
789 | u32 nesting_level, void *context, void **return_value) | |
790 | { | |
791 | struct acpi_namespace_node *node; | |
792 | struct acpi_namespace_node *prt_node = NULL; | |
793 | struct acpi_namespace_node *crs_node = NULL; | |
794 | struct acpi_namespace_node *prs_node = NULL; | |
795 | struct acpi_namespace_node *aei_node = NULL; | |
796 | char *parent_path; | |
797 | struct acpi_buffer return_buffer; | |
798 | acpi_status status; | |
799 | ||
800 | node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); | |
0e166e4f | 801 | parent_path = acpi_ns_get_normalized_pathname(node, TRUE); |
99575102 LZ |
802 | if (!parent_path) { |
803 | return (AE_NO_MEMORY); | |
804 | } | |
805 | ||
806 | /* Get handles to the resource methods for this device */ | |
807 | ||
808 | (void)acpi_get_handle(node, METHOD_NAME__PRT, | |
809 | ACPI_CAST_PTR(acpi_handle, &prt_node)); | |
810 | (void)acpi_get_handle(node, METHOD_NAME__CRS, | |
811 | ACPI_CAST_PTR(acpi_handle, &crs_node)); | |
812 | (void)acpi_get_handle(node, METHOD_NAME__PRS, | |
813 | ACPI_CAST_PTR(acpi_handle, &prs_node)); | |
814 | (void)acpi_get_handle(node, METHOD_NAME__AEI, | |
815 | ACPI_CAST_PTR(acpi_handle, &aei_node)); | |
816 | ||
817 | if (!prt_node && !crs_node && !prs_node && !aei_node) { | |
818 | goto cleanup; /* Nothing to do */ | |
819 | } | |
820 | ||
821 | acpi_os_printf("\nDevice: %s\n", parent_path); | |
822 | ||
823 | /* Prepare for a return object of arbitrary size */ | |
824 | ||
825 | return_buffer.pointer = acpi_gbl_db_buffer; | |
826 | return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; | |
827 | ||
828 | /* _PRT */ | |
829 | ||
830 | if (prt_node) { | |
831 | acpi_os_printf("Evaluating _PRT\n"); | |
832 | ||
833 | status = | |
834 | acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer); | |
835 | if (ACPI_FAILURE(status)) { | |
836 | acpi_os_printf("Could not evaluate _PRT: %s\n", | |
837 | acpi_format_exception(status)); | |
838 | goto get_crs; | |
839 | } | |
840 | ||
841 | return_buffer.pointer = acpi_gbl_db_buffer; | |
842 | return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; | |
843 | ||
844 | status = acpi_get_irq_routing_table(node, &return_buffer); | |
845 | if (ACPI_FAILURE(status)) { | |
846 | acpi_os_printf("GetIrqRoutingTable failed: %s\n", | |
847 | acpi_format_exception(status)); | |
848 | goto get_crs; | |
849 | } | |
850 | ||
851 | acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer)); | |
852 | } | |
853 | ||
854 | /* _CRS */ | |
855 | ||
856 | get_crs: | |
857 | if (crs_node) { | |
858 | acpi_os_printf("Evaluating _CRS\n"); | |
859 | ||
860 | return_buffer.pointer = acpi_gbl_db_buffer; | |
861 | return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; | |
862 | ||
863 | status = | |
864 | acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer); | |
865 | if (ACPI_FAILURE(status)) { | |
866 | acpi_os_printf("Could not evaluate _CRS: %s\n", | |
867 | acpi_format_exception(status)); | |
868 | goto get_prs; | |
869 | } | |
870 | ||
871 | /* This code exercises the acpi_walk_resources interface */ | |
872 | ||
873 | status = acpi_walk_resources(node, METHOD_NAME__CRS, | |
874 | acpi_db_resource_callback, NULL); | |
875 | if (ACPI_FAILURE(status)) { | |
876 | acpi_os_printf("AcpiWalkResources failed: %s\n", | |
877 | acpi_format_exception(status)); | |
878 | goto get_prs; | |
879 | } | |
880 | ||
881 | /* Get the _CRS resource list (test ALLOCATE buffer) */ | |
882 | ||
883 | return_buffer.pointer = NULL; | |
884 | return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | |
885 | ||
886 | status = acpi_get_current_resources(node, &return_buffer); | |
887 | if (ACPI_FAILURE(status)) { | |
888 | acpi_os_printf("AcpiGetCurrentResources failed: %s\n", | |
889 | acpi_format_exception(status)); | |
890 | goto get_prs; | |
891 | } | |
892 | ||
893 | /* This code exercises the acpi_walk_resource_buffer interface */ | |
894 | ||
895 | status = acpi_walk_resource_buffer(&return_buffer, | |
896 | acpi_db_resource_callback, | |
897 | NULL); | |
898 | if (ACPI_FAILURE(status)) { | |
899 | acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n", | |
900 | acpi_format_exception(status)); | |
901 | goto end_crs; | |
902 | } | |
903 | ||
904 | /* Dump the _CRS resource list */ | |
905 | ||
906 | acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource, | |
907 | return_buffer. | |
908 | pointer)); | |
909 | ||
910 | /* | |
911 | * Perform comparison of original AML to newly created AML. This | |
912 | * tests both the AML->Resource conversion and the Resource->AML | |
913 | * conversion. | |
914 | */ | |
915 | (void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS); | |
916 | ||
917 | /* Execute _SRS with the resource list */ | |
918 | ||
919 | acpi_os_printf("Evaluating _SRS\n"); | |
920 | ||
921 | status = acpi_set_current_resources(node, &return_buffer); | |
922 | if (ACPI_FAILURE(status)) { | |
923 | acpi_os_printf("AcpiSetCurrentResources failed: %s\n", | |
924 | acpi_format_exception(status)); | |
925 | goto end_crs; | |
926 | } | |
927 | ||
928 | end_crs: | |
929 | ACPI_FREE(return_buffer.pointer); | |
930 | } | |
931 | ||
932 | /* _PRS */ | |
933 | ||
934 | get_prs: | |
935 | if (prs_node) { | |
936 | acpi_os_printf("Evaluating _PRS\n"); | |
937 | ||
938 | return_buffer.pointer = acpi_gbl_db_buffer; | |
939 | return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; | |
940 | ||
941 | status = | |
942 | acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer); | |
943 | if (ACPI_FAILURE(status)) { | |
944 | acpi_os_printf("Could not evaluate _PRS: %s\n", | |
945 | acpi_format_exception(status)); | |
946 | goto get_aei; | |
947 | } | |
948 | ||
949 | return_buffer.pointer = acpi_gbl_db_buffer; | |
950 | return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; | |
951 | ||
952 | status = acpi_get_possible_resources(node, &return_buffer); | |
953 | if (ACPI_FAILURE(status)) { | |
954 | acpi_os_printf("AcpiGetPossibleResources failed: %s\n", | |
955 | acpi_format_exception(status)); | |
956 | goto get_aei; | |
957 | } | |
958 | ||
959 | acpi_rs_dump_resource_list(ACPI_CAST_PTR | |
960 | (struct acpi_resource, | |
961 | acpi_gbl_db_buffer)); | |
962 | } | |
963 | ||
964 | /* _AEI */ | |
965 | ||
966 | get_aei: | |
967 | if (aei_node) { | |
968 | acpi_os_printf("Evaluating _AEI\n"); | |
969 | ||
970 | return_buffer.pointer = acpi_gbl_db_buffer; | |
971 | return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; | |
972 | ||
973 | status = | |
974 | acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer); | |
975 | if (ACPI_FAILURE(status)) { | |
976 | acpi_os_printf("Could not evaluate _AEI: %s\n", | |
977 | acpi_format_exception(status)); | |
978 | goto cleanup; | |
979 | } | |
980 | ||
981 | return_buffer.pointer = acpi_gbl_db_buffer; | |
982 | return_buffer.length = ACPI_DEBUG_BUFFER_SIZE; | |
983 | ||
984 | status = acpi_get_event_resources(node, &return_buffer); | |
985 | if (ACPI_FAILURE(status)) { | |
986 | acpi_os_printf("AcpiGetEventResources failed: %s\n", | |
987 | acpi_format_exception(status)); | |
988 | goto cleanup; | |
989 | } | |
990 | ||
991 | acpi_rs_dump_resource_list(ACPI_CAST_PTR | |
992 | (struct acpi_resource, | |
993 | acpi_gbl_db_buffer)); | |
994 | } | |
995 | ||
996 | cleanup: | |
997 | ACPI_FREE(parent_path); | |
998 | return (AE_OK); | |
999 | } | |
1000 | ||
1001 | /******************************************************************************* | |
1002 | * | |
1003 | * FUNCTION: acpi_db_display_resources | |
1004 | * | |
1005 | * PARAMETERS: object_arg - String object name or object pointer. | |
1006 | * NULL or "*" means "display resources for | |
1007 | * all devices" | |
1008 | * | |
1009 | * RETURN: None | |
1010 | * | |
1011 | * DESCRIPTION: Display the resource objects associated with a device. | |
1012 | * | |
1013 | ******************************************************************************/ | |
1014 | ||
1015 | void acpi_db_display_resources(char *object_arg) | |
1016 | { | |
1017 | struct acpi_namespace_node *node; | |
1018 | ||
1019 | acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); | |
1020 | acpi_dbg_level |= ACPI_LV_RESOURCES; | |
1021 | ||
1022 | /* Asterisk means "display resources for all devices" */ | |
1023 | ||
1024 | if (!object_arg || (!strcmp(object_arg, "*"))) { | |
1025 | (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | |
1026 | ACPI_UINT32_MAX, | |
1027 | acpi_db_device_resources, NULL, NULL, | |
1028 | NULL); | |
1029 | } else { | |
1030 | /* Convert string to object pointer */ | |
1031 | ||
1032 | node = acpi_db_convert_to_node(object_arg); | |
1033 | if (node) { | |
1034 | if (node->type != ACPI_TYPE_DEVICE) { | |
1035 | acpi_os_printf | |
1036 | ("%4.4s: Name is not a device object (%s)\n", | |
1037 | node->name.ascii, | |
1038 | acpi_ut_get_type_name(node->type)); | |
1039 | } else { | |
1040 | (void)acpi_db_device_resources(node, 0, NULL, | |
1041 | NULL); | |
1042 | } | |
1043 | } | |
1044 | } | |
1045 | ||
1046 | acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); | |
1047 | } | |
1048 | ||
1049 | #if (!ACPI_REDUCED_HARDWARE) | |
1050 | /******************************************************************************* | |
1051 | * | |
1052 | * FUNCTION: acpi_db_generate_gpe | |
1053 | * | |
1054 | * PARAMETERS: gpe_arg - Raw GPE number, ascii string | |
1055 | * block_arg - GPE block number, ascii string | |
1056 | * 0 or 1 for FADT GPE blocks | |
1057 | * | |
1058 | * RETURN: None | |
1059 | * | |
1060 | * DESCRIPTION: Simulate firing of a GPE | |
1061 | * | |
1062 | ******************************************************************************/ | |
1063 | ||
1064 | void acpi_db_generate_gpe(char *gpe_arg, char *block_arg) | |
1065 | { | |
1066 | u32 block_number = 0; | |
1067 | u32 gpe_number; | |
1068 | struct acpi_gpe_event_info *gpe_event_info; | |
1069 | ||
1070 | gpe_number = strtoul(gpe_arg, NULL, 0); | |
1071 | ||
1072 | /* | |
1073 | * If no block arg, or block arg == 0 or 1, use the FADT-defined | |
1074 | * GPE blocks. | |
1075 | */ | |
1076 | if (block_arg) { | |
1077 | block_number = strtoul(block_arg, NULL, 0); | |
1078 | if (block_number == 1) { | |
1079 | block_number = 0; | |
1080 | } | |
1081 | } | |
1082 | ||
1083 | gpe_event_info = | |
1084 | acpi_ev_get_gpe_event_info(ACPI_TO_POINTER(block_number), | |
1085 | gpe_number); | |
1086 | if (!gpe_event_info) { | |
1087 | acpi_os_printf("Invalid GPE\n"); | |
1088 | return; | |
1089 | } | |
1090 | ||
1091 | (void)acpi_ev_gpe_dispatch(NULL, gpe_event_info, gpe_number); | |
1092 | } | |
1093 | ||
1094 | /******************************************************************************* | |
1095 | * | |
1096 | * FUNCTION: acpi_db_generate_sci | |
1097 | * | |
1098 | * PARAMETERS: None | |
1099 | * | |
1100 | * RETURN: None | |
1101 | * | |
1102 | * DESCRIPTION: Simulate an SCI -- just call the SCI dispatch. | |
1103 | * | |
1104 | ******************************************************************************/ | |
1105 | ||
1106 | void acpi_db_generate_sci(void) | |
1107 | { | |
1108 | acpi_ev_sci_dispatch(); | |
1109 | } | |
1110 | ||
1111 | #endif /* !ACPI_REDUCED_HARDWARE */ | |
1112 | ||
1113 | /******************************************************************************* | |
1114 | * | |
1115 | * FUNCTION: acpi_db_trace | |
1116 | * | |
1117 | * PARAMETERS: enable_arg - ENABLE/AML to enable tracer | |
1118 | * DISABLE to disable tracer | |
1119 | * method_arg - Method to trace | |
1120 | * once_arg - Whether trace once | |
1121 | * | |
1122 | * RETURN: None | |
1123 | * | |
1124 | * DESCRIPTION: Control method tracing facility | |
1125 | * | |
1126 | ******************************************************************************/ | |
1127 | ||
1128 | void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg) | |
1129 | { | |
1130 | u32 debug_level = 0; | |
1131 | u32 debug_layer = 0; | |
1132 | u32 flags = 0; | |
1133 | ||
4d16ca17 ME |
1134 | acpi_ut_strupr(enable_arg); |
1135 | acpi_ut_strupr(once_arg); | |
99575102 LZ |
1136 | |
1137 | if (method_arg) { | |
1138 | if (acpi_db_trace_method_name) { | |
1139 | ACPI_FREE(acpi_db_trace_method_name); | |
1140 | acpi_db_trace_method_name = NULL; | |
1141 | } | |
1142 | ||
1143 | acpi_db_trace_method_name = | |
1144 | ACPI_ALLOCATE(strlen(method_arg) + 1); | |
1145 | if (!acpi_db_trace_method_name) { | |
1146 | acpi_os_printf("Failed to allocate method name (%s)\n", | |
1147 | method_arg); | |
1148 | return; | |
1149 | } | |
1150 | ||
1151 | strcpy(acpi_db_trace_method_name, method_arg); | |
1152 | } | |
1153 | ||
1154 | if (!strcmp(enable_arg, "ENABLE") || | |
1155 | !strcmp(enable_arg, "METHOD") || !strcmp(enable_arg, "OPCODE")) { | |
1156 | if (!strcmp(enable_arg, "ENABLE")) { | |
1157 | ||
1158 | /* Inherit current console settings */ | |
1159 | ||
1160 | debug_level = acpi_gbl_db_console_debug_level; | |
1161 | debug_layer = acpi_dbg_layer; | |
1162 | } else { | |
1163 | /* Restrict console output to trace points only */ | |
1164 | ||
1165 | debug_level = ACPI_LV_TRACE_POINT; | |
1166 | debug_layer = ACPI_EXECUTER; | |
1167 | } | |
1168 | ||
1169 | flags = ACPI_TRACE_ENABLED; | |
1170 | ||
1171 | if (!strcmp(enable_arg, "OPCODE")) { | |
1172 | flags |= ACPI_TRACE_OPCODE; | |
1173 | } | |
1174 | ||
1175 | if (once_arg && !strcmp(once_arg, "ONCE")) { | |
1176 | flags |= ACPI_TRACE_ONESHOT; | |
1177 | } | |
1178 | } | |
1179 | ||
1180 | (void)acpi_debug_trace(acpi_db_trace_method_name, | |
1181 | debug_level, debug_layer, flags); | |
1182 | } |