diff options
author | Bob Moore <robert.moore@intel.com> | 2009-11-11 20:44:06 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-11-24 21:31:10 -0500 |
commit | ad5babeed8d3082406c5b67ae558b95a479ddb6f (patch) | |
tree | 1a39c2247ad6dc694d599543f2524c145e5efbf4 /drivers/acpi | |
parent | 419a909dd10142d015dd96457db1b1eda643f89e (diff) |
ACPICA: Add repair for predefined methods that must return sorted lists
This change will repair (by sorting) packages returned by _ALR,
_PSS, and _TSS. Drivers can now assume that the packages are
correctly sorted. Adds one new file, nsrepair2.c.
ACPICA BZ 784.
http://www.acpica.org/bugzilla/show_bug.cgi?id=784
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpica/Makefile | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/acnamesp.h | 13 | ||||
-rw-r--r-- | drivers/acpi/acpica/nspredef.c | 6 | ||||
-rw-r--r-- | drivers/acpi/acpica/nsrepair2.c | 540 |
4 files changed, 559 insertions, 2 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index e7973bc16846..7423052ece5a 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile | |||
@@ -28,7 +28,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o | |||
28 | acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \ | 28 | acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \ |
29 | nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ | 29 | nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ |
30 | nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ | 30 | nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ |
31 | nsparse.o nspredef.o nsrepair.o | 31 | nsparse.o nspredef.o nsrepair.o nsrepair2.o |
32 | 32 | ||
33 | acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o | 33 | acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o |
34 | 34 | ||
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 168e60893a2a..ab83919dda61 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h | |||
@@ -273,7 +273,8 @@ acpi_ns_get_attached_data(struct acpi_namespace_node *node, | |||
273 | acpi_object_handler handler, void **data); | 273 | acpi_object_handler handler, void **data); |
274 | 274 | ||
275 | /* | 275 | /* |
276 | * nsrepair - return object repair for predefined methods/objects | 276 | * nsrepair - General return object repair for all |
277 | * predefined methods/objects | ||
277 | */ | 278 | */ |
278 | acpi_status | 279 | acpi_status |
279 | acpi_ns_repair_object(struct acpi_predefined_data *data, | 280 | acpi_ns_repair_object(struct acpi_predefined_data *data, |
@@ -286,6 +287,16 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data, | |||
286 | union acpi_operand_object **obj_desc_ptr); | 287 | union acpi_operand_object **obj_desc_ptr); |
287 | 288 | ||
288 | /* | 289 | /* |
290 | * nsrepair2 - Return object repair for specific | ||
291 | * predefined methods/objects | ||
292 | */ | ||
293 | acpi_status | ||
294 | acpi_ns_complex_repairs(struct acpi_predefined_data *data, | ||
295 | struct acpi_namespace_node *node, | ||
296 | acpi_status validate_status, | ||
297 | union acpi_operand_object **return_object_ptr); | ||
298 | |||
299 | /* | ||
289 | * nssearch - Namespace searching and entry | 300 | * nssearch - Namespace searching and entry |
290 | */ | 301 | */ |
291 | acpi_status | 302 | acpi_status |
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 40280981033e..b05f42903c86 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c | |||
@@ -232,6 +232,12 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, | |||
232 | status = acpi_ns_check_package(data, return_object_ptr); | 232 | status = acpi_ns_check_package(data, return_object_ptr); |
233 | } | 233 | } |
234 | 234 | ||
235 | /* | ||
236 | * Perform additional, more complicated repairs on a per-name | ||
237 | * basis. | ||
238 | */ | ||
239 | status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); | ||
240 | |||
235 | check_validation_status: | 241 | check_validation_status: |
236 | /* | 242 | /* |
237 | * If the object validation failed or if we successfully repaired one | 243 | * If the object validation failed or if we successfully repaired one |
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c new file mode 100644 index 000000000000..d07b68613818 --- /dev/null +++ b/drivers/acpi/acpica/nsrepair2.c | |||
@@ -0,0 +1,540 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: nsrepair2 - Repair for objects returned by specific | ||
4 | * predefined methods | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2009, Intel Corp. | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include "accommon.h" | ||
47 | #include "acnamesp.h" | ||
48 | |||
49 | #define _COMPONENT ACPI_NAMESPACE | ||
50 | ACPI_MODULE_NAME("nsrepair2") | ||
51 | |||
52 | /* | ||
53 | * Information structure and handler for ACPI predefined names that can | ||
54 | * be repaired on a per-name basis. | ||
55 | */ | ||
56 | typedef | ||
57 | acpi_status(*acpi_repair_function) (struct acpi_predefined_data *data, | ||
58 | union acpi_operand_object **return_object_ptr); | ||
59 | |||
60 | typedef struct acpi_repair_info { | ||
61 | char name[ACPI_NAME_SIZE]; | ||
62 | acpi_repair_function repair_function; | ||
63 | |||
64 | } acpi_repair_info; | ||
65 | |||
66 | /* Local prototypes */ | ||
67 | |||
68 | static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct | ||
69 | acpi_namespace_node | ||
70 | *node); | ||
71 | |||
72 | static acpi_status | ||
73 | acpi_ns_repair_ALR(struct acpi_predefined_data *data, | ||
74 | union acpi_operand_object **return_object_ptr); | ||
75 | |||
76 | static acpi_status | ||
77 | acpi_ns_repair_PSS(struct acpi_predefined_data *data, | ||
78 | union acpi_operand_object **return_object_ptr); | ||
79 | |||
80 | static acpi_status | ||
81 | acpi_ns_repair_TSS(struct acpi_predefined_data *data, | ||
82 | union acpi_operand_object **return_object_ptr); | ||
83 | |||
84 | static acpi_status | ||
85 | acpi_ns_check_sorted_list(struct acpi_predefined_data *data, | ||
86 | union acpi_operand_object *return_object, | ||
87 | u32 expected_count, | ||
88 | u32 sort_index, | ||
89 | u8 sort_direction, char *sort_key_name); | ||
90 | |||
91 | static acpi_status | ||
92 | acpi_ns_remove_null_elements(union acpi_operand_object *package); | ||
93 | |||
94 | static acpi_status | ||
95 | acpi_ns_sort_list(union acpi_operand_object **elements, | ||
96 | u32 count, u32 index, u8 sort_direction); | ||
97 | |||
98 | /* Values for sort_direction above */ | ||
99 | |||
100 | #define ACPI_SORT_ASCENDING 0 | ||
101 | #define ACPI_SORT_DESCENDING 1 | ||
102 | |||
103 | /* | ||
104 | * This table contains the names of the predefined methods for which we can | ||
105 | * perform more complex repairs. | ||
106 | * | ||
107 | * _ALR: Sort the list ascending by ambient_illuminance if necessary | ||
108 | * _PSS: Sort the list descending by Power if necessary | ||
109 | * _TSS: Sort the list descending by Power if necessary | ||
110 | */ | ||
111 | static const struct acpi_repair_info acpi_ns_repairable_names[] = { | ||
112 | {"_ALR", acpi_ns_repair_ALR}, | ||
113 | {"_PSS", acpi_ns_repair_PSS}, | ||
114 | {"_TSS", acpi_ns_repair_TSS}, | ||
115 | {{0, 0, 0, 0}, NULL} /* Table terminator */ | ||
116 | }; | ||
117 | |||
118 | /****************************************************************************** | ||
119 | * | ||
120 | * FUNCTION: acpi_ns_complex_repairs | ||
121 | * | ||
122 | * PARAMETERS: Data - Pointer to validation data structure | ||
123 | * Node - Namespace node for the method/object | ||
124 | * validate_status - Original status of earlier validation | ||
125 | * return_object_ptr - Pointer to the object returned from the | ||
126 | * evaluation of a method or object | ||
127 | * | ||
128 | * RETURN: Status. AE_OK if repair was successful. If name is not | ||
129 | * matched, validate_status is returned. | ||
130 | * | ||
131 | * DESCRIPTION: Attempt to repair/convert a return object of a type that was | ||
132 | * not expected. | ||
133 | * | ||
134 | *****************************************************************************/ | ||
135 | |||
136 | acpi_status | ||
137 | acpi_ns_complex_repairs(struct acpi_predefined_data *data, | ||
138 | struct acpi_namespace_node *node, | ||
139 | acpi_status validate_status, | ||
140 | union acpi_operand_object **return_object_ptr) | ||
141 | { | ||
142 | const struct acpi_repair_info *predefined; | ||
143 | acpi_status status; | ||
144 | |||
145 | /* Check if this name is in the list of repairable names */ | ||
146 | |||
147 | predefined = acpi_ns_match_repairable_name(node); | ||
148 | if (!predefined) { | ||
149 | return (validate_status); | ||
150 | } | ||
151 | |||
152 | status = predefined->repair_function(data, return_object_ptr); | ||
153 | return (status); | ||
154 | } | ||
155 | |||
156 | /****************************************************************************** | ||
157 | * | ||
158 | * FUNCTION: acpi_ns_match_repairable_name | ||
159 | * | ||
160 | * PARAMETERS: Node - Namespace node for the method/object | ||
161 | * | ||
162 | * RETURN: Pointer to entry in repair table. NULL indicates not found. | ||
163 | * | ||
164 | * DESCRIPTION: Check an object name against the repairable object list. | ||
165 | * | ||
166 | *****************************************************************************/ | ||
167 | |||
168 | static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct | ||
169 | acpi_namespace_node | ||
170 | *node) | ||
171 | { | ||
172 | const struct acpi_repair_info *this_name; | ||
173 | |||
174 | /* Search info table for a repairable predefined method/object name */ | ||
175 | |||
176 | this_name = acpi_ns_repairable_names; | ||
177 | while (this_name->repair_function) { | ||
178 | if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) { | ||
179 | return (this_name); | ||
180 | } | ||
181 | this_name++; | ||
182 | } | ||
183 | |||
184 | return (NULL); /* Not found */ | ||
185 | } | ||
186 | |||
187 | /****************************************************************************** | ||
188 | * | ||
189 | * FUNCTION: acpi_ns_repair_ALR | ||
190 | * | ||
191 | * PARAMETERS: Data - Pointer to validation data structure | ||
192 | * return_object_ptr - Pointer to the object returned from the | ||
193 | * evaluation of a method or object | ||
194 | * | ||
195 | * RETURN: Status. AE_OK if object is OK or was repaired successfully | ||
196 | * | ||
197 | * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list | ||
198 | * ascending by the ambient illuminance values. | ||
199 | * | ||
200 | *****************************************************************************/ | ||
201 | |||
202 | static acpi_status | ||
203 | acpi_ns_repair_ALR(struct acpi_predefined_data *data, | ||
204 | union acpi_operand_object **return_object_ptr) | ||
205 | { | ||
206 | union acpi_operand_object *return_object = *return_object_ptr; | ||
207 | acpi_status status; | ||
208 | |||
209 | status = acpi_ns_check_sorted_list(data, return_object, 2, 1, | ||
210 | ACPI_SORT_ASCENDING, | ||
211 | "AmbientIlluminance"); | ||
212 | |||
213 | return (status); | ||
214 | } | ||
215 | |||
216 | /****************************************************************************** | ||
217 | * | ||
218 | * FUNCTION: acpi_ns_repair_TSS | ||
219 | * | ||
220 | * PARAMETERS: Data - Pointer to validation data structure | ||
221 | * return_object_ptr - Pointer to the object returned from the | ||
222 | * evaluation of a method or object | ||
223 | * | ||
224 | * RETURN: Status. AE_OK if object is OK or was repaired successfully | ||
225 | * | ||
226 | * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list | ||
227 | * descending by the power dissipation values. | ||
228 | * | ||
229 | *****************************************************************************/ | ||
230 | |||
231 | static acpi_status | ||
232 | acpi_ns_repair_TSS(struct acpi_predefined_data *data, | ||
233 | union acpi_operand_object **return_object_ptr) | ||
234 | { | ||
235 | union acpi_operand_object *return_object = *return_object_ptr; | ||
236 | acpi_status status; | ||
237 | |||
238 | status = acpi_ns_check_sorted_list(data, return_object, 5, 1, | ||
239 | ACPI_SORT_DESCENDING, | ||
240 | "PowerDissipation"); | ||
241 | |||
242 | return (status); | ||
243 | } | ||
244 | |||
245 | /****************************************************************************** | ||
246 | * | ||
247 | * FUNCTION: acpi_ns_repair_PSS | ||
248 | * | ||
249 | * PARAMETERS: Data - Pointer to validation data structure | ||
250 | * return_object_ptr - Pointer to the object returned from the | ||
251 | * evaluation of a method or object | ||
252 | * | ||
253 | * RETURN: Status. AE_OK if object is OK or was repaired successfully | ||
254 | * | ||
255 | * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list | ||
256 | * by the CPU frequencies. Check that the power dissipation values | ||
257 | * are all proportional to CPU frequency (i.e., sorting by | ||
258 | * frequency should be the same as sorting by power.) | ||
259 | * | ||
260 | *****************************************************************************/ | ||
261 | |||
262 | static acpi_status | ||
263 | acpi_ns_repair_PSS(struct acpi_predefined_data *data, | ||
264 | union acpi_operand_object **return_object_ptr) | ||
265 | { | ||
266 | union acpi_operand_object *return_object = *return_object_ptr; | ||
267 | union acpi_operand_object **outer_elements; | ||
268 | u32 outer_element_count; | ||
269 | union acpi_operand_object **elements; | ||
270 | union acpi_operand_object *obj_desc; | ||
271 | u32 previous_value; | ||
272 | acpi_status status; | ||
273 | u32 i; | ||
274 | |||
275 | /* | ||
276 | * Entries (sub-packages) in the _PSS Package must be sorted by power | ||
277 | * dissipation, in descending order. If it appears that the list is | ||
278 | * incorrectly sorted, sort it. We sort by cpu_frequency, since this | ||
279 | * should be proportional to the power. | ||
280 | */ | ||
281 | status = acpi_ns_check_sorted_list(data, return_object, 6, 0, | ||
282 | ACPI_SORT_DESCENDING, | ||
283 | "CpuFrequency"); | ||
284 | if (ACPI_FAILURE(status)) { | ||
285 | return (status); | ||
286 | } | ||
287 | |||
288 | /* | ||
289 | * We now know the list is correctly sorted by CPU frequency. Check if | ||
290 | * the power dissipation values are proportional. | ||
291 | */ | ||
292 | previous_value = ACPI_UINT32_MAX; | ||
293 | outer_elements = return_object->package.elements; | ||
294 | outer_element_count = return_object->package.count; | ||
295 | |||
296 | for (i = 0; i < outer_element_count; i++) { | ||
297 | elements = (*outer_elements)->package.elements; | ||
298 | obj_desc = elements[1]; /* Index1 = power_dissipation */ | ||
299 | |||
300 | if ((u32) obj_desc->integer.value > previous_value) { | ||
301 | ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, | ||
302 | data->node_flags, | ||
303 | "SubPackage[%u,%u] - suspicious power dissipation values", | ||
304 | i - 1, i)); | ||
305 | } | ||
306 | |||
307 | previous_value = (u32) obj_desc->integer.value; | ||
308 | outer_elements++; | ||
309 | } | ||
310 | |||
311 | return (AE_OK); | ||
312 | } | ||
313 | |||
314 | /****************************************************************************** | ||
315 | * | ||
316 | * FUNCTION: acpi_ns_check_sorted_list | ||
317 | * | ||
318 | * PARAMETERS: Data - Pointer to validation data structure | ||
319 | * return_object - Pointer to the top-level returned object | ||
320 | * expected_count - Minimum length of each sub-package | ||
321 | * sort_index - Sub-package entry to sort on | ||
322 | * sort_direction - Ascending or descending | ||
323 | * sort_key_name - Name of the sort_index field | ||
324 | * | ||
325 | * RETURN: Status. AE_OK if the list is valid and is sorted correctly or | ||
326 | * has been repaired by sorting the list. | ||
327 | * | ||
328 | * DESCRIPTION: Check if the package list is valid and sorted correctly by the | ||
329 | * sort_index. If not, then sort the list. | ||
330 | * | ||
331 | *****************************************************************************/ | ||
332 | |||
333 | static acpi_status | ||
334 | acpi_ns_check_sorted_list(struct acpi_predefined_data *data, | ||
335 | union acpi_operand_object *return_object, | ||
336 | u32 expected_count, | ||
337 | u32 sort_index, | ||
338 | u8 sort_direction, char *sort_key_name) | ||
339 | { | ||
340 | u32 outer_element_count; | ||
341 | union acpi_operand_object **outer_elements; | ||
342 | union acpi_operand_object **elements; | ||
343 | union acpi_operand_object *obj_desc; | ||
344 | u32 i; | ||
345 | u32 previous_value; | ||
346 | acpi_status status; | ||
347 | |||
348 | /* The top-level object must be a package */ | ||
349 | |||
350 | if (return_object->common.type != ACPI_TYPE_PACKAGE) { | ||
351 | return (AE_AML_OPERAND_TYPE); | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * Detect any NULL package elements and remove them from the | ||
356 | * package. | ||
357 | * | ||
358 | * TBD: We may want to do this for all predefined names that | ||
359 | * return a variable-length package of packages. | ||
360 | */ | ||
361 | status = acpi_ns_remove_null_elements(return_object); | ||
362 | if (status == AE_NULL_ENTRY) { | ||
363 | ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, | ||
364 | "NULL elements removed from package")); | ||
365 | |||
366 | /* Exit if package is now zero length */ | ||
367 | |||
368 | if (!return_object->package.count) { | ||
369 | return (AE_NULL_ENTRY); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | outer_elements = return_object->package.elements; | ||
374 | outer_element_count = return_object->package.count; | ||
375 | if (!outer_element_count) { | ||
376 | return (AE_AML_PACKAGE_LIMIT); | ||
377 | } | ||
378 | |||
379 | previous_value = 0; | ||
380 | if (sort_direction == ACPI_SORT_DESCENDING) { | ||
381 | previous_value = ACPI_UINT32_MAX; | ||
382 | } | ||
383 | |||
384 | /* Examine each subpackage */ | ||
385 | |||
386 | for (i = 0; i < outer_element_count; i++) { | ||
387 | |||
388 | /* Each element of the top-level package must also be a package */ | ||
389 | |||
390 | if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) { | ||
391 | return (AE_AML_OPERAND_TYPE); | ||
392 | } | ||
393 | |||
394 | /* Each sub-package must have the minimum length */ | ||
395 | |||
396 | if ((*outer_elements)->package.count < expected_count) { | ||
397 | return (AE_AML_PACKAGE_LIMIT); | ||
398 | } | ||
399 | |||
400 | elements = (*outer_elements)->package.elements; | ||
401 | obj_desc = elements[sort_index]; | ||
402 | |||
403 | if (obj_desc->common.type != ACPI_TYPE_INTEGER) { | ||
404 | return (AE_AML_OPERAND_TYPE); | ||
405 | } | ||
406 | |||
407 | /* | ||
408 | * The list must be sorted in the specified order. If we detect a | ||
409 | * discrepancy, issue a warning and sort the entire list | ||
410 | */ | ||
411 | if (((sort_direction == ACPI_SORT_ASCENDING) && | ||
412 | (obj_desc->integer.value < previous_value)) || | ||
413 | ((sort_direction == ACPI_SORT_DESCENDING) && | ||
414 | (obj_desc->integer.value > previous_value))) { | ||
415 | status = | ||
416 | acpi_ns_sort_list(return_object->package.elements, | ||
417 | outer_element_count, sort_index, | ||
418 | sort_direction); | ||
419 | if (ACPI_FAILURE(status)) { | ||
420 | return (status); | ||
421 | } | ||
422 | |||
423 | data->flags |= ACPI_OBJECT_REPAIRED; | ||
424 | |||
425 | ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, | ||
426 | data->node_flags, | ||
427 | "Repaired unsorted list - now sorted by %s", | ||
428 | sort_key_name)); | ||
429 | return (AE_OK); | ||
430 | } | ||
431 | |||
432 | previous_value = (u32) obj_desc->integer.value; | ||
433 | outer_elements++; | ||
434 | } | ||
435 | |||
436 | return (AE_OK); | ||
437 | } | ||
438 | |||
439 | /****************************************************************************** | ||
440 | * | ||
441 | * FUNCTION: acpi_ns_remove_null_elements | ||
442 | * | ||
443 | * PARAMETERS: obj_desc - A Package object | ||
444 | * | ||
445 | * RETURN: Status. AE_NULL_ENTRY means that one or more elements were | ||
446 | * removed. | ||
447 | * | ||
448 | * DESCRIPTION: Remove all NULL package elements and update the package count. | ||
449 | * | ||
450 | *****************************************************************************/ | ||
451 | |||
452 | static acpi_status | ||
453 | acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) | ||
454 | { | ||
455 | union acpi_operand_object **source; | ||
456 | union acpi_operand_object **dest; | ||
457 | acpi_status status = AE_OK; | ||
458 | u32 count; | ||
459 | u32 new_count; | ||
460 | u32 i; | ||
461 | |||
462 | count = obj_desc->package.count; | ||
463 | new_count = count; | ||
464 | |||
465 | source = obj_desc->package.elements; | ||
466 | dest = source; | ||
467 | |||
468 | /* Examine all elements of the package object */ | ||
469 | |||
470 | for (i = 0; i < count; i++) { | ||
471 | if (!*source) { | ||
472 | status = AE_NULL_ENTRY; | ||
473 | new_count--; | ||
474 | } else { | ||
475 | *dest = *source; | ||
476 | dest++; | ||
477 | } | ||
478 | source++; | ||
479 | } | ||
480 | |||
481 | if (status == AE_NULL_ENTRY) { | ||
482 | |||
483 | /* NULL terminate list and update the package count */ | ||
484 | |||
485 | *dest = NULL; | ||
486 | obj_desc->package.count = new_count; | ||
487 | } | ||
488 | |||
489 | return (status); | ||
490 | } | ||
491 | |||
492 | /****************************************************************************** | ||
493 | * | ||
494 | * FUNCTION: acpi_ns_sort_list | ||
495 | * | ||
496 | * PARAMETERS: Elements - Package object element list | ||
497 | * Count - Element count for above | ||
498 | * Index - Sort by which package element | ||
499 | * sort_direction - Ascending or Descending sort | ||
500 | * | ||
501 | * RETURN: Status | ||
502 | * | ||
503 | * DESCRIPTION: Sort the objects that are in a package element list. | ||
504 | * | ||
505 | * NOTE: Assumes that all NULL elements have been removed from the package. | ||
506 | * | ||
507 | *****************************************************************************/ | ||
508 | |||
509 | static acpi_status | ||
510 | acpi_ns_sort_list(union acpi_operand_object **elements, | ||
511 | u32 count, u32 index, u8 sort_direction) | ||
512 | { | ||
513 | union acpi_operand_object *obj_desc1; | ||
514 | union acpi_operand_object *obj_desc2; | ||
515 | union acpi_operand_object *temp_obj; | ||
516 | u32 i; | ||
517 | u32 j; | ||
518 | |||
519 | /* Simple bubble sort */ | ||
520 | |||
521 | for (i = 1; i < count; i++) { | ||
522 | for (j = (count - 1); j >= i; j--) { | ||
523 | obj_desc1 = elements[j - 1]->package.elements[index]; | ||
524 | obj_desc2 = elements[j]->package.elements[index]; | ||
525 | |||
526 | if (((sort_direction == ACPI_SORT_ASCENDING) && | ||
527 | (obj_desc1->integer.value > | ||
528 | obj_desc2->integer.value)) | ||
529 | || ((sort_direction == ACPI_SORT_DESCENDING) | ||
530 | && (obj_desc1->integer.value < | ||
531 | obj_desc2->integer.value))) { | ||
532 | temp_obj = elements[j - 1]; | ||
533 | elements[j - 1] = elements[j]; | ||
534 | elements[j] = temp_obj; | ||
535 | } | ||
536 | } | ||
537 | } | ||
538 | |||
539 | return (AE_OK); | ||
540 | } | ||