rscalc.c 20.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/*******************************************************************************
 *
 * Module Name: rscalc - Calculate stream and list lengths
 *
 ******************************************************************************/

/*
8
 * Copyright (C) 2000 - 2013, Intel Corp.
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
L
Len Brown 已提交
45 46 47
#include "accommon.h"
#include "acresrc.h"
#include "acnamesp.h"
L
Linus Torvalds 已提交
48 49

#define _COMPONENT          ACPI_RESOURCES
L
Len Brown 已提交
50
ACPI_MODULE_NAME("rscalc")
L
Linus Torvalds 已提交
51

R
Robert Moore 已提交
52 53 54
/* Local prototypes */
static u8 acpi_rs_count_set_bits(u16 bit_field);

B
Bob Moore 已提交
55
static acpi_rs_length
R
Robert Moore 已提交
56 57 58 59 60
acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);

static u32
acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);

L
Linus Torvalds 已提交
61 62
/*******************************************************************************
 *
R
Robert Moore 已提交
63
 * FUNCTION:    acpi_rs_count_set_bits
L
Linus Torvalds 已提交
64
 *
R
Robert Moore 已提交
65
 * PARAMETERS:  bit_field       - Field in which to count bits
L
Linus Torvalds 已提交
66
 *
R
Robert Moore 已提交
67
 * RETURN:      Number of bits set within the field
L
Linus Torvalds 已提交
68
 *
R
Robert Moore 已提交
69 70
 * DESCRIPTION: Count the number of bits set in a resource field. Used for
 *              (Short descriptor) interrupt and DMA lists.
L
Linus Torvalds 已提交
71 72 73
 *
 ******************************************************************************/

R
Robert Moore 已提交
74 75
static u8 acpi_rs_count_set_bits(u16 bit_field)
{
76
	u8 bits_set;
R
Robert Moore 已提交
77

R
Robert Moore 已提交
78
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
79

R
Robert Moore 已提交
80
	for (bits_set = 0; bit_field; bits_set++) {
B
Bob Moore 已提交
81

R
Robert Moore 已提交
82
		/* Zero the least significant bit that is set */
L
Linus Torvalds 已提交
83

84
		bit_field &= (u16) (bit_field - 1);
R
Robert Moore 已提交
85
	}
L
Linus Torvalds 已提交
86

87
	return (bits_set);
R
Robert Moore 已提交
88
}
L
Linus Torvalds 已提交
89 90 91

/*******************************************************************************
 *
R
Robert Moore 已提交
92
 * FUNCTION:    acpi_rs_struct_option_length
L
Linus Torvalds 已提交
93
 *
R
Robert Moore 已提交
94
 * PARAMETERS:  resource_source     - Pointer to optional descriptor field
L
Linus Torvalds 已提交
95 96 97
 *
 * RETURN:      Status
 *
R
Robert Moore 已提交
98 99 100
 * DESCRIPTION: Common code to handle optional resource_source_index and
 *              resource_source fields in some Large descriptors. Used during
 *              list-to-stream conversion
L
Linus Torvalds 已提交
101 102 103
 *
 ******************************************************************************/

B
Bob Moore 已提交
104
static acpi_rs_length
R
Robert Moore 已提交
105
acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
L
Linus Torvalds 已提交
106
{
R
Robert Moore 已提交
107 108 109 110 111 112 113 114
	ACPI_FUNCTION_ENTRY();

	/*
	 * If the resource_source string is valid, return the size of the string
	 * (string_length includes the NULL terminator) plus the size of the
	 * resource_source_index (1).
	 */
	if (resource_source->string_ptr) {
B
Bob Moore 已提交
115
		return ((acpi_rs_length) (resource_source->string_length + 1));
R
Robert Moore 已提交
116
	}
L
Linus Torvalds 已提交
117

R
Robert Moore 已提交
118 119
	return (0);
}
L
Linus Torvalds 已提交
120

R
Robert Moore 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
/*******************************************************************************
 *
 * FUNCTION:    acpi_rs_stream_option_length
 *
 * PARAMETERS:  resource_length     - Length from the resource header
 *              minimum_total_length - Minimum length of this resource, before
 *                                    any optional fields. Includes header size
 *
 * RETURN:      Length of optional string (0 if no string present)
 *
 * DESCRIPTION: Common code to handle optional resource_source_index and
 *              resource_source fields in some Large descriptors. Used during
 *              stream-to-list conversion
 *
 ******************************************************************************/
