ia64/linux-2.6.18-xen.hg

view drivers/acpi/utilities/utcopy.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /******************************************************************************
2 *
3 * Module Name: utcopy - Internal to external object translation utilities
4 *
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2006, 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 */
44 #include <acpi/acpi.h>
45 #include <acpi/amlcode.h>
47 #define _COMPONENT ACPI_UTILITIES
48 ACPI_MODULE_NAME("utcopy")
50 /* Local prototypes */
51 static acpi_status
52 acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
53 union acpi_object *external_object,
54 u8 * data_space, acpi_size * buffer_space_used);
56 static acpi_status
57 acpi_ut_copy_ielement_to_ielement(u8 object_type,
58 union acpi_operand_object *source_object,
59 union acpi_generic_state *state,
60 void *context);
62 static acpi_status
63 acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
64 u8 * buffer, acpi_size * space_used);
66 static acpi_status
67 acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
68 union acpi_operand_object **return_obj);
70 static acpi_status
71 acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
72 union acpi_operand_object *dest_desc);
74 static acpi_status
75 acpi_ut_copy_ielement_to_eelement(u8 object_type,
76 union acpi_operand_object *source_object,
77 union acpi_generic_state *state,
78 void *context);
80 static acpi_status
81 acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
82 union acpi_operand_object *dest_obj,
83 struct acpi_walk_state *walk_state);
85 /*******************************************************************************
86 *
87 * FUNCTION: acpi_ut_copy_isimple_to_esimple
88 *
89 * PARAMETERS: internal_object - Source object to be copied
90 * external_object - Where to return the copied object
91 * data_space - Where object data is returned (such as
92 * buffer and string data)
93 * buffer_space_used - Length of data_space that was used
94 *
95 * RETURN: Status
96 *
97 * DESCRIPTION: This function is called to copy a simple internal object to
98 * an external object.
99 *
100 * The data_space buffer is assumed to have sufficient space for
101 * the object.
102 *
103 ******************************************************************************/
105 static acpi_status
106 acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
107 union acpi_object *external_object,
108 u8 * data_space, acpi_size * buffer_space_used)
109 {
110 acpi_status status = AE_OK;
112 ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple);
114 *buffer_space_used = 0;
116 /*
117 * Check for NULL object case (could be an uninitialized
118 * package element)
119 */
120 if (!internal_object) {
121 return_ACPI_STATUS(AE_OK);
122 }
124 /* Always clear the external object */
126 ACPI_MEMSET(external_object, 0, sizeof(union acpi_object));
128 /*
129 * In general, the external object will be the same type as
130 * the internal object
131 */
132 external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
134 /* However, only a limited number of external types are supported */
136 switch (ACPI_GET_OBJECT_TYPE(internal_object)) {
137 case ACPI_TYPE_STRING:
139 external_object->string.pointer = (char *)data_space;
140 external_object->string.length = internal_object->string.length;
141 *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
142 internal_object->
143 string.
144 length + 1);
146 ACPI_MEMCPY((void *)data_space,
147 (void *)internal_object->string.pointer,
148 (acpi_size) internal_object->string.length + 1);
149 break;
151 case ACPI_TYPE_BUFFER:
153 external_object->buffer.pointer = data_space;
154 external_object->buffer.length = internal_object->buffer.length;
155 *buffer_space_used =
156 ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string.
157 length);
159 ACPI_MEMCPY((void *)data_space,
160 (void *)internal_object->buffer.pointer,
161 internal_object->buffer.length);
162 break;
164 case ACPI_TYPE_INTEGER:
166 external_object->integer.value = internal_object->integer.value;
167 break;
169 case ACPI_TYPE_LOCAL_REFERENCE:
171 /*
172 * This is an object reference. Attempt to dereference it.
173 */
174 switch (internal_object->reference.opcode) {
175 case AML_INT_NAMEPATH_OP:
177 /* For namepath, return the object handle ("reference") */
179 default:
180 /*
181 * Use the object type of "Any" to indicate a reference
182 * to object containing a handle to an ACPI named object.
183 */
184 external_object->type = ACPI_TYPE_ANY;
185 external_object->reference.handle =
186 internal_object->reference.node;
187 break;
188 }
189 break;
191 case ACPI_TYPE_PROCESSOR:
193 external_object->processor.proc_id =
194 internal_object->processor.proc_id;
195 external_object->processor.pblk_address =
196 internal_object->processor.address;
197 external_object->processor.pblk_length =
198 internal_object->processor.length;
199 break;
201 case ACPI_TYPE_POWER:
203 external_object->power_resource.system_level =
204 internal_object->power_resource.system_level;
206 external_object->power_resource.resource_order =
207 internal_object->power_resource.resource_order;
208 break;
210 default:
211 /*
212 * There is no corresponding external object type
213 */
214 return_ACPI_STATUS(AE_SUPPORT);
215 }
217 return_ACPI_STATUS(status);
218 }
220 /*******************************************************************************
221 *
222 * FUNCTION: acpi_ut_copy_ielement_to_eelement
223 *
224 * PARAMETERS: acpi_pkg_callback
225 *
226 * RETURN: Status
227 *
228 * DESCRIPTION: Copy one package element to another package element
229 *
230 ******************************************************************************/
232 static acpi_status
233 acpi_ut_copy_ielement_to_eelement(u8 object_type,
234 union acpi_operand_object *source_object,
235 union acpi_generic_state *state,
236 void *context)
237 {
238 acpi_status status = AE_OK;
239 struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
240 acpi_size object_space;
241 u32 this_index;
242 union acpi_object *target_object;
244 ACPI_FUNCTION_ENTRY();
246 this_index = state->pkg.index;
247 target_object = (union acpi_object *)
248 &((union acpi_object *)(state->pkg.dest_object))->package.
249 elements[this_index];
251 switch (object_type) {
252 case ACPI_COPY_TYPE_SIMPLE:
254 /*
255 * This is a simple or null object
256 */
257 status = acpi_ut_copy_isimple_to_esimple(source_object,
258 target_object,
259 info->free_space,
260 &object_space);
261 if (ACPI_FAILURE(status)) {
262 return (status);
263 }
264 break;
266 case ACPI_COPY_TYPE_PACKAGE:
268 /*
269 * Build the package object
270 */
271 target_object->type = ACPI_TYPE_PACKAGE;
272 target_object->package.count = source_object->package.count;
273 target_object->package.elements =
274 ACPI_CAST_PTR(union acpi_object, info->free_space);
276 /*
277 * Pass the new package object back to the package walk routine
278 */
279 state->pkg.this_target_obj = target_object;
281 /*
282 * Save space for the array of objects (Package elements)
283 * update the buffer length counter
284 */
285 object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
286 target_object->
287 package.count *
288 sizeof(union
289 acpi_object));
290 break;
292 default:
293 return (AE_BAD_PARAMETER);
294 }
296 info->free_space += object_space;
297 info->length += object_space;
298 return (status);
299 }
301 /*******************************************************************************
302 *
303 * FUNCTION: acpi_ut_copy_ipackage_to_epackage
304 *
305 * PARAMETERS: internal_object - Pointer to the object we are returning
306 * Buffer - Where the object is returned
307 * space_used - Where the object length is returned
308 *
309 * RETURN: Status
310 *
311 * DESCRIPTION: This function is called to place a package object in a user
312 * buffer. A package object by definition contains other objects.
313 *
314 * The buffer is assumed to have sufficient space for the object.
315 * The caller must have verified the buffer length needed using the
316 * acpi_ut_get_object_size function before calling this function.
317 *
318 ******************************************************************************/
320 static acpi_status
321 acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
322 u8 * buffer, acpi_size * space_used)
323 {
324 union acpi_object *external_object;
325 acpi_status status;
326 struct acpi_pkg_info info;
328 ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage);
330 /*
331 * First package at head of the buffer
332 */
333 external_object = ACPI_CAST_PTR(union acpi_object, buffer);
335 /*
336 * Free space begins right after the first package
337 */
338 info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
339 info.free_space =
340 buffer + ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
341 info.object_space = 0;
342 info.num_packages = 1;
344 external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
345 external_object->package.count = internal_object->package.count;
346 external_object->package.elements = ACPI_CAST_PTR(union acpi_object,
347 info.free_space);
349 /*
350 * Leave room for an array of ACPI_OBJECTS in the buffer
351 * and move the free space past it
352 */
353 info.length += (acpi_size) external_object->package.count *
354 ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
355 info.free_space += external_object->package.count *
356 ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
358 status = acpi_ut_walk_package_tree(internal_object, external_object,
359 acpi_ut_copy_ielement_to_eelement,
360 &info);
362 *space_used = info.length;
363 return_ACPI_STATUS(status);
364 }
366 /*******************************************************************************
367 *
368 * FUNCTION: acpi_ut_copy_iobject_to_eobject
369 *
370 * PARAMETERS: internal_object - The internal object to be converted
371 * buffer_ptr - Where the object is returned
372 *
373 * RETURN: Status
374 *
375 * DESCRIPTION: This function is called to build an API object to be returned to
376 * the caller.
377 *
378 ******************************************************************************/
380 acpi_status
381 acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object,
382 struct acpi_buffer *ret_buffer)
383 {
384 acpi_status status;
386 ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject);
388 if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) {
389 /*
390 * Package object: Copy all subobjects (including
391 * nested packages)
392 */
393 status = acpi_ut_copy_ipackage_to_epackage(internal_object,
394 ret_buffer->pointer,
395 &ret_buffer->length);
396 } else {
397 /*
398 * Build a simple object (no nested objects)
399 */
400 status = acpi_ut_copy_isimple_to_esimple(internal_object,
401 ACPI_CAST_PTR(union
402 acpi_object,
403 ret_buffer->
404 pointer),
405 ACPI_ADD_PTR(u8,
406 ret_buffer->
407 pointer,
408 ACPI_ROUND_UP_TO_NATIVE_WORD
409 (sizeof
410 (union
411 acpi_object))),
412 &ret_buffer->length);
413 /*
414 * build simple does not include the object size in the length
415 * so we add it in here
416 */
417 ret_buffer->length += sizeof(union acpi_object);
418 }
420 return_ACPI_STATUS(status);
421 }
423 /*******************************************************************************
424 *
425 * FUNCTION: acpi_ut_copy_esimple_to_isimple
426 *
427 * PARAMETERS: external_object - The external object to be converted
428 * ret_internal_object - Where the internal object is returned
429 *
430 * RETURN: Status
431 *
432 * DESCRIPTION: This function copies an external object to an internal one.
433 * NOTE: Pointers can be copied, we don't need to copy data.
434 * (The pointers have to be valid in our address space no matter
435 * what we do with them!)
436 *
437 ******************************************************************************/
439 static acpi_status
440 acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
441 union acpi_operand_object **ret_internal_object)
442 {
443 union acpi_operand_object *internal_object;
445 ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple);
447 /*
448 * Simple types supported are: String, Buffer, Integer
449 */
450 switch (external_object->type) {
451 case ACPI_TYPE_STRING:
452 case ACPI_TYPE_BUFFER:
453 case ACPI_TYPE_INTEGER:
455 internal_object = acpi_ut_create_internal_object((u8)
456 external_object->
457 type);
458 if (!internal_object) {
459 return_ACPI_STATUS(AE_NO_MEMORY);
460 }
461 break;
463 default:
464 /* All other types are not supported */
466 return_ACPI_STATUS(AE_SUPPORT);
467 }
469 /* Must COPY string and buffer contents */
471 switch (external_object->type) {
472 case ACPI_TYPE_STRING:
474 internal_object->string.pointer =
475 ACPI_ALLOCATE_ZEROED((acpi_size) external_object->string.
476 length + 1);
477 if (!internal_object->string.pointer) {
478 goto error_exit;
479 }
481 ACPI_MEMCPY(internal_object->string.pointer,
482 external_object->string.pointer,
483 external_object->string.length);
485 internal_object->string.length = external_object->string.length;
486 break;
488 case ACPI_TYPE_BUFFER:
490 internal_object->buffer.pointer =
491 ACPI_ALLOCATE_ZEROED(external_object->buffer.length);
492 if (!internal_object->buffer.pointer) {
493 goto error_exit;
494 }
496 ACPI_MEMCPY(internal_object->buffer.pointer,
497 external_object->buffer.pointer,
498 external_object->buffer.length);
500 internal_object->buffer.length = external_object->buffer.length;
501 break;
503 case ACPI_TYPE_INTEGER:
505 internal_object->integer.value = external_object->integer.value;
506 break;
508 default:
509 /* Other types can't get here */
510 break;
511 }
513 *ret_internal_object = internal_object;
514 return_ACPI_STATUS(AE_OK);
516 error_exit:
517 acpi_ut_remove_reference(internal_object);
518 return_ACPI_STATUS(AE_NO_MEMORY);
519 }
521 #ifdef ACPI_FUTURE_IMPLEMENTATION
522 /* Code to convert packages that are parameters to control methods */
524 /*******************************************************************************
525 *
526 * FUNCTION: acpi_ut_copy_epackage_to_ipackage
527 *
528 * PARAMETERS: *internal_object - Pointer to the object we are returning
529 * *Buffer - Where the object is returned
530 * *space_used - Where the length of the object is returned
531 *
532 * RETURN: Status
533 *
534 * DESCRIPTION: This function is called to place a package object in a user
535 * buffer. A package object by definition contains other objects.
536 *
537 * The buffer is assumed to have sufficient space for the object.
538 * The caller must have verified the buffer length needed using the
539 * acpi_ut_get_object_size function before calling this function.
540 *
541 ******************************************************************************/
543 static acpi_status
544 acpi_ut_copy_epackage_to_ipackage(union acpi_operand_object *internal_object,
545 u8 * buffer, u32 * space_used)
546 {
547 u8 *free_space;
548 union acpi_object *external_object;
549 u32 length = 0;
550 u32 this_index;
551 u32 object_space = 0;
552 union acpi_operand_object *this_internal_obj;
553 union acpi_object *this_external_obj;
555 ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
557 /*
558 * First package at head of the buffer
559 */
560 external_object = (union acpi_object *)buffer;
562 /*
563 * Free space begins right after the first package
564 */
565 free_space = buffer + sizeof(union acpi_object);
567 external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
568 external_object->package.count = internal_object->package.count;
569 external_object->package.elements = (union acpi_object *)free_space;
571 /*
572 * Build an array of ACPI_OBJECTS in the buffer
573 * and move the free space past it
574 */
575 free_space +=
576 external_object->package.count * sizeof(union acpi_object);
578 /* Call walk_package */
580 }
582 #endif /* Future implementation */
584 /*******************************************************************************
585 *
586 * FUNCTION: acpi_ut_copy_eobject_to_iobject
587 *
588 * PARAMETERS: *internal_object - The external object to be converted
589 * *buffer_ptr - Where the internal object is returned
590 *
591 * RETURN: Status - the status of the call
592 *
593 * DESCRIPTION: Converts an external object to an internal object.
594 *
595 ******************************************************************************/
597 acpi_status
598 acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
599 union acpi_operand_object **internal_object)
600 {
601 acpi_status status;
603 ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
605 if (external_object->type == ACPI_TYPE_PACKAGE) {
606 /*
607 * Packages as external input to control methods are not supported,
608 */
609 ACPI_ERROR((AE_INFO,
610 "Packages as parameters not implemented!"));
612 return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
613 }
615 else {
616 /*
617 * Build a simple object (no nested objects)
618 */
619 status =
620 acpi_ut_copy_esimple_to_isimple(external_object,
621 internal_object);
622 }
624 return_ACPI_STATUS(status);
625 }
627 /*******************************************************************************
628 *
629 * FUNCTION: acpi_ut_copy_simple_object
630 *
631 * PARAMETERS: source_desc - The internal object to be copied
632 * dest_desc - New target object
633 *
634 * RETURN: Status
635 *
636 * DESCRIPTION: Simple copy of one internal object to another. Reference count
637 * of the destination object is preserved.
638 *
639 ******************************************************************************/
641 static acpi_status
642 acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
643 union acpi_operand_object *dest_desc)
644 {
645 u16 reference_count;
646 union acpi_operand_object *next_object;
648 /* Save fields from destination that we don't want to overwrite */
650 reference_count = dest_desc->common.reference_count;
651 next_object = dest_desc->common.next_object;
653 /* Copy the entire source object over the destination object */
655 ACPI_MEMCPY((char *)dest_desc, (char *)source_desc,
656 sizeof(union acpi_operand_object));
658 /* Restore the saved fields */
660 dest_desc->common.reference_count = reference_count;
661 dest_desc->common.next_object = next_object;
663 /* New object is not static, regardless of source */
665 dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
667 /* Handle the objects with extra data */
669 switch (ACPI_GET_OBJECT_TYPE(dest_desc)) {
670 case ACPI_TYPE_BUFFER:
671 /*
672 * Allocate and copy the actual buffer if and only if:
673 * 1) There is a valid buffer pointer
674 * 2) The buffer has a length > 0
675 */
676 if ((source_desc->buffer.pointer) &&
677 (source_desc->buffer.length)) {
678 dest_desc->buffer.pointer =
679 ACPI_ALLOCATE(source_desc->buffer.length);
680 if (!dest_desc->buffer.pointer) {
681 return (AE_NO_MEMORY);
682 }
684 /* Copy the actual buffer data */
686 ACPI_MEMCPY(dest_desc->buffer.pointer,
687 source_desc->buffer.pointer,
688 source_desc->buffer.length);
689 }
690 break;
692 case ACPI_TYPE_STRING:
693 /*
694 * Allocate and copy the actual string if and only if:
695 * 1) There is a valid string pointer
696 * (Pointer to a NULL string is allowed)
697 */
698 if (source_desc->string.pointer) {
699 dest_desc->string.pointer =
700 ACPI_ALLOCATE((acpi_size) source_desc->string.
701 length + 1);
702 if (!dest_desc->string.pointer) {
703 return (AE_NO_MEMORY);
704 }
706 /* Copy the actual string data */
708 ACPI_MEMCPY(dest_desc->string.pointer,
709 source_desc->string.pointer,
710 (acpi_size) source_desc->string.length + 1);
711 }
712 break;
714 case ACPI_TYPE_LOCAL_REFERENCE:
715 /*
716 * We copied the reference object, so we now must add a reference
717 * to the object pointed to by the reference
718 */
719 acpi_ut_add_reference(source_desc->reference.object);
720 break;
722 default:
723 /* Nothing to do for other simple objects */
724 break;
725 }
727 return (AE_OK);
728 }
730 /*******************************************************************************
731 *
732 * FUNCTION: acpi_ut_copy_ielement_to_ielement
733 *
734 * PARAMETERS: acpi_pkg_callback
735 *
736 * RETURN: Status
737 *
738 * DESCRIPTION: Copy one package element to another package element
739 *
740 ******************************************************************************/
742 static acpi_status
743 acpi_ut_copy_ielement_to_ielement(u8 object_type,
744 union acpi_operand_object *source_object,
745 union acpi_generic_state *state,
746 void *context)
747 {
748 acpi_status status = AE_OK;
749 u32 this_index;
750 union acpi_operand_object **this_target_ptr;
751 union acpi_operand_object *target_object;
753 ACPI_FUNCTION_ENTRY();
755 this_index = state->pkg.index;
756 this_target_ptr = (union acpi_operand_object **)
757 &state->pkg.dest_object->package.elements[this_index];
759 switch (object_type) {
760 case ACPI_COPY_TYPE_SIMPLE:
762 /* A null source object indicates a (legal) null package element */
764 if (source_object) {
765 /*
766 * This is a simple object, just copy it
767 */
768 target_object =
769 acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE
770 (source_object));
771 if (!target_object) {
772 return (AE_NO_MEMORY);
773 }
775 status =
776 acpi_ut_copy_simple_object(source_object,
777 target_object);
778 if (ACPI_FAILURE(status)) {
779 goto error_exit;
780 }
782 *this_target_ptr = target_object;
783 } else {
784 /* Pass through a null element */
786 *this_target_ptr = NULL;
787 }
788 break;
790 case ACPI_COPY_TYPE_PACKAGE:
792 /*
793 * This object is a package - go down another nesting level
794 * Create and build the package object
795 */
796 target_object =
797 acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
798 if (!target_object) {
799 return (AE_NO_MEMORY);
800 }
802 target_object->package.count = source_object->package.count;
803 target_object->common.flags = source_object->common.flags;
805 /*
806 * Create the object array
807 */
808 target_object->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.count + 1) * sizeof(void *));
809 if (!target_object->package.elements) {
810 status = AE_NO_MEMORY;
811 goto error_exit;
812 }
814 /*
815 * Pass the new package object back to the package walk routine
816 */
817 state->pkg.this_target_obj = target_object;
819 /*
820 * Store the object pointer in the parent package object
821 */
822 *this_target_ptr = target_object;
823 break;
825 default:
826 return (AE_BAD_PARAMETER);
827 }
829 return (status);
831 error_exit:
832 acpi_ut_remove_reference(target_object);
833 return (status);
834 }
836 /*******************************************************************************
837 *
838 * FUNCTION: acpi_ut_copy_ipackage_to_ipackage
839 *
840 * PARAMETERS: *source_obj - Pointer to the source package object
841 * *dest_obj - Where the internal object is returned
842 *
843 * RETURN: Status - the status of the call
844 *
845 * DESCRIPTION: This function is called to copy an internal package object
846 * into another internal package object.
847 *
848 ******************************************************************************/
850 static acpi_status
851 acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
852 union acpi_operand_object *dest_obj,
853 struct acpi_walk_state *walk_state)
854 {
855 acpi_status status = AE_OK;
857 ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage);
859 dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj);
860 dest_obj->common.flags = source_obj->common.flags;
861 dest_obj->package.count = source_obj->package.count;
863 /*
864 * Create the object array and walk the source package tree
865 */
866 dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
867 source_obj->package.
868 count +
869 1) * sizeof(void *));
870 if (!dest_obj->package.elements) {
871 ACPI_ERROR((AE_INFO, "Package allocation failure"));
872 return_ACPI_STATUS(AE_NO_MEMORY);
873 }
875 /*
876 * Copy the package element-by-element by walking the package "tree".
877 * This handles nested packages of arbitrary depth.
878 */
879 status = acpi_ut_walk_package_tree(source_obj, dest_obj,
880 acpi_ut_copy_ielement_to_ielement,
881 walk_state);
882 if (ACPI_FAILURE(status)) {
884 /* On failure, delete the destination package object */
886 acpi_ut_remove_reference(dest_obj);
887 }
889 return_ACPI_STATUS(status);
890 }
892 /*******************************************************************************
893 *
894 * FUNCTION: acpi_ut_copy_iobject_to_iobject
895 *
896 * PARAMETERS: walk_state - Current walk state
897 * source_desc - The internal object to be copied
898 * dest_desc - Where the copied object is returned
899 *
900 * RETURN: Status
901 *
902 * DESCRIPTION: Copy an internal object to a new internal object
903 *
904 ******************************************************************************/
906 acpi_status
907 acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
908 union acpi_operand_object **dest_desc,
909 struct acpi_walk_state *walk_state)
910 {
911 acpi_status status = AE_OK;
913 ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject);
915 /* Create the top level object */
917 *dest_desc =
918 acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE(source_desc));
919 if (!*dest_desc) {
920 return_ACPI_STATUS(AE_NO_MEMORY);
921 }
923 /* Copy the object and possible subobjects */
925 if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_PACKAGE) {
926 status =
927 acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc,
928 walk_state);
929 } else {
930 status = acpi_ut_copy_simple_object(source_desc, *dest_desc);
931 }
933 return_ACPI_STATUS(status);
934 }