1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /*******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: rscalc - Calculate stream and list lengths
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun ******************************************************************************/
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <acpi/acpi.h>
9*4882a593Smuzhiyun #include "accommon.h"
10*4882a593Smuzhiyun #include "acresrc.h"
11*4882a593Smuzhiyun #include "acnamesp.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #define _COMPONENT ACPI_RESOURCES
14*4882a593Smuzhiyun ACPI_MODULE_NAME("rscalc")
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun /* Local prototypes */
17*4882a593Smuzhiyun static u8 acpi_rs_count_set_bits(u16 bit_field);
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun static acpi_rs_length
20*4882a593Smuzhiyun acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun static u32
23*4882a593Smuzhiyun acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /*******************************************************************************
26*4882a593Smuzhiyun *
27*4882a593Smuzhiyun * FUNCTION: acpi_rs_count_set_bits
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * PARAMETERS: bit_field - Field in which to count bits
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * RETURN: Number of bits set within the field
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * DESCRIPTION: Count the number of bits set in a resource field. Used for
34*4882a593Smuzhiyun * (Short descriptor) interrupt and DMA lists.
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun ******************************************************************************/
37*4882a593Smuzhiyun
acpi_rs_count_set_bits(u16 bit_field)38*4882a593Smuzhiyun static u8 acpi_rs_count_set_bits(u16 bit_field)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun u8 bits_set;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun for (bits_set = 0; bit_field; bits_set++) {
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* Zero the least significant bit that is set */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun bit_field &= (u16) (bit_field - 1);
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun return (bits_set);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /*******************************************************************************
55*4882a593Smuzhiyun *
56*4882a593Smuzhiyun * FUNCTION: acpi_rs_struct_option_length
57*4882a593Smuzhiyun *
58*4882a593Smuzhiyun * PARAMETERS: resource_source - Pointer to optional descriptor field
59*4882a593Smuzhiyun *
60*4882a593Smuzhiyun * RETURN: Status
61*4882a593Smuzhiyun *
62*4882a593Smuzhiyun * DESCRIPTION: Common code to handle optional resource_source_index and
63*4882a593Smuzhiyun * resource_source fields in some Large descriptors. Used during
64*4882a593Smuzhiyun * list-to-stream conversion
65*4882a593Smuzhiyun *
66*4882a593Smuzhiyun ******************************************************************************/
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun static acpi_rs_length
acpi_rs_struct_option_length(struct acpi_resource_source * resource_source)69*4882a593Smuzhiyun acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /*
74*4882a593Smuzhiyun * If the resource_source string is valid, return the size of the string
75*4882a593Smuzhiyun * (string_length includes the NULL terminator) plus the size of the
76*4882a593Smuzhiyun * resource_source_index (1).
77*4882a593Smuzhiyun */
78*4882a593Smuzhiyun if (resource_source->string_ptr) {
79*4882a593Smuzhiyun return ((acpi_rs_length)(resource_source->string_length + 1));
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun return (0);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /*******************************************************************************
86*4882a593Smuzhiyun *
87*4882a593Smuzhiyun * FUNCTION: acpi_rs_stream_option_length
88*4882a593Smuzhiyun *
89*4882a593Smuzhiyun * PARAMETERS: resource_length - Length from the resource header
90*4882a593Smuzhiyun * minimum_total_length - Minimum length of this resource, before
91*4882a593Smuzhiyun * any optional fields. Includes header size
92*4882a593Smuzhiyun *
93*4882a593Smuzhiyun * RETURN: Length of optional string (0 if no string present)
94*4882a593Smuzhiyun *
95*4882a593Smuzhiyun * DESCRIPTION: Common code to handle optional resource_source_index and
96*4882a593Smuzhiyun * resource_source fields in some Large descriptors. Used during
97*4882a593Smuzhiyun * stream-to-list conversion
98*4882a593Smuzhiyun *
99*4882a593Smuzhiyun ******************************************************************************/
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun static u32
acpi_rs_stream_option_length(u32 resource_length,u32 minimum_aml_resource_length)102*4882a593Smuzhiyun acpi_rs_stream_option_length(u32 resource_length,
103*4882a593Smuzhiyun u32 minimum_aml_resource_length)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun u32 string_length = 0;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /*
110*4882a593Smuzhiyun * The resource_source_index and resource_source are optional elements of
111*4882a593Smuzhiyun * some Large-type resource descriptors.
112*4882a593Smuzhiyun */
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /*
115*4882a593Smuzhiyun * If the length of the actual resource descriptor is greater than the
116*4882a593Smuzhiyun * ACPI spec-defined minimum length, it means that a resource_source_index
117*4882a593Smuzhiyun * exists and is followed by a (required) null terminated string. The
118*4882a593Smuzhiyun * string length (including the null terminator) is the resource length
119*4882a593Smuzhiyun * minus the minimum length, minus one byte for the resource_source_index
120*4882a593Smuzhiyun * itself.
121*4882a593Smuzhiyun */
122*4882a593Smuzhiyun if (resource_length > minimum_aml_resource_length) {
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /* Compute the length of the optional string */
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun string_length =
127*4882a593Smuzhiyun resource_length - minimum_aml_resource_length - 1;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /*
131*4882a593Smuzhiyun * Round the length up to a multiple of the native word in order to
132*4882a593Smuzhiyun * guarantee that the entire resource descriptor is native word aligned
133*4882a593Smuzhiyun */
134*4882a593Smuzhiyun return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /*******************************************************************************
138*4882a593Smuzhiyun *
139*4882a593Smuzhiyun * FUNCTION: acpi_rs_get_aml_length
140*4882a593Smuzhiyun *
141*4882a593Smuzhiyun * PARAMETERS: resource - Pointer to the resource linked list
142*4882a593Smuzhiyun * resource_list_size - Size of the resource linked list
143*4882a593Smuzhiyun * size_needed - Where the required size is returned
144*4882a593Smuzhiyun *
145*4882a593Smuzhiyun * RETURN: Status
146*4882a593Smuzhiyun *
147*4882a593Smuzhiyun * DESCRIPTION: Takes a linked list of internal resource descriptors and
148*4882a593Smuzhiyun * calculates the size buffer needed to hold the corresponding
149*4882a593Smuzhiyun * external resource byte stream.
150*4882a593Smuzhiyun *
151*4882a593Smuzhiyun ******************************************************************************/
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun acpi_status
acpi_rs_get_aml_length(struct acpi_resource * resource,acpi_size resource_list_size,acpi_size * size_needed)154*4882a593Smuzhiyun acpi_rs_get_aml_length(struct acpi_resource *resource,
155*4882a593Smuzhiyun acpi_size resource_list_size, acpi_size *size_needed)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun acpi_size aml_size_needed = 0;
158*4882a593Smuzhiyun struct acpi_resource *resource_end;
159*4882a593Smuzhiyun acpi_rs_length total_size;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(rs_get_aml_length);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /* Traverse entire list of internal resource descriptors */
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun resource_end =
166*4882a593Smuzhiyun ACPI_ADD_PTR(struct acpi_resource, resource, resource_list_size);
167*4882a593Smuzhiyun while (resource < resource_end) {
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* Validate the descriptor type */
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
172*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /* Sanity check the length. It must not be zero, or we loop forever */
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if (!resource->length) {
178*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /* Get the base size of the (external stream) resource descriptor */
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun total_size = acpi_gbl_aml_resource_sizes[resource->type];
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /*
186*4882a593Smuzhiyun * Augment the base size for descriptors with optional and/or
187*4882a593Smuzhiyun * variable-length fields
188*4882a593Smuzhiyun */
189*4882a593Smuzhiyun switch (resource->type) {
190*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_IRQ:
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun /* Length can be 3 or 2 */
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun if (resource->data.irq.descriptor_length == 2) {
195*4882a593Smuzhiyun total_size--;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun break;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_START_DEPENDENT:
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /* Length can be 1 or 0 */
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun if (resource->data.irq.descriptor_length == 0) {
204*4882a593Smuzhiyun total_size--;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun break;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_VENDOR:
209*4882a593Smuzhiyun /*
210*4882a593Smuzhiyun * Vendor Defined Resource:
211*4882a593Smuzhiyun * For a Vendor Specific resource, if the Length is between 1 and 7
212*4882a593Smuzhiyun * it will be created as a Small Resource data type, otherwise it
213*4882a593Smuzhiyun * is a Large Resource data type.
214*4882a593Smuzhiyun */
215*4882a593Smuzhiyun if (resource->data.vendor.byte_length > 7) {
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* Base size of a Large resource descriptor */
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun total_size =
220*4882a593Smuzhiyun sizeof(struct aml_resource_large_header);
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /* Add the size of the vendor-specific data */
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun total_size = (acpi_rs_length)
226*4882a593Smuzhiyun (total_size + resource->data.vendor.byte_length);
227*4882a593Smuzhiyun break;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_END_TAG:
230*4882a593Smuzhiyun /*
231*4882a593Smuzhiyun * End Tag:
232*4882a593Smuzhiyun * We are done -- return the accumulated total size.
233*4882a593Smuzhiyun */
234*4882a593Smuzhiyun *size_needed = aml_size_needed + total_size;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun /* Normal exit */
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_ADDRESS16:
241*4882a593Smuzhiyun /*
242*4882a593Smuzhiyun * 16-Bit Address Resource:
243*4882a593Smuzhiyun * Add the size of the optional resource_source info
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
246*4882a593Smuzhiyun acpi_rs_struct_option_length
247*4882a593Smuzhiyun (&resource->data.
248*4882a593Smuzhiyun address16.
249*4882a593Smuzhiyun resource_source));
250*4882a593Smuzhiyun break;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_ADDRESS32:
253*4882a593Smuzhiyun /*
254*4882a593Smuzhiyun * 32-Bit Address Resource:
255*4882a593Smuzhiyun * Add the size of the optional resource_source info
256*4882a593Smuzhiyun */
257*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
258*4882a593Smuzhiyun acpi_rs_struct_option_length
259*4882a593Smuzhiyun (&resource->data.
260*4882a593Smuzhiyun address32.
261*4882a593Smuzhiyun resource_source));
262*4882a593Smuzhiyun break;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_ADDRESS64:
265*4882a593Smuzhiyun /*
266*4882a593Smuzhiyun * 64-Bit Address Resource:
267*4882a593Smuzhiyun * Add the size of the optional resource_source info
268*4882a593Smuzhiyun */
269*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
270*4882a593Smuzhiyun acpi_rs_struct_option_length
271*4882a593Smuzhiyun (&resource->data.
272*4882a593Smuzhiyun address64.
273*4882a593Smuzhiyun resource_source));
274*4882a593Smuzhiyun break;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
277*4882a593Smuzhiyun /*
278*4882a593Smuzhiyun * Extended IRQ Resource:
279*4882a593Smuzhiyun * Add the size of each additional optional interrupt beyond the
280*4882a593Smuzhiyun * required 1 (4 bytes for each u32 interrupt number)
281*4882a593Smuzhiyun */
282*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
283*4882a593Smuzhiyun ((resource->data.
284*4882a593Smuzhiyun extended_irq.
285*4882a593Smuzhiyun interrupt_count -
286*4882a593Smuzhiyun 1) * 4) +
287*4882a593Smuzhiyun /* Add the size of the optional resource_source info */
288*4882a593Smuzhiyun acpi_rs_struct_option_length
289*4882a593Smuzhiyun (&resource->data.
290*4882a593Smuzhiyun extended_irq.
291*4882a593Smuzhiyun resource_source));
292*4882a593Smuzhiyun break;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_GPIO:
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
297*4882a593Smuzhiyun (resource->data.gpio.
298*4882a593Smuzhiyun pin_table_length * 2) +
299*4882a593Smuzhiyun resource->data.gpio.
300*4882a593Smuzhiyun resource_source.
301*4882a593Smuzhiyun string_length +
302*4882a593Smuzhiyun resource->data.gpio.
303*4882a593Smuzhiyun vendor_length);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun break;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_PIN_FUNCTION:
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
310*4882a593Smuzhiyun (resource->data.
311*4882a593Smuzhiyun pin_function.
312*4882a593Smuzhiyun pin_table_length * 2) +
313*4882a593Smuzhiyun resource->data.
314*4882a593Smuzhiyun pin_function.
315*4882a593Smuzhiyun resource_source.
316*4882a593Smuzhiyun string_length +
317*4882a593Smuzhiyun resource->data.
318*4882a593Smuzhiyun pin_function.
319*4882a593Smuzhiyun vendor_length);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun break;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_SERIAL_BUS:
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun total_size =
326*4882a593Smuzhiyun acpi_gbl_aml_resource_serial_bus_sizes[resource->
327*4882a593Smuzhiyun data.
328*4882a593Smuzhiyun common_serial_bus.
329*4882a593Smuzhiyun type];
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
332*4882a593Smuzhiyun resource->data.
333*4882a593Smuzhiyun i2c_serial_bus.
334*4882a593Smuzhiyun resource_source.
335*4882a593Smuzhiyun string_length +
336*4882a593Smuzhiyun resource->data.
337*4882a593Smuzhiyun i2c_serial_bus.
338*4882a593Smuzhiyun vendor_length);
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun break;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_PIN_CONFIG:
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
345*4882a593Smuzhiyun (resource->data.
346*4882a593Smuzhiyun pin_config.
347*4882a593Smuzhiyun pin_table_length * 2) +
348*4882a593Smuzhiyun resource->data.pin_config.
349*4882a593Smuzhiyun resource_source.
350*4882a593Smuzhiyun string_length +
351*4882a593Smuzhiyun resource->data.pin_config.
352*4882a593Smuzhiyun vendor_length);
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun break;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_PIN_GROUP:
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
359*4882a593Smuzhiyun (resource->data.pin_group.
360*4882a593Smuzhiyun pin_table_length * 2) +
361*4882a593Smuzhiyun resource->data.pin_group.
362*4882a593Smuzhiyun resource_label.
363*4882a593Smuzhiyun string_length +
364*4882a593Smuzhiyun resource->data.pin_group.
365*4882a593Smuzhiyun vendor_length);
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun break;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION:
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
372*4882a593Smuzhiyun resource->data.
373*4882a593Smuzhiyun pin_group_function.
374*4882a593Smuzhiyun resource_source.
375*4882a593Smuzhiyun string_length +
376*4882a593Smuzhiyun resource->data.
377*4882a593Smuzhiyun pin_group_function.
378*4882a593Smuzhiyun resource_source_label.
379*4882a593Smuzhiyun string_length +
380*4882a593Smuzhiyun resource->data.
381*4882a593Smuzhiyun pin_group_function.
382*4882a593Smuzhiyun vendor_length);
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun break;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG:
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun total_size = (acpi_rs_length)(total_size +
389*4882a593Smuzhiyun resource->data.
390*4882a593Smuzhiyun pin_group_config.
391*4882a593Smuzhiyun resource_source.
392*4882a593Smuzhiyun string_length +
393*4882a593Smuzhiyun resource->data.
394*4882a593Smuzhiyun pin_group_config.
395*4882a593Smuzhiyun resource_source_label.
396*4882a593Smuzhiyun string_length +
397*4882a593Smuzhiyun resource->data.
398*4882a593Smuzhiyun pin_group_config.
399*4882a593Smuzhiyun vendor_length);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun break;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun default:
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun break;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun /* Update the total */
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun aml_size_needed += total_size;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* Point to the next object */
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun resource =
415*4882a593Smuzhiyun ACPI_ADD_PTR(struct acpi_resource, resource,
416*4882a593Smuzhiyun resource->length);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun /* Did not find an end_tag resource descriptor */
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /*******************************************************************************
425*4882a593Smuzhiyun *
426*4882a593Smuzhiyun * FUNCTION: acpi_rs_get_list_length
427*4882a593Smuzhiyun *
428*4882a593Smuzhiyun * PARAMETERS: aml_buffer - Pointer to the resource byte stream
429*4882a593Smuzhiyun * aml_buffer_length - Size of aml_buffer
430*4882a593Smuzhiyun * size_needed - Where the size needed is returned
431*4882a593Smuzhiyun *
432*4882a593Smuzhiyun * RETURN: Status
433*4882a593Smuzhiyun *
434*4882a593Smuzhiyun * DESCRIPTION: Takes an external resource byte stream and calculates the size
435*4882a593Smuzhiyun * buffer needed to hold the corresponding internal resource
436*4882a593Smuzhiyun * descriptor linked list.
437*4882a593Smuzhiyun *
438*4882a593Smuzhiyun ******************************************************************************/
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun acpi_status
acpi_rs_get_list_length(u8 * aml_buffer,u32 aml_buffer_length,acpi_size * size_needed)441*4882a593Smuzhiyun acpi_rs_get_list_length(u8 *aml_buffer,
442*4882a593Smuzhiyun u32 aml_buffer_length, acpi_size *size_needed)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun acpi_status status;
445*4882a593Smuzhiyun u8 *end_aml;
446*4882a593Smuzhiyun u8 *buffer;
447*4882a593Smuzhiyun u32 buffer_size;
448*4882a593Smuzhiyun u16 temp16;
449*4882a593Smuzhiyun u16 resource_length;
450*4882a593Smuzhiyun u32 extra_struct_bytes;
451*4882a593Smuzhiyun u8 resource_index;
452*4882a593Smuzhiyun u8 minimum_aml_resource_length;
453*4882a593Smuzhiyun union aml_resource *aml_resource;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(rs_get_list_length);
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun *size_needed = ACPI_RS_SIZE_MIN; /* Minimum size is one end_tag */
458*4882a593Smuzhiyun end_aml = aml_buffer + aml_buffer_length;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun /* Walk the list of AML resource descriptors */
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun while (aml_buffer < end_aml) {
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun /* Validate the Resource Type and Resource Length */
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun status =
467*4882a593Smuzhiyun acpi_ut_validate_resource(NULL, aml_buffer,
468*4882a593Smuzhiyun &resource_index);
469*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
470*4882a593Smuzhiyun /*
471*4882a593Smuzhiyun * Exit on failure. Cannot continue because the descriptor length
472*4882a593Smuzhiyun * may be bogus also.
473*4882a593Smuzhiyun */
474*4882a593Smuzhiyun return_ACPI_STATUS(status);
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun aml_resource = (void *)aml_buffer;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun /* Get the resource length and base (minimum) AML size */
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun resource_length = acpi_ut_get_resource_length(aml_buffer);
482*4882a593Smuzhiyun minimum_aml_resource_length =
483*4882a593Smuzhiyun acpi_gbl_resource_aml_sizes[resource_index];
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun /*
486*4882a593Smuzhiyun * Augment the size for descriptors with optional
487*4882a593Smuzhiyun * and/or variable length fields
488*4882a593Smuzhiyun */
489*4882a593Smuzhiyun extra_struct_bytes = 0;
490*4882a593Smuzhiyun buffer =
491*4882a593Smuzhiyun aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun switch (acpi_ut_get_resource_type(aml_buffer)) {
494*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_IRQ:
495*4882a593Smuzhiyun /*
496*4882a593Smuzhiyun * IRQ Resource:
497*4882a593Smuzhiyun * Get the number of bits set in the 16-bit IRQ mask
498*4882a593Smuzhiyun */
499*4882a593Smuzhiyun ACPI_MOVE_16_TO_16(&temp16, buffer);
500*4882a593Smuzhiyun extra_struct_bytes = acpi_rs_count_set_bits(temp16);
501*4882a593Smuzhiyun break;
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_DMA:
504*4882a593Smuzhiyun /*
505*4882a593Smuzhiyun * DMA Resource:
506*4882a593Smuzhiyun * Get the number of bits set in the 8-bit DMA mask
507*4882a593Smuzhiyun */
508*4882a593Smuzhiyun extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
509*4882a593Smuzhiyun break;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_VENDOR_SMALL:
512*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_VENDOR_LARGE:
513*4882a593Smuzhiyun /*
514*4882a593Smuzhiyun * Vendor Resource:
515*4882a593Smuzhiyun * Get the number of vendor data bytes
516*4882a593Smuzhiyun */
517*4882a593Smuzhiyun extra_struct_bytes = resource_length;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun /*
520*4882a593Smuzhiyun * There is already one byte included in the minimum
521*4882a593Smuzhiyun * descriptor size. If there are extra struct bytes,
522*4882a593Smuzhiyun * subtract one from the count.
523*4882a593Smuzhiyun */
524*4882a593Smuzhiyun if (extra_struct_bytes) {
525*4882a593Smuzhiyun extra_struct_bytes--;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun break;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_END_TAG:
530*4882a593Smuzhiyun /*
531*4882a593Smuzhiyun * End Tag: This is the normal exit
532*4882a593Smuzhiyun */
533*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_ADDRESS32:
536*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_ADDRESS16:
537*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_ADDRESS64:
538*4882a593Smuzhiyun /*
539*4882a593Smuzhiyun * Address Resource:
540*4882a593Smuzhiyun * Add the size of the optional resource_source
541*4882a593Smuzhiyun */
542*4882a593Smuzhiyun extra_struct_bytes =
543*4882a593Smuzhiyun acpi_rs_stream_option_length(resource_length,
544*4882a593Smuzhiyun minimum_aml_resource_length);
545*4882a593Smuzhiyun break;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
548*4882a593Smuzhiyun /*
549*4882a593Smuzhiyun * Extended IRQ Resource:
550*4882a593Smuzhiyun * Using the interrupt_table_length, add 4 bytes for each additional
551*4882a593Smuzhiyun * interrupt. Note: at least one interrupt is required and is
552*4882a593Smuzhiyun * included in the minimum descriptor size (reason for the -1)
553*4882a593Smuzhiyun */
554*4882a593Smuzhiyun extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun /* Add the size of the optional resource_source */
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun extra_struct_bytes +=
559*4882a593Smuzhiyun acpi_rs_stream_option_length(resource_length -
560*4882a593Smuzhiyun extra_struct_bytes,
561*4882a593Smuzhiyun minimum_aml_resource_length);
562*4882a593Smuzhiyun break;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_GPIO:
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun /* Vendor data is optional */
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun if (aml_resource->gpio.vendor_length) {
569*4882a593Smuzhiyun extra_struct_bytes +=
570*4882a593Smuzhiyun aml_resource->gpio.vendor_offset -
571*4882a593Smuzhiyun aml_resource->gpio.pin_table_offset +
572*4882a593Smuzhiyun aml_resource->gpio.vendor_length;
573*4882a593Smuzhiyun } else {
574*4882a593Smuzhiyun extra_struct_bytes +=
575*4882a593Smuzhiyun aml_resource->large_header.resource_length +
576*4882a593Smuzhiyun sizeof(struct aml_resource_large_header) -
577*4882a593Smuzhiyun aml_resource->gpio.pin_table_offset;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun break;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_PIN_FUNCTION:
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun /* Vendor data is optional */
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun if (aml_resource->pin_function.vendor_length) {
586*4882a593Smuzhiyun extra_struct_bytes +=
587*4882a593Smuzhiyun aml_resource->pin_function.vendor_offset -
588*4882a593Smuzhiyun aml_resource->pin_function.
589*4882a593Smuzhiyun pin_table_offset +
590*4882a593Smuzhiyun aml_resource->pin_function.vendor_length;
591*4882a593Smuzhiyun } else {
592*4882a593Smuzhiyun extra_struct_bytes +=
593*4882a593Smuzhiyun aml_resource->large_header.resource_length +
594*4882a593Smuzhiyun sizeof(struct aml_resource_large_header) -
595*4882a593Smuzhiyun aml_resource->pin_function.pin_table_offset;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun break;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_SERIAL_BUS:
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun minimum_aml_resource_length =
602*4882a593Smuzhiyun acpi_gbl_resource_aml_serial_bus_sizes
603*4882a593Smuzhiyun [aml_resource->common_serial_bus.type];
604*4882a593Smuzhiyun extra_struct_bytes +=
605*4882a593Smuzhiyun aml_resource->common_serial_bus.resource_length -
606*4882a593Smuzhiyun minimum_aml_resource_length;
607*4882a593Smuzhiyun break;
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_PIN_CONFIG:
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun /* Vendor data is optional */
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun if (aml_resource->pin_config.vendor_length) {
614*4882a593Smuzhiyun extra_struct_bytes +=
615*4882a593Smuzhiyun aml_resource->pin_config.vendor_offset -
616*4882a593Smuzhiyun aml_resource->pin_config.pin_table_offset +
617*4882a593Smuzhiyun aml_resource->pin_config.vendor_length;
618*4882a593Smuzhiyun } else {
619*4882a593Smuzhiyun extra_struct_bytes +=
620*4882a593Smuzhiyun aml_resource->large_header.resource_length +
621*4882a593Smuzhiyun sizeof(struct aml_resource_large_header) -
622*4882a593Smuzhiyun aml_resource->pin_config.pin_table_offset;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun break;
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_PIN_GROUP:
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun extra_struct_bytes +=
629*4882a593Smuzhiyun aml_resource->pin_group.vendor_offset -
630*4882a593Smuzhiyun aml_resource->pin_group.pin_table_offset +
631*4882a593Smuzhiyun aml_resource->pin_group.vendor_length;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun break;
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION:
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun extra_struct_bytes +=
638*4882a593Smuzhiyun aml_resource->pin_group_function.vendor_offset -
639*4882a593Smuzhiyun aml_resource->pin_group_function.res_source_offset +
640*4882a593Smuzhiyun aml_resource->pin_group_function.vendor_length;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun break;
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG:
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun extra_struct_bytes +=
647*4882a593Smuzhiyun aml_resource->pin_group_config.vendor_offset -
648*4882a593Smuzhiyun aml_resource->pin_group_config.res_source_offset +
649*4882a593Smuzhiyun aml_resource->pin_group_config.vendor_length;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun break;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun default:
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun break;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun /*
659*4882a593Smuzhiyun * Update the required buffer size for the internal descriptor structs
660*4882a593Smuzhiyun *
661*4882a593Smuzhiyun * Important: Round the size up for the appropriate alignment. This
662*4882a593Smuzhiyun * is a requirement on IA64.
663*4882a593Smuzhiyun */
664*4882a593Smuzhiyun if (acpi_ut_get_resource_type(aml_buffer) ==
665*4882a593Smuzhiyun ACPI_RESOURCE_NAME_SERIAL_BUS) {
666*4882a593Smuzhiyun buffer_size =
667*4882a593Smuzhiyun acpi_gbl_resource_struct_serial_bus_sizes
668*4882a593Smuzhiyun [aml_resource->common_serial_bus.type] +
669*4882a593Smuzhiyun extra_struct_bytes;
670*4882a593Smuzhiyun } else {
671*4882a593Smuzhiyun buffer_size =
672*4882a593Smuzhiyun acpi_gbl_resource_struct_sizes[resource_index] +
673*4882a593Smuzhiyun extra_struct_bytes;
674*4882a593Smuzhiyun }
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
677*4882a593Smuzhiyun *size_needed += buffer_size;
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
680*4882a593Smuzhiyun "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
681*4882a593Smuzhiyun acpi_ut_get_resource_type(aml_buffer),
682*4882a593Smuzhiyun acpi_ut_get_descriptor_length(aml_buffer),
683*4882a593Smuzhiyun buffer_size));
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun /*
686*4882a593Smuzhiyun * Point to the next resource within the AML stream using the length
687*4882a593Smuzhiyun * contained in the resource descriptor header
688*4882a593Smuzhiyun */
689*4882a593Smuzhiyun aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun /* Did not find an end_tag resource descriptor */
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun /*******************************************************************************
698*4882a593Smuzhiyun *
699*4882a593Smuzhiyun * FUNCTION: acpi_rs_get_pci_routing_table_length
700*4882a593Smuzhiyun *
701*4882a593Smuzhiyun * PARAMETERS: package_object - Pointer to the package object
702*4882a593Smuzhiyun * buffer_size_needed - u32 pointer of the size buffer
703*4882a593Smuzhiyun * needed to properly return the
704*4882a593Smuzhiyun * parsed data
705*4882a593Smuzhiyun *
706*4882a593Smuzhiyun * RETURN: Status
707*4882a593Smuzhiyun *
708*4882a593Smuzhiyun * DESCRIPTION: Given a package representing a PCI routing table, this
709*4882a593Smuzhiyun * calculates the size of the corresponding linked list of
710*4882a593Smuzhiyun * descriptions.
711*4882a593Smuzhiyun *
712*4882a593Smuzhiyun ******************************************************************************/
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun acpi_status
acpi_rs_get_pci_routing_table_length(union acpi_operand_object * package_object,acpi_size * buffer_size_needed)715*4882a593Smuzhiyun acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
716*4882a593Smuzhiyun acpi_size *buffer_size_needed)
717*4882a593Smuzhiyun {
718*4882a593Smuzhiyun u32 number_of_elements;
719*4882a593Smuzhiyun acpi_size temp_size_needed = 0;
720*4882a593Smuzhiyun union acpi_operand_object **top_object_list;
721*4882a593Smuzhiyun u32 index;
722*4882a593Smuzhiyun union acpi_operand_object *package_element;
723*4882a593Smuzhiyun union acpi_operand_object **sub_object_list;
724*4882a593Smuzhiyun u8 name_found;
725*4882a593Smuzhiyun u32 table_index;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun number_of_elements = package_object->package.count;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun /*
732*4882a593Smuzhiyun * Calculate the size of the return buffer.
733*4882a593Smuzhiyun * The base size is the number of elements * the sizes of the
734*4882a593Smuzhiyun * structures. Additional space for the strings is added below.
735*4882a593Smuzhiyun * The minus one is to subtract the size of the u8 Source[1]
736*4882a593Smuzhiyun * member because it is added below.
737*4882a593Smuzhiyun *
738*4882a593Smuzhiyun * But each PRT_ENTRY structure has a pointer to a string and
739*4882a593Smuzhiyun * the size of that string must be found.
740*4882a593Smuzhiyun */
741*4882a593Smuzhiyun top_object_list = package_object->package.elements;
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun for (index = 0; index < number_of_elements; index++) {
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun /* Dereference the subpackage */
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun package_element = *top_object_list;
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun /* We must have a valid Package object */
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun if (!package_element ||
752*4882a593Smuzhiyun (package_element->common.type != ACPI_TYPE_PACKAGE)) {
753*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun /*
757*4882a593Smuzhiyun * The sub_object_list will now point to an array of the
758*4882a593Smuzhiyun * four IRQ elements: Address, Pin, Source and source_index
759*4882a593Smuzhiyun */
760*4882a593Smuzhiyun sub_object_list = package_element->package.elements;
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun /* Scan the irq_table_elements for the Source Name String */
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun name_found = FALSE;
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun for (table_index = 0;
767*4882a593Smuzhiyun table_index < package_element->package.count
768*4882a593Smuzhiyun && !name_found; table_index++) {
769*4882a593Smuzhiyun if (*sub_object_list && /* Null object allowed */
770*4882a593Smuzhiyun ((ACPI_TYPE_STRING ==
771*4882a593Smuzhiyun (*sub_object_list)->common.type) ||
772*4882a593Smuzhiyun ((ACPI_TYPE_LOCAL_REFERENCE ==
773*4882a593Smuzhiyun (*sub_object_list)->common.type) &&
774*4882a593Smuzhiyun ((*sub_object_list)->reference.class ==
775*4882a593Smuzhiyun ACPI_REFCLASS_NAME)))) {
776*4882a593Smuzhiyun name_found = TRUE;
777*4882a593Smuzhiyun } else {
778*4882a593Smuzhiyun /* Look at the next element */
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun sub_object_list++;
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun /* Was a String type found? */
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun if (name_found) {
789*4882a593Smuzhiyun if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) {
790*4882a593Smuzhiyun /*
791*4882a593Smuzhiyun * The length String.Length field does not include the
792*4882a593Smuzhiyun * terminating NULL, add 1
793*4882a593Smuzhiyun */
794*4882a593Smuzhiyun temp_size_needed += ((acpi_size)
795*4882a593Smuzhiyun (*sub_object_list)->string.
796*4882a593Smuzhiyun length + 1);
797*4882a593Smuzhiyun } else {
798*4882a593Smuzhiyun temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun } else {
801*4882a593Smuzhiyun /*
802*4882a593Smuzhiyun * If no name was found, then this is a NULL, which is
803*4882a593Smuzhiyun * translated as a u32 zero.
804*4882a593Smuzhiyun */
805*4882a593Smuzhiyun temp_size_needed += sizeof(u32);
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun /* Round up the size since each element must be aligned */
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun /* Point to the next union acpi_operand_object */
813*4882a593Smuzhiyun
814*4882a593Smuzhiyun top_object_list++;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun /*
818*4882a593Smuzhiyun * Add an extra element to the end of the list, essentially a
819*4882a593Smuzhiyun * NULL terminator
820*4882a593Smuzhiyun */
821*4882a593Smuzhiyun *buffer_size_needed =
822*4882a593Smuzhiyun temp_size_needed + sizeof(struct acpi_pci_routing_table);
823*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
824*4882a593Smuzhiyun }
825