L
Linus Torvalds 已提交
136

R
Robert Moore 已提交
137
static u32
B
Bob Moore 已提交
138 139
acpi_rs_stream_option_length(u32 resource_length,
			     u32 minimum_aml_resource_length)
R
Robert Moore 已提交
140 141
{
	u32 string_length = 0;
L
Linus Torvalds 已提交
142

R
Robert Moore 已提交
143
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
144

R
Robert Moore 已提交
145 146 147 148
	/*
	 * The resource_source_index and resource_source are optional elements of some
	 * Large-type resource descriptors.
	 */
R
Robert Moore 已提交
149

R
Robert Moore 已提交
150 151 152 153 154 155 156
	/*
	 * If the length of the actual resource descriptor is greater than the ACPI
	 * spec-defined minimum length, it means that a resource_source_index exists
	 * and is followed by a (required) null terminated string. The string length
	 * (including the null terminator) is the resource length minus the minimum
	 * length, minus one byte for the resource_source_index itself.
	 */
B
Bob Moore 已提交
157
	if (resource_length > minimum_aml_resource_length) {
B
Bob Moore 已提交
158

R
Robert Moore 已提交
159
		/* Compute the length of the optional string */
L
Linus Torvalds 已提交
160

B
Bob Moore 已提交
161 162
		string_length =
		    resource_length - minimum_aml_resource_length - 1;
R
Robert Moore 已提交
163
	}
L
Linus Torvalds 已提交
164

B
Bob Moore 已提交
165 166 167 168 169
	/*
	 * Round the length up to a multiple of the native word in order to
	 * guarantee that the entire resource descriptor is native word aligned
	 */
	return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
R
Robert Moore 已提交
170
}
L
Linus Torvalds 已提交
171

R
Robert Moore 已提交
172 173
/*******************************************************************************
 *
B
Bob Moore 已提交
174
 * FUNCTION:    acpi_rs_get_aml_length
R
Robert Moore 已提交
175
 *
176
 * PARAMETERS:  resource            - Pointer to the resource linked list
R
Robert Moore 已提交
177 178 179 180 181 182 183 184 185
 *              size_needed         - Where the required size is returned
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Takes a linked list of internal resource descriptors and
 *              calculates the size buffer needed to hold the corresponding
 *              external resource byte stream.
 *
 ******************************************************************************/
L
Linus Torvalds 已提交
186

