xref: /openbmc/linux/drivers/acpi/acpica/rscalc.c (revision 5bd2315b)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /*******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: rscalc - Calculate stream and list lengths
595b482a8SLen Brown  *
695b482a8SLen Brown  ******************************************************************************/
795b482a8SLen Brown 
895b482a8SLen Brown #include <acpi/acpi.h>
9e2f7a777SLen Brown #include "accommon.h"
10e2f7a777SLen Brown #include "acresrc.h"
11e2f7a777SLen Brown #include "acnamesp.h"
1295b482a8SLen Brown 
1395b482a8SLen Brown #define _COMPONENT          ACPI_RESOURCES
1495b482a8SLen Brown ACPI_MODULE_NAME("rscalc")
1595b482a8SLen Brown 
1695b482a8SLen Brown /* Local prototypes */
1795b482a8SLen Brown static u8 acpi_rs_count_set_bits(u16 bit_field);
1895b482a8SLen Brown 
1995b482a8SLen Brown static acpi_rs_length
2095b482a8SLen Brown acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
2195b482a8SLen Brown 
2295b482a8SLen Brown static u32
2395b482a8SLen Brown acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
2495b482a8SLen Brown 
2595b482a8SLen Brown /*******************************************************************************
2695b482a8SLen Brown  *
2795b482a8SLen Brown  * FUNCTION:    acpi_rs_count_set_bits
2895b482a8SLen Brown  *
2995b482a8SLen Brown  * PARAMETERS:  bit_field       - Field in which to count bits
3095b482a8SLen Brown  *
3195b482a8SLen Brown  * RETURN:      Number of bits set within the field
3295b482a8SLen Brown  *
3395b482a8SLen Brown  * DESCRIPTION: Count the number of bits set in a resource field. Used for
3495b482a8SLen Brown  *              (Short descriptor) interrupt and DMA lists.
3595b482a8SLen Brown  *
3695b482a8SLen Brown  ******************************************************************************/
3795b482a8SLen Brown 
acpi_rs_count_set_bits(u16 bit_field)3895b482a8SLen Brown static u8 acpi_rs_count_set_bits(u16 bit_field)
3995b482a8SLen Brown {
4095b482a8SLen Brown 	u8 bits_set;
4195b482a8SLen Brown 
4295b482a8SLen Brown 	ACPI_FUNCTION_ENTRY();
4395b482a8SLen Brown 
4495b482a8SLen Brown 	for (bits_set = 0; bit_field; bits_set++) {
4595b482a8SLen Brown 
4695b482a8SLen Brown 		/* Zero the least significant bit that is set */
4795b482a8SLen Brown 
4895b482a8SLen Brown 		bit_field &= (u16) (bit_field - 1);
4995b482a8SLen Brown 	}
5095b482a8SLen Brown 
519c0d7939SLv Zheng 	return (bits_set);
5295b482a8SLen Brown }
5395b482a8SLen Brown 
5495b482a8SLen Brown /*******************************************************************************
5595b482a8SLen Brown  *
5695b482a8SLen Brown  * FUNCTION:    acpi_rs_struct_option_length
5795b482a8SLen Brown  *
5895b482a8SLen Brown  * PARAMETERS:  resource_source     - Pointer to optional descriptor field
5995b482a8SLen Brown  *
6095b482a8SLen Brown  * RETURN:      Status
6195b482a8SLen Brown  *
6295b482a8SLen Brown  * DESCRIPTION: Common code to handle optional resource_source_index and
6395b482a8SLen Brown  *              resource_source fields in some Large descriptors. Used during
6495b482a8SLen Brown  *              list-to-stream conversion
6595b482a8SLen Brown  *
6695b482a8SLen Brown  ******************************************************************************/
6795b482a8SLen Brown 
6895b482a8SLen Brown static acpi_rs_length
acpi_rs_struct_option_length(struct acpi_resource_source * resource_source)6995b482a8SLen Brown acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
7095b482a8SLen Brown {
7195b482a8SLen Brown 	ACPI_FUNCTION_ENTRY();
7295b482a8SLen Brown 
7395b482a8SLen Brown 	/*
7495b482a8SLen Brown 	 * If the resource_source string is valid, return the size of the string
7595b482a8SLen Brown 	 * (string_length includes the NULL terminator) plus the size of the
7695b482a8SLen Brown 	 * resource_source_index (1).
7795b482a8SLen Brown 	 */
7895b482a8SLen Brown 	if (resource_source->string_ptr) {
7995b482a8SLen Brown 		return ((acpi_rs_length)(resource_source->string_length + 1));
8095b482a8SLen Brown 	}
8195b482a8SLen Brown 
8295b482a8SLen Brown 	return (0);
8395b482a8SLen Brown }
8495b482a8SLen Brown 
8595b482a8SLen Brown /*******************************************************************************
8695b482a8SLen Brown  *
8795b482a8SLen Brown  * FUNCTION:    acpi_rs_stream_option_length
8895b482a8SLen Brown  *
8995b482a8SLen Brown  * PARAMETERS:  resource_length     - Length from the resource header
9095b482a8SLen Brown  *              minimum_total_length - Minimum length of this resource, before
9195b482a8SLen Brown  *                                    any optional fields. Includes header size
9295b482a8SLen Brown  *
9395b482a8SLen Brown  * RETURN:      Length of optional string (0 if no string present)
9495b482a8SLen Brown  *
9595b482a8SLen Brown  * DESCRIPTION: Common code to handle optional resource_source_index and
9695b482a8SLen Brown  *              resource_source fields in some Large descriptors. Used during
9795b482a8SLen Brown  *              stream-to-list conversion
9895b482a8SLen Brown  *
9995b482a8SLen Brown  ******************************************************************************/
10095b482a8SLen Brown 
10195b482a8SLen Brown static u32
acpi_rs_stream_option_length(u32 resource_length,u32 minimum_aml_resource_length)10295b482a8SLen Brown acpi_rs_stream_option_length(u32 resource_length,
10395b482a8SLen Brown 			     u32 minimum_aml_resource_length)
10495b482a8SLen Brown {
10595b482a8SLen Brown 	u32 string_length = 0;
10695b482a8SLen Brown 
10795b482a8SLen Brown 	ACPI_FUNCTION_ENTRY();
10895b482a8SLen Brown 
10995b482a8SLen Brown 	/*
1101fad8738SBob Moore 	 * The resource_source_index and resource_source are optional elements of
1111fad8738SBob Moore 	 * some Large-type resource descriptors.
11295b482a8SLen Brown 	 */
11395b482a8SLen Brown 
11495b482a8SLen Brown 	/*
1151fad8738SBob Moore 	 * If the length of the actual resource descriptor is greater than the
1161fad8738SBob Moore 	 * ACPI spec-defined minimum length, it means that a resource_source_index
1171fad8738SBob Moore 	 * exists and is followed by a (required) null terminated string. The
1181fad8738SBob Moore 	 * string length (including the null terminator) is the resource length
1191fad8738SBob Moore 	 * minus the minimum length, minus one byte for the resource_source_index
1201fad8738SBob Moore 	 * itself.
12195b482a8SLen Brown 	 */
12295b482a8SLen Brown 	if (resource_length > minimum_aml_resource_length) {
12395b482a8SLen Brown 
12495b482a8SLen Brown 		/* Compute the length of the optional string */
12595b482a8SLen Brown 
12695b482a8SLen Brown 		string_length =
12795b482a8SLen Brown 		    resource_length - minimum_aml_resource_length - 1;
12895b482a8SLen Brown 	}
12995b482a8SLen Brown 
13095b482a8SLen Brown 	/*
13195b482a8SLen Brown 	 * Round the length up to a multiple of the native word in order to
13295b482a8SLen Brown 	 * guarantee that the entire resource descriptor is native word aligned
13395b482a8SLen Brown 	 */
13495b482a8SLen Brown 	return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
13595b482a8SLen Brown }
13695b482a8SLen Brown 
13795b482a8SLen Brown /*******************************************************************************
13895b482a8SLen Brown  *
13995b482a8SLen Brown  * FUNCTION:    acpi_rs_get_aml_length
14095b482a8SLen Brown  *
141ba494beeSBob Moore  * PARAMETERS:  resource            - Pointer to the resource linked list
1429a0a3597SLv Zheng  *              resource_list_size  - Size of the resource linked list
14395b482a8SLen Brown  *              size_needed         - Where the required size is returned
14495b482a8SLen Brown  *
14595b482a8SLen Brown  * RETURN:      Status
14695b482a8SLen Brown  *
14795b482a8SLen Brown  * DESCRIPTION: Takes a linked list of internal resource descriptors and
14895b482a8SLen Brown  *              calculates the size buffer needed to hold the corresponding
14995b482a8SLen Brown  *              external resource byte stream.
15095b482a8SLen Brown  *
15195b482a8SLen Brown  ******************************************************************************/
15295b482a8SLen Brown 
15395b482a8SLen Brown acpi_status
acpi_rs_get_aml_length(struct acpi_resource * resource,acpi_size resource_list_size,acpi_size * size_needed)1549a0a3597SLv Zheng acpi_rs_get_aml_length(struct acpi_resource *resource,
1559a0a3597SLv Zheng 		       acpi_size resource_list_size, acpi_size *size_needed)
15695b482a8SLen Brown {
15795b482a8SLen Brown 	acpi_size aml_size_needed = 0;
1589a0a3597SLv Zheng 	struct acpi_resource *resource_end;
15995b482a8SLen Brown 	acpi_rs_length total_size;
16095b482a8SLen Brown 
16195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(rs_get_aml_length);
16295b482a8SLen Brown 
16395b482a8SLen Brown 	/* Traverse entire list of internal resource descriptors */
16495b482a8SLen Brown 
1659a0a3597SLv Zheng 	resource_end =
1669a0a3597SLv Zheng 	    ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size);
1679a0a3597SLv Zheng 	while (resource < resource_end) {
16895b482a8SLen Brown 
16995b482a8SLen Brown 		/* Validate the descriptor type */
17095b482a8SLen Brown 
17195b482a8SLen Brown 		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
17295b482a8SLen Brown 			return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
17395b482a8SLen Brown 		}
17495b482a8SLen Brown 
175c13085e5SBob Moore 		/* Sanity check the length. It must not be zero, or we loop forever */
176c13085e5SBob Moore 
177c13085e5SBob Moore 		if (!resource->length) {
178c13085e5SBob Moore 			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
179c13085e5SBob Moore 		}
180c13085e5SBob Moore 
18195b482a8SLen Brown 		/* Get the base size of the (external stream) resource descriptor */
18295b482a8SLen Brown 
18395b482a8SLen Brown 		total_size = acpi_gbl_aml_resource_sizes[resource->type];
18495b482a8SLen Brown 
18595b482a8SLen Brown 		/*
18695b482a8SLen Brown 		 * Augment the base size for descriptors with optional and/or
18795b482a8SLen Brown 		 * variable-length fields
18895b482a8SLen Brown 		 */
18995b482a8SLen Brown 		switch (resource->type) {
19095b482a8SLen Brown 		case ACPI_RESOURCE_TYPE_IRQ:
19195b482a8SLen Brown 
19295b482a8SLen Brown 			/* Length can be 3 or 2 */
19395b482a8SLen Brown 
19495b482a8SLen Brown 			if (resource->data.irq.descriptor_length == 2) {
19595b482a8SLen Brown 				total_size--;
19695b482a8SLen Brown 			}
19795b482a8SLen Brown 			break;
19895b482a8SLen Brown 
19995b482a8SLen Brown 		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
20095b482a8SLen Brown 
20195b482a8SLen Brown 			/* Length can be 1 or 0 */
20295b482a8SLen Brown 
20395b482a8SLen Brown 			if (resource->data.irq.descriptor_length == 0) {
20495b482a8SLen Brown 				total_size--;
20595b482a8SLen Brown 			}
20695b482a8SLen Brown 			break;
20795b482a8SLen Brown 
20895b482a8SLen Brown 		case ACPI_RESOURCE_TYPE_VENDOR:
20995b482a8SLen Brown 			/*
21095b482a8SLen Brown 			 * Vendor Defined Resource:
21195b482a8SLen Brown 			 * For a Vendor Specific resource, if the Length is between 1 and 7
21295b482a8SLen Brown 			 * it will be created as a Small Resource data type, otherwise it
21395b482a8SLen Brown 			 * is a Large Resource data type.
21495b482a8SLen Brown 			 */
21595b482a8SLen Brown 			if (resource->data.vendor.byte_length > 7) {
21695b482a8SLen Brown 
21795b482a8SLen Brown 				/* Base size of a Large resource descriptor */
21895b482a8SLen Brown 
21995b482a8SLen Brown 				total_size =
22095b482a8SLen Brown 				    sizeof(struct aml_resource_large_header);
22195b482a8SLen Brown 			}
22295b482a8SLen Brown 
22395b482a8SLen Brown 			/* Add the size of the vendor-specific data */
22495b482a8SLen Brown 
22595b482a8SLen Brown 			total_size = (acpi_rs_length)
22695b482a8SLen Brown 			    (total_size + resource->data.vendor.byte_length);
22795b482a8SLen Brown 			break;
22895b482a8SLen Brown 
22995b482a8SLen Brown 		case ACPI_RESOURCE_TYPE_END_TAG:
23095b482a8SLen Brown 			/*
23195b482a8SLen Brown 			 * End Tag:
23295b482a8SLen Brown 			 * We are done -- return the accumulated total size.
23395b482a8SLen Brown 			 */
23495b482a8SLen Brown 			*size_needed = aml_size_needed + total_size;
23595b482a8SLen Brown 
23695b482a8SLen Brown 			/* Normal exit */
23795b482a8SLen Brown 
23895b482a8SLen Brown 			return_ACPI_STATUS(AE_OK);
23995b482a8SLen Brown 
24095b482a8SLen Brown 		case ACPI_RESOURCE_TYPE_ADDRESS16:
24195b482a8SLen Brown 			/*
24295b482a8SLen Brown 			 * 16-Bit Address Resource:
24395b482a8SLen Brown 			 * Add the size of the optional resource_source info
24495b482a8SLen Brown 			 */
2451fad8738SBob Moore 			total_size = (acpi_rs_length)(total_size +
2461fad8738SBob Moore 						      acpi_rs_struct_option_length
2471fad8738SBob Moore 						      (&resource->data.
24895b482a8SLen Brown 						       address16.
24995b482a8SLen Brown 						       resource_source));
25095b482a8SLen Brown 			break;
25195b482a8SLen Brown 
25295b482a8SLen Brown 		case ACPI_RESOURCE_TYPE_ADDRESS32:
25395b482a8SLen Brown 			/*
25495b482a8SLen Brown 			 * 32-Bit Address Resource:
25595b482a8SLen Brown 			 * Add the size of the optional resource_source info
25695b482a8SLen Brown 			 */
2571fad8738SBob Moore 			total_size = (acpi_rs_length)(total_size +
2581fad8738SBob Moore 						      acpi_rs_struct_option_length
2591fad8738SBob Moore 						      (&resource->data.
26095b482a8SLen Brown 						       address32.
26195b482a8SLen Brown 						       resource_source));
26295b482a8SLen Brown 			break;
26395b482a8SLen Brown 
26495b482a8SLen Brown 		case ACPI_RESOURCE_TYPE_ADDRESS64:
26595b482a8SLen Brown 			/*
26695b482a8SLen Brown 			 * 64-Bit Address Resource:
26795b482a8SLen Brown 			 * Add the size of the optional resource_source info
26895b482a8SLen Brown 			 */
2691fad8738SBob Moore 			total_size = (acpi_rs_length)(total_size +
2701fad8738SBob Moore 						      acpi_rs_struct_option_length
2711fad8738SBob Moore 						      (&resource->data.
27295b482a8SLen Brown 						       address64.
27395b482a8SLen Brown 						       resource_source));
27495b482a8SLen Brown 			break;
27595b482a8SLen Brown 
27695b482a8SLen Brown 		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
27795b482a8SLen Brown 			/*
27895b482a8SLen Brown 			 * Extended IRQ Resource:
27995b482a8SLen Brown 			 * Add the size of each additional optional interrupt beyond the
28095b482a8SLen Brown 			 * required 1 (4 bytes for each u32 interrupt number)
28195b482a8SLen Brown 			 */
2821fad8738SBob Moore 			total_size = (acpi_rs_length)(total_size +
2831fad8738SBob Moore 						      ((resource->data.
2841fad8738SBob Moore 							extended_irq.
2851fad8738SBob Moore 							interrupt_count -
28695b482a8SLen Brown 							1) * 4) +
28795b482a8SLen Brown 						      /* Add the size of the optional resource_source info */
2881fad8738SBob Moore 						      acpi_rs_struct_option_length
2891fad8738SBob Moore 						      (&resource->data.
29095b482a8SLen Brown 						       extended_irq.
29195b482a8SLen Brown 						       resource_source));
29295b482a8SLen Brown 			break;
29395b482a8SLen Brown 
294e0fe0a8dSLin Ming 		case ACPI_RESOURCE_TYPE_GPIO:
295e0fe0a8dSLin Ming 
2961fad8738SBob Moore 			total_size = (acpi_rs_length)(total_size +
297e0fe0a8dSLin Ming 						      (resource->data.gpio.
298e0fe0a8dSLin Ming 						       pin_table_length * 2) +
299e0fe0a8dSLin Ming 						      resource->data.gpio.
3001fad8738SBob Moore 						      resource_source.
3011fad8738SBob Moore 						      string_length +
302e0fe0a8dSLin Ming 						      resource->data.gpio.
303e0fe0a8dSLin Ming 						      vendor_length);
304e0fe0a8dSLin Ming 
305e0fe0a8dSLin Ming 			break;
306e0fe0a8dSLin Ming 
3072b726930SMika Westerberg 		case ACPI_RESOURCE_TYPE_PIN_FUNCTION:
3082b726930SMika Westerberg 
3092b726930SMika Westerberg 			total_size = (acpi_rs_length)(total_size +
3102b726930SMika Westerberg 						      (resource->data.
3112b726930SMika Westerberg 						       pin_function.
3122b726930SMika Westerberg 						       pin_table_length * 2) +
3132b726930SMika Westerberg 						      resource->data.
3142b726930SMika Westerberg 						      pin_function.
3152b726930SMika Westerberg 						      resource_source.
3162b726930SMika Westerberg 						      string_length +
3172b726930SMika Westerberg 						      resource->data.
3182b726930SMika Westerberg 						      pin_function.
3192b726930SMika Westerberg 						      vendor_length);
3202b726930SMika Westerberg 
3212b726930SMika Westerberg 			break;
3222b726930SMika Westerberg 
323520d4a0eSNiyas Sait 		case ACPI_RESOURCE_TYPE_CLOCK_INPUT:
324520d4a0eSNiyas Sait 
325520d4a0eSNiyas Sait 			total_size = (acpi_rs_length)(total_size +
326520d4a0eSNiyas Sait 						      resource->data.
327520d4a0eSNiyas Sait 						      clock_input.
328520d4a0eSNiyas Sait 						      resource_source.
329520d4a0eSNiyas Sait 						      string_length);
330520d4a0eSNiyas Sait 
331520d4a0eSNiyas Sait 			break;
332520d4a0eSNiyas Sait 
333e0fe0a8dSLin Ming 		case ACPI_RESOURCE_TYPE_SERIAL_BUS:
334e0fe0a8dSLin Ming 
335e0fe0a8dSLin Ming 			total_size =
336e0fe0a8dSLin Ming 			    acpi_gbl_aml_resource_serial_bus_sizes[resource->
337e0fe0a8dSLin Ming 								   data.
338e0fe0a8dSLin Ming 								   common_serial_bus.
339e0fe0a8dSLin Ming 								   type];
340e0fe0a8dSLin Ming 
341e0fe0a8dSLin Ming 			total_size = (acpi_rs_length)(total_size +
342e0fe0a8dSLin Ming 						      resource->data.
343e0fe0a8dSLin Ming 						      i2c_serial_bus.
344e0fe0a8dSLin Ming 						      resource_source.
345e0fe0a8dSLin Ming 						      string_length +
346e0fe0a8dSLin Ming 						      resource->data.
347e0fe0a8dSLin Ming 						      i2c_serial_bus.
348e0fe0a8dSLin Ming 						      vendor_length);
349e0fe0a8dSLin Ming 
350e0fe0a8dSLin Ming 			break;
351e0fe0a8dSLin Ming 
35297028ce6SMika Westerberg 		case ACPI_RESOURCE_TYPE_PIN_CONFIG:
35397028ce6SMika Westerberg 
35497028ce6SMika Westerberg 			total_size = (acpi_rs_length)(total_size +
35597028ce6SMika Westerberg 						      (resource->data.
35697028ce6SMika Westerberg 						       pin_config.
35797028ce6SMika Westerberg 						       pin_table_length * 2) +
35897028ce6SMika Westerberg 						      resource->data.pin_config.
35997028ce6SMika Westerberg 						      resource_source.
36097028ce6SMika Westerberg 						      string_length +
36197028ce6SMika Westerberg 						      resource->data.pin_config.
36297028ce6SMika Westerberg 						      vendor_length);
36397028ce6SMika Westerberg 
36497028ce6SMika Westerberg 			break;
36597028ce6SMika Westerberg 
366fdaa0980SMika Westerberg 		case ACPI_RESOURCE_TYPE_PIN_GROUP:
367fdaa0980SMika Westerberg 
368fdaa0980SMika Westerberg 			total_size = (acpi_rs_length)(total_size +
369fdaa0980SMika Westerberg 						      (resource->data.pin_group.
370fdaa0980SMika Westerberg 						       pin_table_length * 2) +
371fdaa0980SMika Westerberg 						      resource->data.pin_group.
372fdaa0980SMika Westerberg 						      resource_label.
373fdaa0980SMika Westerberg 						      string_length +
374fdaa0980SMika Westerberg 						      resource->data.pin_group.
375fdaa0980SMika Westerberg 						      vendor_length);
376fdaa0980SMika Westerberg 
377fdaa0980SMika Westerberg 			break;
378fdaa0980SMika Westerberg 
379f8a6c866SMika Westerberg 		case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION:
380f8a6c866SMika Westerberg 
381f8a6c866SMika Westerberg 			total_size = (acpi_rs_length)(total_size +
382f8a6c866SMika Westerberg 						      resource->data.
383f8a6c866SMika Westerberg 						      pin_group_function.
384f8a6c866SMika Westerberg 						      resource_source.
385f8a6c866SMika Westerberg 						      string_length +
386f8a6c866SMika Westerberg 						      resource->data.
387f8a6c866SMika Westerberg 						      pin_group_function.
388f8a6c866SMika Westerberg 						      resource_source_label.
389f8a6c866SMika Westerberg 						      string_length +
390f8a6c866SMika Westerberg 						      resource->data.
391f8a6c866SMika Westerberg 						      pin_group_function.
392f8a6c866SMika Westerberg 						      vendor_length);
393f8a6c866SMika Westerberg 
394f8a6c866SMika Westerberg 			break;
395f8a6c866SMika Westerberg 
396044b7239SMika Westerberg 		case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG:
397044b7239SMika Westerberg 
398044b7239SMika Westerberg 			total_size = (acpi_rs_length)(total_size +
399044b7239SMika Westerberg 						      resource->data.
400044b7239SMika Westerberg 						      pin_group_config.
401044b7239SMika Westerberg 						      resource_source.
402044b7239SMika Westerberg 						      string_length +
403044b7239SMika Westerberg 						      resource->data.
404044b7239SMika Westerberg 						      pin_group_config.
405044b7239SMika Westerberg 						      resource_source_label.
406044b7239SMika Westerberg 						      string_length +
407044b7239SMika Westerberg 						      resource->data.
408044b7239SMika Westerberg 						      pin_group_config.
409044b7239SMika Westerberg 						      vendor_length);
410044b7239SMika Westerberg 
411044b7239SMika Westerberg 			break;
412044b7239SMika Westerberg 
41395b482a8SLen Brown 		default:
4141d1ea1b7SChao Guan 
41595b482a8SLen Brown 			break;
41695b482a8SLen Brown 		}
41795b482a8SLen Brown 
41895b482a8SLen Brown 		/* Update the total */
41995b482a8SLen Brown 
42095b482a8SLen Brown 		aml_size_needed += total_size;
42195b482a8SLen Brown 
42295b482a8SLen Brown 		/* Point to the next object */
42395b482a8SLen Brown 
42495b482a8SLen Brown 		resource =
42595b482a8SLen Brown 		    ACPI_ADD_PTR(struct acpi_resource, resource,
42695b482a8SLen Brown 				 resource->length);
42795b482a8SLen Brown 	}
42895b482a8SLen Brown 
42995b482a8SLen Brown 	/* Did not find an end_tag resource descriptor */
43095b482a8SLen Brown 
43195b482a8SLen Brown 	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
43295b482a8SLen Brown }
43395b482a8SLen Brown 
43495b482a8SLen Brown /*******************************************************************************
43595b482a8SLen Brown  *
43695b482a8SLen Brown  * FUNCTION:    acpi_rs_get_list_length
43795b482a8SLen Brown  *
43895b482a8SLen Brown  * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
43995b482a8SLen Brown  *              aml_buffer_length   - Size of aml_buffer
44095b482a8SLen Brown  *              size_needed         - Where the size needed is returned
44195b482a8SLen Brown  *
44295b482a8SLen Brown  * RETURN:      Status
44395b482a8SLen Brown  *
44495b482a8SLen Brown  * DESCRIPTION: Takes an external resource byte stream and calculates the size
44595b482a8SLen Brown  *              buffer needed to hold the corresponding internal resource
44695b482a8SLen Brown  *              descriptor linked list.
44795b482a8SLen Brown  *
44895b482a8SLen Brown  ******************************************************************************/
44995b482a8SLen Brown 
45095b482a8SLen Brown acpi_status
acpi_rs_get_list_length(u8 * aml_buffer,u32 aml_buffer_length,acpi_size * size_needed)45195b482a8SLen Brown acpi_rs_get_list_length(u8 *aml_buffer,
45295b482a8SLen Brown 			u32 aml_buffer_length, acpi_size *size_needed)
45395b482a8SLen Brown {
45495b482a8SLen Brown 	acpi_status status;
45595b482a8SLen Brown 	u8 *end_aml;
45695b482a8SLen Brown 	u8 *buffer;
45795b482a8SLen Brown 	u32 buffer_size;
45895b482a8SLen Brown 	u16 temp16;
45995b482a8SLen Brown 	u16 resource_length;
46095b482a8SLen Brown 	u32 extra_struct_bytes;
46195b482a8SLen Brown 	u8 resource_index;
46295b482a8SLen Brown 	u8 minimum_aml_resource_length;
463e0fe0a8dSLin Ming 	union aml_resource *aml_resource;
46495b482a8SLen Brown 
46595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(rs_get_list_length);
46695b482a8SLen Brown 
467e0fe0a8dSLin Ming 	*size_needed = ACPI_RS_SIZE_MIN;	/* Minimum size is one end_tag */
46895b482a8SLen Brown 	end_aml = aml_buffer + aml_buffer_length;
46995b482a8SLen Brown 
47095b482a8SLen Brown 	/* Walk the list of AML resource descriptors */
47195b482a8SLen Brown 
47295b482a8SLen Brown 	while (aml_buffer < end_aml) {
47395b482a8SLen Brown 
47495b482a8SLen Brown 		/* Validate the Resource Type and Resource Length */
47595b482a8SLen Brown 
476886308ecSBob Moore 		status =
477886308ecSBob Moore 		    acpi_ut_validate_resource(NULL, aml_buffer,
478886308ecSBob Moore 					      &resource_index);
47995b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
480e0fe0a8dSLin Ming 			/*
481e0fe0a8dSLin Ming 			 * Exit on failure. Cannot continue because the descriptor length
482e0fe0a8dSLin Ming 			 * may be bogus also.
483e0fe0a8dSLin Ming 			 */
48495b482a8SLen Brown 			return_ACPI_STATUS(status);
48595b482a8SLen Brown 		}
48695b482a8SLen Brown 
487e0fe0a8dSLin Ming 		aml_resource = (void *)aml_buffer;
488e0fe0a8dSLin Ming 
48995b482a8SLen Brown 		/* Get the resource length and base (minimum) AML size */
49095b482a8SLen Brown 
49195b482a8SLen Brown 		resource_length = acpi_ut_get_resource_length(aml_buffer);
49295b482a8SLen Brown 		minimum_aml_resource_length =
49395b482a8SLen Brown 		    acpi_gbl_resource_aml_sizes[resource_index];
49495b482a8SLen Brown 
49595b482a8SLen Brown 		/*
49695b482a8SLen Brown 		 * Augment the size for descriptors with optional
49795b482a8SLen Brown 		 * and/or variable length fields
49895b482a8SLen Brown 		 */
49995b482a8SLen Brown 		extra_struct_bytes = 0;
50095b482a8SLen Brown 		buffer =
50195b482a8SLen Brown 		    aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
50295b482a8SLen Brown 
50395b482a8SLen Brown 		switch (acpi_ut_get_resource_type(aml_buffer)) {
50495b482a8SLen Brown 		case ACPI_RESOURCE_NAME_IRQ:
50595b482a8SLen Brown 			/*
50695b482a8SLen Brown 			 * IRQ Resource:
50795b482a8SLen Brown 			 * Get the number of bits set in the 16-bit IRQ mask
50895b482a8SLen Brown 			 */
50995b482a8SLen Brown 			ACPI_MOVE_16_TO_16(&temp16, buffer);
51095b482a8SLen Brown 			extra_struct_bytes = acpi_rs_count_set_bits(temp16);
51195b482a8SLen Brown 			break;
51295b482a8SLen Brown 
51395b482a8SLen Brown 		case ACPI_RESOURCE_NAME_DMA:
51495b482a8SLen Brown 			/*
51595b482a8SLen Brown 			 * DMA Resource:
51695b482a8SLen Brown 			 * Get the number of bits set in the 8-bit DMA mask
51795b482a8SLen Brown 			 */
51895b482a8SLen Brown 			extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
51995b482a8SLen Brown 			break;
52095b482a8SLen Brown 
52195b482a8SLen Brown 		case ACPI_RESOURCE_NAME_VENDOR_SMALL:
52295b482a8SLen Brown 		case ACPI_RESOURCE_NAME_VENDOR_LARGE:
52395b482a8SLen Brown 			/*
52495b482a8SLen Brown 			 * Vendor Resource:
52595b482a8SLen Brown 			 * Get the number of vendor data bytes
52695b482a8SLen Brown 			 */
52795b482a8SLen Brown 			extra_struct_bytes = resource_length;
528bee6dc39SFeng Tang 
529bee6dc39SFeng Tang 			/*
530bee6dc39SFeng Tang 			 * There is already one byte included in the minimum
531bee6dc39SFeng Tang 			 * descriptor size. If there are extra struct bytes,
532bee6dc39SFeng Tang 			 * subtract one from the count.
533bee6dc39SFeng Tang 			 */
534bee6dc39SFeng Tang 			if (extra_struct_bytes) {
535bee6dc39SFeng Tang 				extra_struct_bytes--;
536bee6dc39SFeng Tang 			}
53795b482a8SLen Brown 			break;
53895b482a8SLen Brown 
53995b482a8SLen Brown 		case ACPI_RESOURCE_NAME_END_TAG:
54095b482a8SLen Brown 			/*
541e0fe0a8dSLin Ming 			 * End Tag: This is the normal exit
54295b482a8SLen Brown 			 */
54395b482a8SLen Brown 			return_ACPI_STATUS(AE_OK);
54495b482a8SLen Brown 
54595b482a8SLen Brown 		case ACPI_RESOURCE_NAME_ADDRESS32:
54695b482a8SLen Brown 		case ACPI_RESOURCE_NAME_ADDRESS16:
54795b482a8SLen Brown 		case ACPI_RESOURCE_NAME_ADDRESS64:
54895b482a8SLen Brown 			/*
54995b482a8SLen Brown 			 * Address Resource:
55095b482a8SLen Brown 			 * Add the size of the optional resource_source
55195b482a8SLen Brown 			 */
55295b482a8SLen Brown 			extra_struct_bytes =
55395b482a8SLen Brown 			    acpi_rs_stream_option_length(resource_length,
55495b482a8SLen Brown 							 minimum_aml_resource_length);
55595b482a8SLen Brown 			break;
55695b482a8SLen Brown 
55795b482a8SLen Brown 		case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
55895b482a8SLen Brown 			/*
55995b482a8SLen Brown 			 * Extended IRQ Resource:
56095b482a8SLen Brown 			 * Using the interrupt_table_length, add 4 bytes for each additional
56195b482a8SLen Brown 			 * interrupt. Note: at least one interrupt is required and is
56295b482a8SLen Brown 			 * included in the minimum descriptor size (reason for the -1)
56395b482a8SLen Brown 			 */
56495b482a8SLen Brown 			extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
56595b482a8SLen Brown 
56695b482a8SLen Brown 			/* Add the size of the optional resource_source */
56795b482a8SLen Brown 
56895b482a8SLen Brown 			extra_struct_bytes +=
56995b482a8SLen Brown 			    acpi_rs_stream_option_length(resource_length -
57095b482a8SLen Brown 							 extra_struct_bytes,
57195b482a8SLen Brown 							 minimum_aml_resource_length);
57295b482a8SLen Brown 			break;
57395b482a8SLen Brown 
574e0fe0a8dSLin Ming 		case ACPI_RESOURCE_NAME_GPIO:
575e0fe0a8dSLin Ming 
576e0fe0a8dSLin Ming 			/* Vendor data is optional */
577e0fe0a8dSLin Ming 
578e0fe0a8dSLin Ming 			if (aml_resource->gpio.vendor_length) {
579e0fe0a8dSLin Ming 				extra_struct_bytes +=
580e0fe0a8dSLin Ming 				    aml_resource->gpio.vendor_offset -
581e0fe0a8dSLin Ming 				    aml_resource->gpio.pin_table_offset +
582e0fe0a8dSLin Ming 				    aml_resource->gpio.vendor_length;
583e0fe0a8dSLin Ming 			} else {
584e0fe0a8dSLin Ming 				extra_struct_bytes +=
585e0fe0a8dSLin Ming 				    aml_resource->large_header.resource_length +
586e0fe0a8dSLin Ming 				    sizeof(struct aml_resource_large_header) -
587e0fe0a8dSLin Ming 				    aml_resource->gpio.pin_table_offset;
588e0fe0a8dSLin Ming 			}
589e0fe0a8dSLin Ming 			break;
590e0fe0a8dSLin Ming 
5912b726930SMika Westerberg 		case ACPI_RESOURCE_NAME_PIN_FUNCTION:
5922b726930SMika Westerberg 
5932b726930SMika Westerberg 			/* Vendor data is optional */
5942b726930SMika Westerberg 
5952b726930SMika Westerberg 			if (aml_resource->pin_function.vendor_length) {
5962b726930SMika Westerberg 				extra_struct_bytes +=
5972b726930SMika Westerberg 				    aml_resource->pin_function.vendor_offset -
5982b726930SMika Westerberg 				    aml_resource->pin_function.
5992b726930SMika Westerberg 				    pin_table_offset +
6002b726930SMika Westerberg 				    aml_resource->pin_function.vendor_length;
6012b726930SMika Westerberg 			} else {
6022b726930SMika Westerberg 				extra_struct_bytes +=
6032b726930SMika Westerberg 				    aml_resource->large_header.resource_length +
6042b726930SMika Westerberg 				    sizeof(struct aml_resource_large_header) -
6052b726930SMika Westerberg 				    aml_resource->pin_function.pin_table_offset;
6062b726930SMika Westerberg 			}
6072b726930SMika Westerberg 			break;
6082b726930SMika Westerberg 
609*5bd2315bSTamir Duberstein 		case ACPI_RESOURCE_NAME_SERIAL_BUS:{
610*5bd2315bSTamir Duberstein 
611*5bd2315bSTamir Duberstein 				/* Avoid undefined behavior: member access within misaligned address */
612*5bd2315bSTamir Duberstein 
613*5bd2315bSTamir Duberstein 				struct aml_resource_common_serialbus
614*5bd2315bSTamir Duberstein 				    common_serial_bus;
615*5bd2315bSTamir Duberstein 				memcpy(&common_serial_bus, aml_resource,
616*5bd2315bSTamir Duberstein 				       sizeof(common_serial_bus));
617e0fe0a8dSLin Ming 
618e0fe0a8dSLin Ming 				minimum_aml_resource_length =
619e0fe0a8dSLin Ming 				    acpi_gbl_resource_aml_serial_bus_sizes
620*5bd2315bSTamir Duberstein 				    [common_serial_bus.type];
621e0fe0a8dSLin Ming 				extra_struct_bytes +=
622*5bd2315bSTamir Duberstein 				    common_serial_bus.resource_length -
623e0fe0a8dSLin Ming 				    minimum_aml_resource_length;
624e0fe0a8dSLin Ming 				break;
625*5bd2315bSTamir Duberstein 			}
626e0fe0a8dSLin Ming 
62797028ce6SMika Westerberg 		case ACPI_RESOURCE_NAME_PIN_CONFIG:
62897028ce6SMika Westerberg 
62997028ce6SMika Westerberg 			/* Vendor data is optional */
63097028ce6SMika Westerberg 
63197028ce6SMika Westerberg 			if (aml_resource->pin_config.vendor_length) {
63297028ce6SMika Westerberg 				extra_struct_bytes +=
63397028ce6SMika Westerberg 				    aml_resource->pin_config.vendor_offset -
63497028ce6SMika Westerberg 				    aml_resource->pin_config.pin_table_offset +
63597028ce6SMika Westerberg 				    aml_resource->pin_config.vendor_length;
63697028ce6SMika Westerberg 			} else {
63797028ce6SMika Westerberg 				extra_struct_bytes +=
63897028ce6SMika Westerberg 				    aml_resource->large_header.resource_length +
63997028ce6SMika Westerberg 				    sizeof(struct aml_resource_large_header) -
64097028ce6SMika Westerberg 				    aml_resource->pin_config.pin_table_offset;
64197028ce6SMika Westerberg 			}
64297028ce6SMika Westerberg 			break;
64397028ce6SMika Westerberg 
644fdaa0980SMika Westerberg 		case ACPI_RESOURCE_NAME_PIN_GROUP:
645fdaa0980SMika Westerberg 
646fdaa0980SMika Westerberg 			extra_struct_bytes +=
647fdaa0980SMika Westerberg 			    aml_resource->pin_group.vendor_offset -
648fdaa0980SMika Westerberg 			    aml_resource->pin_group.pin_table_offset +
649fdaa0980SMika Westerberg 			    aml_resource->pin_group.vendor_length;
650fdaa0980SMika Westerberg 
651fdaa0980SMika Westerberg 			break;
652fdaa0980SMika Westerberg 
653f8a6c866SMika Westerberg 		case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION:
654f8a6c866SMika Westerberg 
655f8a6c866SMika Westerberg 			extra_struct_bytes +=
656f8a6c866SMika Westerberg 			    aml_resource->pin_group_function.vendor_offset -
657f8a6c866SMika Westerberg 			    aml_resource->pin_group_function.res_source_offset +
658f8a6c866SMika Westerberg 			    aml_resource->pin_group_function.vendor_length;
659f8a6c866SMika Westerberg 
660f8a6c866SMika Westerberg 			break;
661f8a6c866SMika Westerberg 
662044b7239SMika Westerberg 		case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG:
663044b7239SMika Westerberg 
664044b7239SMika Westerberg 			extra_struct_bytes +=
665044b7239SMika Westerberg 			    aml_resource->pin_group_config.vendor_offset -
666044b7239SMika Westerberg 			    aml_resource->pin_group_config.res_source_offset +
667044b7239SMika Westerberg 			    aml_resource->pin_group_config.vendor_length;
668044b7239SMika Westerberg 
669044b7239SMika Westerberg 			break;
670044b7239SMika Westerberg 
671520d4a0eSNiyas Sait 		case ACPI_RESOURCE_NAME_CLOCK_INPUT:
672520d4a0eSNiyas Sait 			extra_struct_bytes =
673520d4a0eSNiyas Sait 			    acpi_rs_stream_option_length(resource_length,
674520d4a0eSNiyas Sait 							 minimum_aml_resource_length);
675520d4a0eSNiyas Sait 
676520d4a0eSNiyas Sait 			break;
677520d4a0eSNiyas Sait 
67895b482a8SLen Brown 		default:
6791d1ea1b7SChao Guan 
68095b482a8SLen Brown 			break;
68195b482a8SLen Brown 		}
68295b482a8SLen Brown 
68395b482a8SLen Brown 		/*
68495b482a8SLen Brown 		 * Update the required buffer size for the internal descriptor structs
68595b482a8SLen Brown 		 *
68695b482a8SLen Brown 		 * Important: Round the size up for the appropriate alignment. This
68795b482a8SLen Brown 		 * is a requirement on IA64.
68895b482a8SLen Brown 		 */
689e0fe0a8dSLin Ming 		if (acpi_ut_get_resource_type(aml_buffer) ==
690e0fe0a8dSLin Ming 		    ACPI_RESOURCE_NAME_SERIAL_BUS) {
691*5bd2315bSTamir Duberstein 
692*5bd2315bSTamir Duberstein 			/* Avoid undefined behavior: member access within misaligned address */
693*5bd2315bSTamir Duberstein 
694*5bd2315bSTamir Duberstein 			struct aml_resource_common_serialbus common_serial_bus;
695*5bd2315bSTamir Duberstein 			memcpy(&common_serial_bus, aml_resource,
696*5bd2315bSTamir Duberstein 			       sizeof(common_serial_bus));
697*5bd2315bSTamir Duberstein 
698e0fe0a8dSLin Ming 			buffer_size =
699e0fe0a8dSLin Ming 			    acpi_gbl_resource_struct_serial_bus_sizes
700*5bd2315bSTamir Duberstein 			    [common_serial_bus.type] + extra_struct_bytes;
701e0fe0a8dSLin Ming 		} else {
702e0fe0a8dSLin Ming 			buffer_size =
703e0fe0a8dSLin Ming 			    acpi_gbl_resource_struct_sizes[resource_index] +
704e0fe0a8dSLin Ming 			    extra_struct_bytes;
705e0fe0a8dSLin Ming 		}
70695b482a8SLen Brown 
7071fad8738SBob Moore 		buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
70895b482a8SLen Brown 		*size_needed += buffer_size;
70995b482a8SLen Brown 
71095b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
711a2befbb2SBob Moore 				  "Type %.2X, AmlLength %.2X InternalLength %.2X%8X\n",
71295b482a8SLen Brown 				  acpi_ut_get_resource_type(aml_buffer),
71395b482a8SLen Brown 				  acpi_ut_get_descriptor_length(aml_buffer),
714a2befbb2SBob Moore 				  ACPI_FORMAT_UINT64(*size_needed)));
71595b482a8SLen Brown 
71695b482a8SLen Brown 		/*
71795b482a8SLen Brown 		 * Point to the next resource within the AML stream using the length
71895b482a8SLen Brown 		 * contained in the resource descriptor header
71995b482a8SLen Brown 		 */
72095b482a8SLen Brown 		aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
72195b482a8SLen Brown 	}
72295b482a8SLen Brown 
72395b482a8SLen Brown 	/* Did not find an end_tag resource descriptor */
72495b482a8SLen Brown 
72595b482a8SLen Brown 	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
72695b482a8SLen Brown }
72795b482a8SLen Brown 
72895b482a8SLen Brown /*******************************************************************************
72995b482a8SLen Brown  *
73095b482a8SLen Brown  * FUNCTION:    acpi_rs_get_pci_routing_table_length
73195b482a8SLen Brown  *
73295b482a8SLen Brown  * PARAMETERS:  package_object          - Pointer to the package object
73395b482a8SLen Brown  *              buffer_size_needed      - u32 pointer of the size buffer
73495b482a8SLen Brown  *                                        needed to properly return the
73595b482a8SLen Brown  *                                        parsed data
73695b482a8SLen Brown  *
73795b482a8SLen Brown  * RETURN:      Status
73895b482a8SLen Brown  *
73995b482a8SLen Brown  * DESCRIPTION: Given a package representing a PCI routing table, this
74095b482a8SLen Brown  *              calculates the size of the corresponding linked list of
74195b482a8SLen Brown  *              descriptions.
74295b482a8SLen Brown  *
74395b482a8SLen Brown  ******************************************************************************/
74495b482a8SLen Brown 
74595b482a8SLen Brown acpi_status
acpi_rs_get_pci_routing_table_length(union acpi_operand_object * package_object,acpi_size * buffer_size_needed)74695b482a8SLen Brown acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
74795b482a8SLen Brown 				     acpi_size *buffer_size_needed)
74895b482a8SLen Brown {
74995b482a8SLen Brown 	u32 number_of_elements;
75095b482a8SLen Brown 	acpi_size temp_size_needed = 0;
75195b482a8SLen Brown 	union acpi_operand_object **top_object_list;
75295b482a8SLen Brown 	u32 index;
75395b482a8SLen Brown 	union acpi_operand_object *package_element;
75495b482a8SLen Brown 	union acpi_operand_object **sub_object_list;
75595b482a8SLen Brown 	u8 name_found;
75695b482a8SLen Brown 	u32 table_index;
75795b482a8SLen Brown 
75895b482a8SLen Brown 	ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
75995b482a8SLen Brown 
76095b482a8SLen Brown 	number_of_elements = package_object->package.count;
76195b482a8SLen Brown 
76295b482a8SLen Brown 	/*
76395b482a8SLen Brown 	 * Calculate the size of the return buffer.
76495b482a8SLen Brown 	 * The base size is the number of elements * the sizes of the
76595b482a8SLen Brown 	 * structures. Additional space for the strings is added below.
76695b482a8SLen Brown 	 * The minus one is to subtract the size of the u8 Source[1]
76795b482a8SLen Brown 	 * member because it is added below.
76895b482a8SLen Brown 	 *
76995b482a8SLen Brown 	 * But each PRT_ENTRY structure has a pointer to a string and
77095b482a8SLen Brown 	 * the size of that string must be found.
77195b482a8SLen Brown 	 */
77295b482a8SLen Brown 	top_object_list = package_object->package.elements;
77395b482a8SLen Brown 
77495b482a8SLen Brown 	for (index = 0; index < number_of_elements; index++) {
77595b482a8SLen Brown 
7760a16d12aSBob Moore 		/* Dereference the subpackage */
77795b482a8SLen Brown 
77895b482a8SLen Brown 		package_element = *top_object_list;
77995b482a8SLen Brown 
78053951bd5SRobert Moore 		/* We must have a valid Package object */
78153951bd5SRobert Moore 
78253951bd5SRobert Moore 		if (!package_element ||
78353951bd5SRobert Moore 		    (package_element->common.type != ACPI_TYPE_PACKAGE)) {
78453951bd5SRobert Moore 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
78553951bd5SRobert Moore 		}
78653951bd5SRobert Moore 
78795b482a8SLen Brown 		/*
78895b482a8SLen Brown 		 * The sub_object_list will now point to an array of the
78995b482a8SLen Brown 		 * four IRQ elements: Address, Pin, Source and source_index
79095b482a8SLen Brown 		 */
79195b482a8SLen Brown 		sub_object_list = package_element->package.elements;
79295b482a8SLen Brown 
79395b482a8SLen Brown 		/* Scan the irq_table_elements for the Source Name String */
79495b482a8SLen Brown 
79595b482a8SLen Brown 		name_found = FALSE;
79695b482a8SLen Brown 
797aa6329c4SLv Zheng 		for (table_index = 0;
798aa6329c4SLv Zheng 		     table_index < package_element->package.count
799aa6329c4SLv Zheng 		     && !name_found; table_index++) {
80095b482a8SLen Brown 			if (*sub_object_list &&	/* Null object allowed */
80195b482a8SLen Brown 			    ((ACPI_TYPE_STRING ==
8023371c19cSBob Moore 			      (*sub_object_list)->common.type) ||
80395b482a8SLen Brown 			     ((ACPI_TYPE_LOCAL_REFERENCE ==
8043371c19cSBob Moore 			       (*sub_object_list)->common.type) &&
80595b482a8SLen Brown 			      ((*sub_object_list)->reference.class ==
80695b482a8SLen Brown 			       ACPI_REFCLASS_NAME)))) {
80795b482a8SLen Brown 				name_found = TRUE;
80895b482a8SLen Brown 			} else {
80995b482a8SLen Brown 				/* Look at the next element */
81095b482a8SLen Brown 
81195b482a8SLen Brown 				sub_object_list++;
81295b482a8SLen Brown 			}
81395b482a8SLen Brown 		}
81495b482a8SLen Brown 
81595b482a8SLen Brown 		temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
81695b482a8SLen Brown 
81795b482a8SLen Brown 		/* Was a String type found? */
81895b482a8SLen Brown 
81995b482a8SLen Brown 		if (name_found) {
8203371c19cSBob Moore 			if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) {
82195b482a8SLen Brown 				/*
82295b482a8SLen Brown 				 * The length String.Length field does not include the
82395b482a8SLen Brown 				 * terminating NULL, add 1
82495b482a8SLen Brown 				 */
82595b482a8SLen Brown 				temp_size_needed += ((acpi_size)
82695b482a8SLen Brown 						     (*sub_object_list)->string.
82795b482a8SLen Brown 						     length + 1);
82895b482a8SLen Brown 			} else {
8291f86e8c1SLv Zheng 				temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
83095b482a8SLen Brown 			}
83195b482a8SLen Brown 		} else {
83295b482a8SLen Brown 			/*
83395b482a8SLen Brown 			 * If no name was found, then this is a NULL, which is
83495b482a8SLen Brown 			 * translated as a u32 zero.
83595b482a8SLen Brown 			 */
83695b482a8SLen Brown 			temp_size_needed += sizeof(u32);
83795b482a8SLen Brown 		}
83895b482a8SLen Brown 
83995b482a8SLen Brown 		/* Round up the size since each element must be aligned */
84095b482a8SLen Brown 
84195b482a8SLen Brown 		temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
84295b482a8SLen Brown 
84395b482a8SLen Brown 		/* Point to the next union acpi_operand_object */
84495b482a8SLen Brown 
84595b482a8SLen Brown 		top_object_list++;
84695b482a8SLen Brown 	}
84795b482a8SLen Brown 
84895b482a8SLen Brown 	/*
84995b482a8SLen Brown 	 * Add an extra element to the end of the list, essentially a
85095b482a8SLen Brown 	 * NULL terminator
85195b482a8SLen Brown 	 */
85295b482a8SLen Brown 	*buffer_size_needed =
85395b482a8SLen Brown 	    temp_size_needed + sizeof(struct acpi_pci_routing_table);
85495b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
85595b482a8SLen Brown }
856