]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - drivers/acpi/resources/rsutils.c
[ACPI] ACPICA 20051021
[mirror_ubuntu-zesty-kernel.git] / drivers / acpi / resources / rsutils.c
1 /*******************************************************************************
2 *
3 * Module Name: rsutils - Utilities for the resource manager
4 *
5 ******************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
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 <acpi/acnamesp.h>
46 #include <acpi/acresrc.h>
47
48 #define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME("rsutils")
50
51 /*******************************************************************************
52 *
53 * FUNCTION: acpi_rs_decode_bitmask
54 *
55 * PARAMETERS: Mask - Bitmask to decode
56 * List - Where the converted list is returned
57 *
58 * RETURN: Count of bits set (length of list)
59 *
60 * DESCRIPTION: Convert a bit mask into a list of values
61 *
62 ******************************************************************************/
63 u8 acpi_rs_decode_bitmask(u16 mask, u8 * list)
64 {
65 acpi_native_uint i;
66 u8 bit_count;
67
68 /* Decode the mask bits */
69
70 for (i = 0, bit_count = 0; mask; i++) {
71 if (mask & 0x0001) {
72 list[bit_count] = (u8) i;
73 bit_count++;
74 }
75
76 mask >>= 1;
77 }
78
79 return (bit_count);
80 }
81
82 /*******************************************************************************
83 *
84 * FUNCTION: acpi_rs_encode_bitmask
85 *
86 * PARAMETERS: List - List of values to encode
87 * Count - Length of list
88 *
89 * RETURN: Encoded bitmask
90 *
91 * DESCRIPTION: Convert a list of values to an encoded bitmask
92 *
93 ******************************************************************************/
94
95 u16 acpi_rs_encode_bitmask(u8 * list, u8 count)
96 {
97 acpi_native_uint i;
98 u16 mask;
99
100 /* Encode the list into a single bitmask */
101
102 for (i = 0, mask = 0; i < count; i++) {
103 mask |= (0x0001 << list[i]);
104 }
105
106 return (mask);
107 }
108
109 /*******************************************************************************
110 *
111 * FUNCTION: acpi_rs_move_data
112 *
113 * PARAMETERS: Destination - Pointer to the destination descriptor
114 * Source - Pointer to the source descriptor
115 * item_count - How many items to move
116 * move_type - Byte width
117 *
118 * RETURN: None
119 *
120 * DESCRIPTION: Move multiple data items from one descriptor to another. Handles
121 * alignment issues and endian issues if necessary, as configured
122 * via the ACPI_MOVE_* macros. (This is why a memcpy is not used)
123 *
124 ******************************************************************************/
125
126 void
127 acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
128 {
129 acpi_native_uint i;
130
131 /* One move per item */
132
133 for (i = 0; i < item_count; i++) {
134 switch (move_type) {
135 /*
136 * For the 8-bit case, we can perform the move all at once
137 * since there are no alignment or endian issues
138 */
139 case ACPI_RSC_MOVE8:
140 ACPI_MEMCPY(destination, source, item_count);
141 return;
142
143 /*
144 * 16-, 32-, and 64-bit cases must use the move macros that perform
145 * endian conversion and/or accomodate hardware that cannot perform
146 * misaligned memory transfers
147 */
148 case ACPI_RSC_MOVE16:
149 ACPI_MOVE_16_TO_16(&((u16 *) destination)[i],
150 &((u16 *) source)[i]);
151 break;
152
153 case ACPI_RSC_MOVE32:
154 ACPI_MOVE_32_TO_32(&((u32 *) destination)[i],
155 &((u32 *) source)[i]);
156 break;
157
158 case ACPI_RSC_MOVE64:
159 ACPI_MOVE_64_TO_64(&((u64 *) destination)[i],
160 &((u64 *) source)[i]);
161 break;
162
163 default:
164 return;
165 }
166 }
167 }
168
169 /*******************************************************************************
170 *
171 * FUNCTION: acpi_rs_get_resource_info
172 *
173 * PARAMETERS: resource_type - Byte 0 of a resource descriptor
174 *
175 * RETURN: Pointer to the resource conversion handler
176 *
177 * DESCRIPTION: Extract the Resource Type/Name from the first byte of
178 * a resource descriptor.
179 *
180 ******************************************************************************/
181
182 struct acpi_resource_info *acpi_rs_get_resource_info(u8 resource_type)
183 {
184 struct acpi_resource_info *size_info;
185
186 ACPI_FUNCTION_ENTRY();
187
188 /* Determine if this is a small or large resource */
189
190 if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
191 /* Large Resource Type -- bits 6:0 contain the name */
192
193 if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
194 return (NULL);
195 }
196
197 size_info = &acpi_gbl_lg_resource_info[(resource_type &
198 ACPI_RESOURCE_NAME_LARGE_MASK)];
199 } else {
200 /* Small Resource Type -- bits 6:3 contain the name */
201
202 size_info = &acpi_gbl_sm_resource_info[((resource_type &
203 ACPI_RESOURCE_NAME_SMALL_MASK)
204 >> 3)];
205 }
206
207 /* Zero entry indicates an invalid resource type */
208
209 if (!size_info->minimum_internal_struct_length) {
210 return (NULL);
211 }
212
213 return (size_info);
214 }
215
216 /*******************************************************************************
217 *
218 * FUNCTION: acpi_rs_set_resource_length
219 *
220 * PARAMETERS: total_length - Length of the AML descriptor, including
221 * the header and length fields.
222 * Aml - Pointer to the raw AML descriptor
223 *
224 * RETURN: None
225 *
226 * DESCRIPTION: Set the resource_length field of an AML
227 * resource descriptor, both Large and Small descriptors are
228 * supported automatically. Note: Descriptor Type field must
229 * be valid.
230 *
231 ******************************************************************************/
232
233 void
234 acpi_rs_set_resource_length(acpi_rsdesc_size total_length,
235 union aml_resource *aml)
236 {
237 acpi_rs_length resource_length;
238
239 ACPI_FUNCTION_ENTRY();
240
241 /* Determine if this is a small or large resource */
242
243 if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
244 /* Large Resource type -- bytes 1-2 contain the 16-bit length */
245
246 resource_length = (acpi_rs_length)
247 (total_length - sizeof(struct aml_resource_large_header));
248
249 /* Insert length into the Large descriptor length field */
250
251 ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
252 &resource_length);
253 } else {
254 /* Small Resource type -- bits 2:0 of byte 0 contain the length */
255
256 resource_length = (acpi_rs_length)
257 (total_length - sizeof(struct aml_resource_small_header));
258
259 /* Insert length into the descriptor type byte */
260
261 aml->small_header.descriptor_type = (u8)
262
263 /* Clear any existing length, preserving descriptor type bits */
264 ((aml->small_header.
265 descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
266
267 | resource_length);
268 }
269 }
270
271 /*******************************************************************************
272 *
273 * FUNCTION: acpi_rs_set_resource_header
274 *
275 * PARAMETERS: descriptor_type - Byte to be inserted as the type
276 * total_length - Length of the AML descriptor, including
277 * the header and length fields.
278 * Aml - Pointer to the raw AML descriptor
279 *
280 * RETURN: None
281 *
282 * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML
283 * resource descriptor, both Large and Small descriptors are
284 * supported automatically
285 *
286 ******************************************************************************/
287
288 void
289 acpi_rs_set_resource_header(u8 descriptor_type,
290 acpi_rsdesc_size total_length,
291 union aml_resource *aml)
292 {
293 ACPI_FUNCTION_ENTRY();
294
295 /* Set the Descriptor Type */
296
297 aml->small_header.descriptor_type = descriptor_type;
298
299 /* Set the Resource Length */
300
301 acpi_rs_set_resource_length(total_length, aml);
302 }
303
304 /*******************************************************************************
305 *
306 * FUNCTION: acpi_rs_strcpy
307 *
308 * PARAMETERS: Destination - Pointer to the destination string
309 * Source - Pointer to the source string
310 *
311 * RETURN: String length, including NULL terminator
312 *
313 * DESCRIPTION: Local string copy that returns the string length, saving a
314 * strcpy followed by a strlen.
315 *
316 ******************************************************************************/
317
318 static u16 acpi_rs_strcpy(char *destination, char *source)
319 {
320 u16 i;
321
322 ACPI_FUNCTION_ENTRY();
323
324 for (i = 0; source[i]; i++) {
325 destination[i] = source[i];
326 }
327
328 destination[i] = 0;
329
330 /* Return string length including the NULL terminator */
331
332 return ((u16) (i + 1));
333 }
334
335 /*******************************************************************************
336 *
337 * FUNCTION: acpi_rs_get_resource_source
338 *
339 * PARAMETERS: resource_length - Length field of the descriptor
340 * minimum_length - Minimum length of the descriptor (minus
341 * any optional fields)
342 * resource_source - Where the resource_source is returned
343 * Aml - Pointer to the raw AML descriptor
344 * string_ptr - (optional) where to store the actual
345 * resource_source string
346 *
347 * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit
348 *
349 * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
350 * to an internal resource descriptor
351 *
352 ******************************************************************************/
353
354 acpi_rs_length
355 acpi_rs_get_resource_source(acpi_rs_length resource_length,
356 acpi_rs_length minimum_length,
357 struct acpi_resource_source * resource_source,
358 union aml_resource * aml, char *string_ptr)
359 {
360 acpi_rsdesc_size total_length;
361 u8 *aml_resource_source;
362
363 ACPI_FUNCTION_ENTRY();
364
365 total_length =
366 resource_length + sizeof(struct aml_resource_large_header);
367 aml_resource_source = ((u8 *) aml) + minimum_length;
368
369 /*
370 * resource_source is present if the length of the descriptor is longer than
371 * the minimum length.
372 *
373 * Note: Some resource descriptors will have an additional null, so
374 * we add 1 to the minimum length.
375 */
376 if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) {
377 /* Get the resource_source_index */
378
379 resource_source->index = aml_resource_source[0];
380
381 resource_source->string_ptr = string_ptr;
382 if (!string_ptr) {
383 /*
384 * String destination pointer is not specified; Set the String
385 * pointer to the end of the current resource_source structure.
386 */
387 resource_source->string_ptr = (char *)
388 ((u8 *) resource_source) +
389 sizeof(struct acpi_resource_source);
390 }
391
392 /*
393 * In order for the struct_size to fall on a 32-bit boundary, calculate
394 * the length of the string (+1 for the NULL terminator) and expand the
395 * struct_size to the next 32-bit boundary.
396 *
397 * Zero the entire area of the buffer.
398 */
399 total_length =
400 ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN
401 ((char *)&aml_resource_source[1]) +
402 1);
403 ACPI_MEMSET(resource_source->string_ptr, 0, total_length);
404
405 /* Copy the resource_source string to the destination */
406
407 resource_source->string_length =
408 acpi_rs_strcpy(resource_source->string_ptr,
409 (char *)&aml_resource_source[1]);
410
411 return ((acpi_rs_length) total_length);
412 } else {
413 /* resource_source is not present */
414
415 resource_source->index = 0;
416 resource_source->string_length = 0;
417 resource_source->string_ptr = NULL;
418 return (0);
419 }
420 }
421
422 /*******************************************************************************
423 *
424 * FUNCTION: acpi_rs_set_resource_source
425 *
426 * PARAMETERS: Aml - Pointer to the raw AML descriptor
427 * minimum_length - Minimum length of the descriptor (minus
428 * any optional fields)
429 * resource_source - Internal resource_source
430
431 *
432 * RETURN: Total length of the AML descriptor
433 *
434 * DESCRIPTION: Convert an optional resource_source from internal format to a
435 * raw AML resource descriptor
436 *
437 ******************************************************************************/
438
439 acpi_rsdesc_size
440 acpi_rs_set_resource_source(union aml_resource * aml,
441 acpi_rs_length minimum_length,
442 struct acpi_resource_source * resource_source)
443 {
444 u8 *aml_resource_source;
445 acpi_rsdesc_size descriptor_length;
446
447 ACPI_FUNCTION_ENTRY();
448
449 descriptor_length = minimum_length;
450
451 /* Non-zero string length indicates presence of a resource_source */
452
453 if (resource_source->string_length) {
454 /* Point to the end of the AML descriptor */
455
456 aml_resource_source = ((u8 *) aml) + minimum_length;
457
458 /* Copy the resource_source_index */
459
460 aml_resource_source[0] = (u8) resource_source->index;
461
462 /* Copy the resource_source string */
463
464 ACPI_STRCPY((char *)&aml_resource_source[1],
465 resource_source->string_ptr);
466
467 /*
468 * Add the length of the string (+ 1 for null terminator) to the
469 * final descriptor length
470 */
471 descriptor_length +=
472 ((acpi_rsdesc_size) resource_source->string_length + 1);
473 }
474
475 /* Return the new total length of the AML descriptor */
476
477 return (descriptor_length);
478 }
479
480 /*******************************************************************************
481 *
482 * FUNCTION: acpi_rs_get_prt_method_data
483 *
484 * PARAMETERS: Handle - a handle to the containing object
485 * ret_buffer - a pointer to a buffer structure for the
486 * results
487 *
488 * RETURN: Status
489 *
490 * DESCRIPTION: This function is called to get the _PRT value of an object
491 * contained in an object specified by the handle passed in
492 *
493 * If the function fails an appropriate status will be returned
494 * and the contents of the callers buffer is undefined.
495 *
496 ******************************************************************************/
497
498 acpi_status
499 acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
500 {
501 union acpi_operand_object *obj_desc;
502 acpi_status status;
503
504 ACPI_FUNCTION_TRACE("rs_get_prt_method_data");
505
506 /* Parameters guaranteed valid by caller */
507
508 /* Execute the method, no parameters */
509
510 status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRT,
511 ACPI_BTYPE_PACKAGE, &obj_desc);
512 if (ACPI_FAILURE(status)) {
513 return_ACPI_STATUS(status);
514 }
515
516 /*
517 * Create a resource linked list from the byte stream buffer that comes
518 * back from the _CRS method execution.
519 */
520 status = acpi_rs_create_pci_routing_table(obj_desc, ret_buffer);
521
522 /* On exit, we must delete the object returned by evaluate_object */
523
524 acpi_ut_remove_reference(obj_desc);
525 return_ACPI_STATUS(status);
526 }
527
528 /*******************************************************************************
529 *
530 * FUNCTION: acpi_rs_get_crs_method_data
531 *
532 * PARAMETERS: Handle - a handle to the containing object
533 * ret_buffer - a pointer to a buffer structure for the
534 * results
535 *
536 * RETURN: Status
537 *
538 * DESCRIPTION: This function is called to get the _CRS value of an object
539 * contained in an object specified by the handle passed in
540 *
541 * If the function fails an appropriate status will be returned
542 * and the contents of the callers buffer is undefined.
543 *
544 ******************************************************************************/
545
546 acpi_status
547 acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
548 {
549 union acpi_operand_object *obj_desc;
550 acpi_status status;
551
552 ACPI_FUNCTION_TRACE("rs_get_crs_method_data");
553
554 /* Parameters guaranteed valid by caller */
555
556 /* Execute the method, no parameters */
557
558 status = acpi_ut_evaluate_object(handle, METHOD_NAME__CRS,
559 ACPI_BTYPE_BUFFER, &obj_desc);
560 if (ACPI_FAILURE(status)) {
561 return_ACPI_STATUS(status);
562 }
563
564 /*
565 * Make the call to create a resource linked list from the
566 * byte stream buffer that comes back from the _CRS method
567 * execution.
568 */
569 status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
570
571 /* on exit, we must delete the object returned by evaluate_object */
572
573 acpi_ut_remove_reference(obj_desc);
574 return_ACPI_STATUS(status);
575 }
576
577 /*******************************************************************************
578 *
579 * FUNCTION: acpi_rs_get_prs_method_data
580 *
581 * PARAMETERS: Handle - a handle to the containing object
582 * ret_buffer - a pointer to a buffer structure for the
583 * results
584 *
585 * RETURN: Status
586 *
587 * DESCRIPTION: This function is called to get the _PRS value of an object
588 * contained in an object specified by the handle passed in
589 *
590 * If the function fails an appropriate status will be returned
591 * and the contents of the callers buffer is undefined.
592 *
593 ******************************************************************************/
594
595 #ifdef ACPI_FUTURE_USAGE
596 acpi_status
597 acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
598 {
599 union acpi_operand_object *obj_desc;
600 acpi_status status;
601
602 ACPI_FUNCTION_TRACE("rs_get_prs_method_data");
603
604 /* Parameters guaranteed valid by caller */
605
606 /* Execute the method, no parameters */
607
608 status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRS,
609 ACPI_BTYPE_BUFFER, &obj_desc);
610 if (ACPI_FAILURE(status)) {
611 return_ACPI_STATUS(status);
612 }
613
614 /*
615 * Make the call to create a resource linked list from the
616 * byte stream buffer that comes back from the _CRS method
617 * execution.
618 */
619 status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
620
621 /* on exit, we must delete the object returned by evaluate_object */
622
623 acpi_ut_remove_reference(obj_desc);
624 return_ACPI_STATUS(status);
625 }
626 #endif /* ACPI_FUTURE_USAGE */
627
628 /*******************************************************************************
629 *
630 * FUNCTION: acpi_rs_get_method_data
631 *
632 * PARAMETERS: Handle - a handle to the containing object
633 * Path - Path to method, relative to Handle
634 * ret_buffer - a pointer to a buffer structure for the
635 * results
636 *
637 * RETURN: Status
638 *
639 * DESCRIPTION: This function is called to get the _CRS or _PRS value of an
640 * object contained in an object specified by the handle passed in
641 *
642 * If the function fails an appropriate status will be returned
643 * and the contents of the callers buffer is undefined.
644 *
645 ******************************************************************************/
646
647 acpi_status
648 acpi_rs_get_method_data(acpi_handle handle,
649 char *path, struct acpi_buffer *ret_buffer)
650 {
651 union acpi_operand_object *obj_desc;
652 acpi_status status;
653
654 ACPI_FUNCTION_TRACE("rs_get_method_data");
655
656 /* Parameters guaranteed valid by caller */
657
658 /* Execute the method, no parameters */
659
660 status =
661 acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc);
662 if (ACPI_FAILURE(status)) {
663 return_ACPI_STATUS(status);
664 }
665
666 /*
667 * Make the call to create a resource linked list from the
668 * byte stream buffer that comes back from the method
669 * execution.
670 */
671 status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
672
673 /* On exit, we must delete the object returned by evaluate_object */
674
675 acpi_ut_remove_reference(obj_desc);
676 return_ACPI_STATUS(status);
677 }
678
679 /*******************************************************************************
680 *
681 * FUNCTION: acpi_rs_set_srs_method_data
682 *
683 * PARAMETERS: Handle - a handle to the containing object
684 * in_buffer - a pointer to a buffer structure of the
685 * parameter
686 *
687 * RETURN: Status
688 *
689 * DESCRIPTION: This function is called to set the _SRS of an object contained
690 * in an object specified by the handle passed in
691 *
692 * If the function fails an appropriate status will be returned
693 * and the contents of the callers buffer is undefined.
694 *
695 ******************************************************************************/
696
697 acpi_status
698 acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
699 {
700 struct acpi_parameter_info info;
701 union acpi_operand_object *params[2];
702 acpi_status status;
703 struct acpi_buffer buffer;
704
705 ACPI_FUNCTION_TRACE("rs_set_srs_method_data");
706
707 /* Parameters guaranteed valid by caller */
708
709 /*
710 * The in_buffer parameter will point to a linked list of
711 * resource parameters. It needs to be formatted into a
712 * byte stream to be sent in as an input parameter to _SRS
713 *
714 * Convert the linked list into a byte stream
715 */
716 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
717 status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer);
718 if (ACPI_FAILURE(status)) {
719 return_ACPI_STATUS(status);
720 }
721
722 /* Init the param object */
723
724 params[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
725 if (!params[0]) {
726 acpi_os_free(buffer.pointer);
727 return_ACPI_STATUS(AE_NO_MEMORY);
728 }
729
730 /* Set up the parameter object */
731
732 params[0]->buffer.length = (u32) buffer.length;
733 params[0]->buffer.pointer = buffer.pointer;
734 params[0]->common.flags = AOPOBJ_DATA_VALID;
735 params[1] = NULL;
736
737 info.node = handle;
738 info.parameters = params;
739 info.parameter_type = ACPI_PARAM_ARGS;
740
741 /* Execute the method, no return value */
742
743 status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info);
744 if (ACPI_SUCCESS(status)) {
745 /* Delete any return object (especially if implicit_return is enabled) */
746
747 if (info.return_object) {
748 acpi_ut_remove_reference(info.return_object);
749 }
750 }
751
752 /* Clean up and return the status from acpi_ns_evaluate_relative */
753
754 acpi_ut_remove_reference(params[0]);
755 return_ACPI_STATUS(status);
756 }