R
Robert Moore 已提交
187
acpi_status
B
Bob Moore 已提交
188
acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
R
Robert Moore 已提交
189
{
B
Bob Moore 已提交
190
	acpi_size aml_size_needed = 0;
B
Bob Moore 已提交
191
	acpi_rs_length total_size;
L
Linus Torvalds 已提交
192

B
Bob Moore 已提交
193
	ACPI_FUNCTION_TRACE(rs_get_aml_length);
L
Linus Torvalds 已提交
194

R
Robert Moore 已提交
195
	/* Traverse entire list of internal resource descriptors */
L
Linus Torvalds 已提交
196

R
Robert Moore 已提交
197
	while (resource) {
B
Bob Moore 已提交
198

R
Robert Moore 已提交
199
		/* Validate the descriptor type */
L
Linus Torvalds 已提交
200

B
Bob Moore 已提交
201
		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
R
Robert Moore 已提交
202 203
			return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
		}
R
Robert Moore 已提交
204

205 206 207 208 209 210
		/* Sanity check the length. It must not be zero, or we loop forever */

		if (!resource->length) {
			return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
		}

R
Robert Moore 已提交
211
		/* Get the base size of the (external stream) resource descriptor */
L
Linus Torvalds 已提交
212

B
Bob Moore 已提交
213
		total_size = acpi_gbl_aml_resource_sizes[resource->type];
L
Linus Torvalds 已提交
214

R
Robert Moore 已提交
215 216 217 218 219
		/*
		 * Augment the base size for descriptors with optional and/or
		 * variable-length fields
		 */
		switch (resource->type) {
220 221
		case ACPI_RESOURCE_TYPE_IRQ:

222 223
			/* Length can be 3 or 2 */

224 225 226 227 228
			if (resource->data.irq.descriptor_length == 2) {
				total_size--;
			}
			break;

229 230 231 232 233 234 235 236 237
		case ACPI_RESOURCE_TYPE_START_DEPENDENT:

			/* Length can be 1 or 0 */

			if (resource->data.irq.descriptor_length == 0) {
				total_size--;
			}
			break;

B
Bob Moore 已提交
238
		case ACPI_RESOURCE_TYPE_VENDOR:
L
Linus Torvalds 已提交
239
			/*
R
Robert Moore 已提交
240 241 242 243
			 * Vendor Defined Resource:
			 * For a Vendor Specific resource, if the Length is between 1 and 7
			 * it will be created as a Small Resource data type, otherwise it
			 * is a Large Resource data type.
L
Linus Torvalds 已提交
244
			 */
B
Bob Moore 已提交
245
			if (resource->data.vendor.byte_length > 7) {
B
Bob Moore 已提交
246

R
Robert Moore 已提交
247
				/* Base size of a Large resource descriptor */
L
Linus Torvalds 已提交
248

B
Bob Moore 已提交
249
				total_size =
B
Bob Moore 已提交
250
				    sizeof(struct aml_resource_large_header);
L
Linus Torvalds 已提交
251 252
			}

R
Robert Moore 已提交
253
			/* Add the size of the vendor-specific data */
R
Robert Moore 已提交
254

B
Bob Moore 已提交
255 256
			total_size = (acpi_rs_length)
			    (total_size + resource->data.vendor.byte_length);
L
Linus Torvalds 已提交
257 258
			break;

B
Bob Moore 已提交
259
		case ACPI_RESOURCE_TYPE_END_TAG:
L
Linus Torvalds 已提交
260
			/*
R
Robert Moore 已提交
261 262
			 * End Tag:
			 * We are done -- return the accumulated total size.
L
Linus Torvalds 已提交
263
			 */
B
Bob Moore 已提交
264
			*size_needed = aml_size_needed + total_size;
L
Linus Torvalds 已提交
265

R
Robert Moore 已提交
266
			/* Normal exit */
L
Linus Torvalds 已提交
267

R
Robert Moore 已提交
268
			return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
269

B
Bob Moore 已提交
270
		case ACPI_RESOURCE_TYPE_ADDRESS16:
L
Linus Torvalds 已提交
271
			/*
R
Robert Moore 已提交
272 273
			 * 16-Bit Address Resource:
			 * Add the size of the optional resource_source info
L
Linus Torvalds 已提交
274
			 */
B
Bob Moore 已提交
275 276 277 278 279
			total_size = (acpi_rs_length)
			    (total_size +
			     acpi_rs_struct_option_length(&resource->data.
							  address16.
							  resource_source));
L
Linus Torvalds 已提交
280 281
			break;

B
Bob Moore 已提交
282
		case ACPI_RESOURCE_TYPE_ADDRESS32:
L
Linus Torvalds 已提交
283
			/*
R
Robert Moore 已提交
284 285
			 * 32-Bit Address Resource:
			 * Add the size of the optional resource_source info
L
Linus Torvalds 已提交
286
			 */
B
Bob Moore 已提交
287 288 289 290 291
			total_size = (acpi_rs_length)
			    (total_size +
			     acpi_rs_struct_option_length(&resource->data.
							  address32.
							  resource_source));
L
Linus Torvalds 已提交
292 293
			break;

B
Bob Moore 已提交
294
		case ACPI_RESOURCE_TYPE_ADDRESS64:
L
Linus Torvalds 已提交
295
			/*
R
Robert Moore 已提交
296 297
			 * 64-Bit Address Resource:
			 * Add the size of the optional resource_source info
L
Linus Torvalds 已提交
298
			 */
B
Bob Moore 已提交
299 300 301 302 303
			total_size = (acpi_rs_length)
			    (total_size +
			     acpi_rs_struct_option_length(&resource->data.
							  address64.
							  resource_source));
L
Linus Torvalds 已提交
304 305
			break;

B
Bob Moore 已提交
306
		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
L
Linus Torvalds 已提交
307
			/*
R
Robert Moore 已提交
308 309 310
			 * Extended IRQ Resource:
			 * Add the size of each additional optional interrupt beyond the
			 * required 1 (4 bytes for each u32 interrupt number)
L
Linus Torvalds 已提交
311
			 */
B
Bob Moore 已提交
312 313 314 315 316 317 318 319
			total_size = (acpi_rs_length)
			    (total_size +
			     ((resource->data.extended_irq.interrupt_count -
			       1) * 4) +
			     /* Add the size of the optional resource_source info */
			     acpi_rs_struct_option_length(&resource->data.
							  extended_irq.
							  resource_source));
R
Robert Moore 已提交
320
			break;
L
Linus Torvalds 已提交
321

322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
		case ACPI_RESOURCE_TYPE_GPIO:

			total_size =
			    (acpi_rs_length) (total_size +
					      (resource->data.gpio.
					       pin_table_length * 2) +
					      resource->data.gpio.
					      resource_source.string_length +
					      resource->data.gpio.
					      vendor_length);

			break;

		case ACPI_RESOURCE_TYPE_SERIAL_BUS:

			total_size =
			    acpi_gbl_aml_resource_serial_bus_sizes[resource->
								   data.
								   common_serial_bus.
								   type];

			total_size = (acpi_rs_length) (total_size +
						       resource->data.
						       i2c_serial_bus.
						       resource_source.
						       string_length +
						       resource->data.
						       i2c_serial_bus.
						       vendor_length);

			break;

R
Robert Moore 已提交
354
		default:
355

L
Linus Torvalds 已提交
356
			break;
R
Robert Moore 已提交
357
		}
L
Linus Torvalds 已提交
358

R
Robert Moore 已提交
359
		/* Update the total */
L
Linus Torvalds 已提交
360

B
Bob Moore 已提交
361
		aml_size_needed += total_size;
L
Linus Torvalds 已提交
362

R
Robert Moore 已提交
363
		/* Point to the next object */
L
Linus Torvalds 已提交
364

B
Bob Moore 已提交
365
		resource =
B
Bob Moore 已提交
366
		    ACPI_ADD_PTR(struct acpi_resource, resource,
B
Bob Moore 已提交
367
				 resource->length);
R
Robert Moore 已提交
368
	}
L
Linus Torvalds 已提交
369

B
Bob Moore 已提交
370
	/* Did not find an end_tag resource descriptor */
L
Linus Torvalds 已提交
371

B
Bob Moore 已提交
372
	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
R
Robert Moore 已提交
373
}
L
Linus Torvalds 已提交
374

R
Robert Moore 已提交
375 376 377 378
/*******************************************************************************
 *
 * FUNCTION:    acpi_rs_get_list_length
 *
B
Bob Moore 已提交
379 380 381
 * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
 *              aml_buffer_length   - Size of aml_buffer
 *              size_needed         - Where the size needed is returned
R
Robert Moore 已提交
382 383 384 385 386 387 388 389 390 391
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Takes an external resource byte stream and calculates the size
 *              buffer needed to hold the corresponding internal resource
 *              descriptor linked list.
 *
 ******************************************************************************/

acpi_status
B
Bob Moore 已提交
392 393
acpi_rs_get_list_length(u8 * aml_buffer,
			u32 aml_buffer_length, acpi_size * size_needed)
R
Robert Moore 已提交
394
{
B
Bob Moore 已提交
395 396
	acpi_status status;
	u8 *end_aml;
R
Robert Moore 已提交
397
	u8 *buffer;
B
Bob Moore 已提交
398
	u32 buffer_size;
R
Robert Moore 已提交
399 400 401
	u16 temp16;
	u16 resource_length;
	u32 extra_struct_bytes;
B
Bob Moore 已提交
402 403
	u8 resource_index;
	u8 minimum_aml_resource_length;
404
	union aml_resource *aml_resource;
L
Linus Torvalds 已提交
405

B
Bob Moore 已提交
406
	ACPI_FUNCTION_TRACE(rs_get_list_length);
L
Linus Torvalds 已提交
407

408
	*size_needed = ACPI_RS_SIZE_MIN;	/* Minimum size is one end_tag */
B
Bob Moore 已提交
409
	end_aml = aml_buffer + aml_buffer_length;
R
Robert Moore 已提交
410

B
Bob Moore 已提交
411
	/* Walk the list of AML resource descriptors */
L
Linus Torvalds 已提交
412

B
Bob Moore 已提交
413
	while (aml_buffer < end_aml) {
B
Bob Moore 已提交
414

B
Bob Moore 已提交
415
		/* Validate the Resource Type and Resource Length */
L
Linus Torvalds 已提交
416

417 418 419
		status =
		    acpi_ut_validate_resource(NULL, aml_buffer,
					      &resource_index);
B
Bob Moore 已提交
420
		if (ACPI_FAILURE(status)) {
421 422 423 424
			/*
			 * Exit on failure. Cannot continue because the descriptor length
			 * may be bogus also.
			 */
B
Bob Moore 已提交
425
			return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
426 427
		}

428 429
		aml_resource = (void *)aml_buffer;

B
Bob Moore 已提交
430
		/* Get the resource length and base (minimum) AML size */
R
Robert Moore 已提交
431

B
Bob Moore 已提交
432
		resource_length = acpi_ut_get_resource_length(aml_buffer);
B
Bob Moore 已提交
433 434
		minimum_aml_resource_length =
		    acpi_gbl_resource_aml_sizes[resource_index];
R
Robert Moore 已提交
435

B
Bob Moore 已提交
436 437 438 439
		/*
		 * Augment the size for descriptors with optional
		 * and/or variable length fields
		 */
R
Robert Moore 已提交
440
		extra_struct_bytes = 0;
B
Bob Moore 已提交
441 442
		buffer =
		    aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
R
Robert Moore 已提交
443

B
Bob Moore 已提交
444 445
		switch (acpi_ut_get_resource_type(aml_buffer)) {
		case ACPI_RESOURCE_NAME_IRQ:
R
Robert Moore 已提交
446
			/*
B
Bob Moore 已提交
447 448
			 * IRQ Resource:
			 * Get the number of bits set in the 16-bit IRQ mask
R
Robert Moore 已提交
449
			 */
B
Bob Moore 已提交
450
			ACPI_MOVE_16_TO_16(&temp16, buffer);
B
Bob Moore 已提交
451
			extra_struct_bytes = acpi_rs_count_set_bits(temp16);
B
Bob Moore 已提交
452 453 454
			break;

		case ACPI_RESOURCE_NAME_DMA:
R
Robert Moore 已提交
455
			/*
B
Bob Moore 已提交
456 457
			 * DMA Resource:
			 * Get the number of bits set in the 8-bit DMA mask
R
Robert Moore 已提交
458
			 */
B
Bob Moore 已提交
459
			extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
B
Bob Moore 已提交
460 461 462
			break;

		case ACPI_RESOURCE_NAME_VENDOR_SMALL:
B
Bob Moore 已提交
463
		case ACPI_RESOURCE_NAME_VENDOR_LARGE:
B
Bob Moore 已提交
464 465
			/*
			 * Vendor Resource:
B
Bob Moore 已提交
466
			 * Get the number of vendor data bytes
B
Bob Moore 已提交
467
			 */
B
Bob Moore 已提交
468
			extra_struct_bytes = resource_length;
469 470 471 472 473 474 475 476 477

			/*
			 * There is already one byte included in the minimum
			 * descriptor size. If there are extra struct bytes,
			 * subtract one from the count.
			 */
			if (extra_struct_bytes) {
				extra_struct_bytes--;
			}
B
Bob Moore 已提交
478 479 480 481
			break;

		case ACPI_RESOURCE_NAME_END_TAG:
			/*
482
			 * End Tag: This is the normal exit
B
Bob Moore 已提交
483 484 485 486 487
			 */
			return_ACPI_STATUS(AE_OK);

		case ACPI_RESOURCE_NAME_ADDRESS32:
		case ACPI_RESOURCE_NAME_ADDRESS16:
B
Bob Moore 已提交
488
		case ACPI_RESOURCE_NAME_ADDRESS64:
B
Bob Moore 已提交
489
			/*
B
Bob Moore 已提交
490 491
			 * Address Resource:
			 * Add the size of the optional resource_source
B
Bob Moore 已提交
492 493 494 495 496 497 498 499
			 */
			extra_struct_bytes =
			    acpi_rs_stream_option_length(resource_length,
							 minimum_aml_resource_length);
			break;

		case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
			/*
B
Bob Moore 已提交
500 501 502 503
			 * Extended IRQ Resource:
			 * Using the interrupt_table_length, add 4 bytes for each additional
			 * interrupt. Note: at least one interrupt is required and is
			 * included in the minimum descriptor size (reason for the -1)
B
Bob Moore 已提交
504
			 */
B
Bob Moore 已提交
505 506 507 508 509
			extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);

			/* Add the size of the optional resource_source */

			extra_struct_bytes +=
B
Bob Moore 已提交
510 511 512 513 514
			    acpi_rs_stream_option_length(resource_length -
							 extra_struct_bytes,
							 minimum_aml_resource_length);
			break;

515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
		case ACPI_RESOURCE_NAME_GPIO:

			/* Vendor data is optional */

			if (aml_resource->gpio.vendor_length) {
				extra_struct_bytes +=
				    aml_resource->gpio.vendor_offset -
				    aml_resource->gpio.pin_table_offset +
				    aml_resource->gpio.vendor_length;
			} else {
				extra_struct_bytes +=
				    aml_resource->large_header.resource_length +
				    sizeof(struct aml_resource_large_header) -
				    aml_resource->gpio.pin_table_offset;
			}
			break;

		case ACPI_RESOURCE_NAME_SERIAL_BUS:

			minimum_aml_resource_length =
			    acpi_gbl_resource_aml_serial_bus_sizes
			    [aml_resource->common_serial_bus.type];
			extra_struct_bytes +=
			    aml_resource->common_serial_bus.resource_length -
			    minimum_aml_resource_length;
			break;

B
Bob Moore 已提交
542
		default:
543

B
Bob Moore 已提交
544
			break;
R
Robert Moore 已提交
545
		}
R
Robert Moore 已提交
546

B
Bob Moore 已提交
547 548 549 550 551 552
		/*
		 * Update the required buffer size for the internal descriptor structs
		 *
		 * Important: Round the size up for the appropriate alignment. This
		 * is a requirement on IA64.
		 */
553 554 555 556 557 558 559 560 561 562 563 564
		if (acpi_ut_get_resource_type(aml_buffer) ==
		    ACPI_RESOURCE_NAME_SERIAL_BUS) {
			buffer_size =
			    acpi_gbl_resource_struct_serial_bus_sizes
			    [aml_resource->common_serial_bus.type] +
			    extra_struct_bytes;
		} else {
			buffer_size =
			    acpi_gbl_resource_struct_sizes[resource_index] +
			    extra_struct_bytes;
		}
		buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
B
Bob Moore 已提交
565 566

		*size_needed += buffer_size;
L
Linus Torvalds 已提交
567

B
Bob Moore 已提交
568
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
B
Bob Moore 已提交
569
				  "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
B
Bob Moore 已提交
570 571 572
				  acpi_ut_get_resource_type(aml_buffer),
				  acpi_ut_get_descriptor_length(aml_buffer),
				  buffer_size));
R
Robert Moore 已提交
573

R
Robert Moore 已提交
574
		/*
B
Bob Moore 已提交
575 576
		 * Point to the next resource within the AML stream using the length
		 * contained in the resource descriptor header
R
Robert Moore 已提交
577
		 */
B
Bob Moore 已提交
578
		aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
L
Linus Torvalds 已提交
579 580
	}

B
Bob Moore 已提交
581
	/* Did not find an end_tag resource descriptor */
R
Robert Moore 已提交
582

B
Bob Moore 已提交
583
	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
L
Linus Torvalds 已提交
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_rs_get_pci_routing_table_length
 *
 * PARAMETERS:  package_object          - Pointer to the package object
 *              buffer_size_needed      - u32 pointer of the size buffer
 *                                        needed to properly return the
 *                                        parsed data
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Given a package representing a PCI routing table, this
 *              calculates the size of the corresponding linked list of
 *              descriptions.
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
604 605
acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
				     acpi_size * buffer_size_needed)
L
Linus Torvalds 已提交
606
{
L
Len Brown 已提交
607 608 609 610 611 612 613 614
	u32 number_of_elements;
	acpi_size temp_size_needed = 0;
	union acpi_operand_object **top_object_list;
	u32 index;
	union acpi_operand_object *package_element;
	union acpi_operand_object **sub_object_list;
	u8 name_found;
	u32 table_index;
L
Linus Torvalds 已提交
615

B
Bob Moore 已提交
616
	ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
L
Linus Torvalds 已提交
617 618 619 620 621 622

	number_of_elements = package_object->package.count;

	/*
	 * Calculate the size of the return buffer.
	 * The base size is the number of elements * the sizes of the
623
	 * structures. Additional space for the strings is added below.
L
Linus Torvalds 已提交
624 625 626 627 628 629 630 631 632
	 * The minus one is to subtract the size of the u8 Source[1]
	 * member because it is added below.
	 *
	 * But each PRT_ENTRY structure has a pointer to a string and
	 * the size of that string must be found.
	 */
	top_object_list = package_object->package.elements;

	for (index = 0; index < number_of_elements; index++) {
B
Bob Moore 已提交
633

R
Robert Moore 已提交
634 635
		/* Dereference the sub-package */

L
Linus Torvalds 已提交
636 637
		package_element = *top_object_list;

638 639 640 641
		/* We must have a valid Package object */

		if (!package_element ||
		    (package_element->common.type != ACPI_TYPE_PACKAGE)) {
642
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
643 644
		}

L
Linus Torvalds 已提交
645 646 647 648 649 650
		/*
		 * The sub_object_list will now point to an array of the
		 * four IRQ elements: Address, Pin, Source and source_index
		 */
		sub_object_list = package_element->package.elements;

R
Robert Moore 已提交
651 652
		/* Scan the irq_table_elements for the Source Name String */

L
Linus Torvalds 已提交
653 654
		name_found = FALSE;

L
Len Brown 已提交
655 656
		for (table_index = 0; table_index < 4 && !name_found;
		     table_index++) {
B
Bob Moore 已提交
657 658
			if (*sub_object_list &&	/* Null object allowed */
			    ((ACPI_TYPE_STRING ==
659
			      (*sub_object_list)->common.type) ||
B
Bob Moore 已提交
660
			     ((ACPI_TYPE_LOCAL_REFERENCE ==
661
			       (*sub_object_list)->common.type) &&
662 663
			      ((*sub_object_list)->reference.class ==
			       ACPI_REFCLASS_NAME)))) {
L
Linus Torvalds 已提交
664
				name_found = TRUE;
L
Len Brown 已提交
665
			} else {
R
Robert Moore 已提交
666 667
				/* Look at the next element */

L
Linus Torvalds 已提交
668 669 670 671
				sub_object_list++;
			}
		}

L
Len Brown 已提交
672
		temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
L
Linus Torvalds 已提交
673

R
Robert Moore 已提交
674 675
		/* Was a String type found? */

L
Linus Torvalds 已提交
676
		if (name_found) {
677
			if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) {
L
Linus Torvalds 已提交
678 679 680 681
				/*
				 * The length String.Length field does not include the
				 * terminating NULL, add 1
				 */
R
Robert Moore 已提交
682
				temp_size_needed += ((acpi_size)
L
Len Brown 已提交
683 684 685
						     (*sub_object_list)->string.
						     length + 1);
			} else {
L
Lv Zheng 已提交
686
				temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
L
Linus Torvalds 已提交
687
			}
L
Len Brown 已提交
688
		} else {
L
Linus Torvalds 已提交
689 690 691 692
			/*
			 * If no name was found, then this is a NULL, which is
			 * translated as a u32 zero.
			 */
L
Len Brown 已提交
693
			temp_size_needed += sizeof(u32);
L
Linus Torvalds 已提交
694 695 696 697
		}

		/* Round up the size since each element must be aligned */

B
Bob Moore 已提交
698
		temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
L
Linus Torvalds 已提交
699

R
Robert Moore 已提交
700 701
		/* Point to the next union acpi_operand_object */

L
Linus Torvalds 已提交
702 703 704 705
		top_object_list++;
	}

	/*
B
Bob Moore 已提交
706
	 * Add an extra element to the end of the list, essentially a
R
Robert Moore 已提交
707
	 * NULL terminator
L
Linus Torvalds 已提交
708
	 */
L
Len Brown 已提交
709 710 711
	*buffer_size_needed =
	    temp_size_needed + sizeof(struct acpi_pci_routing_table);
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
712
}