aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/namespace/nsinit.c
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2006-04-21 17:15:00 -0400
committerLen Brown <len.brown@intel.com>2006-06-14 02:30:55 -0400
commitb229cf92eee616c7cb5ad8cdb35a19b119f00bc8 (patch)
tree74b52bec6ec029859c2320aba227290a503af31a /drivers/acpi/namespace/nsinit.c
parent793c2388cae3fd023b3b5166354931752d42353c (diff)
ACPI: ACPICA 20060421
Removed a device initialization optimization introduced in 20051216 where the _STA method was not run unless an _INI was also present for the same device. This optimization could cause problems because it could allow _INI methods to be run within a not-present device subtree (If a not-present device had no _INI, _STA would not be run, the not-present status would not be discovered, and the children of the device would be incorrectly traversed.) Implemented a new _STA optimization where namespace subtrees that do not contain _INI are identified and ignored during device initialization. Selectively running _STA can significantly improve boot time on large machines (with assistance from Len Brown.) Implemented support for the device initialization case where the returned _STA flags indicate a device not-present but functioning. In this case, _INI is not run, but the device children are examined for presence, as per the ACPI specification. Implemented an additional change to the IndexField support in order to conform to MS behavior. The value written to the Index Register is not simply a byte offset, it is a byte offset in units of the access width of the parent Index Field. (Fiodor Suietov) Defined and deployed a new OSL interface, acpi_os_validate_address(). This interface is called during the creation of all AML operation regions, and allows the host OS to exert control over what addresses it will allow the AML code to access. Operation Regions whose addresses are disallowed will cause a runtime exception when they are actually accessed (will not affect or abort table loading.) Defined and deployed a new OSL interface, acpi_os_validate_interface(). This interface allows the host OS to match the various "optional" interface/behavior strings for the _OSI predefined control method as appropriate (with assistance from Bjorn Helgaas.) Restructured and corrected various problems in the exception handling code paths within DsCallControlMethod and DsTerminateControlMethod in dsmethod (with assistance from Takayoshi Kochi.) Modified the Linux source converter to ignore quoted string literals while converting identifiers from mixed to lower case. This will correct problems with the disassembler and other areas where such strings must not be modified. The ACPI_FUNCTION_* macros no longer require quotes around the function name. This allows the Linux source converter to convert the names, now that the converter ignores quoted strings. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/namespace/nsinit.c')
-rw-r--r--drivers/acpi/namespace/nsinit.c265
1 files changed, 187 insertions, 78 deletions
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 57b2537643c7..bf1d8dbc0b86 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -58,6 +58,10 @@ static acpi_status
58acpi_ns_init_one_device(acpi_handle obj_handle, 58acpi_ns_init_one_device(acpi_handle obj_handle,
59 u32 nesting_level, void *context, void **return_value); 59 u32 nesting_level, void *context, void **return_value);
60 60
61static acpi_status
62acpi_ns_find_ini_methods(acpi_handle obj_handle,
63 u32 nesting_level, void *context, void **return_value);
64
61/******************************************************************************* 65/*******************************************************************************
62 * 66 *
63 * FUNCTION: acpi_ns_initialize_objects 67 * FUNCTION: acpi_ns_initialize_objects
@@ -76,7 +80,7 @@ acpi_status acpi_ns_initialize_objects(void)
76 acpi_status status; 80 acpi_status status;
77 struct acpi_init_walk_info info; 81 struct acpi_init_walk_info info;
78 82
79 ACPI_FUNCTION_TRACE("ns_initialize_objects"); 83 ACPI_FUNCTION_TRACE(ns_initialize_objects);
80 84
81 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 85 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
82 "**** Starting initialization of namespace objects ****\n")); 86 "**** Starting initialization of namespace objects ****\n"));
@@ -93,7 +97,7 @@ acpi_status acpi_ns_initialize_objects(void)
93 ACPI_UINT32_MAX, acpi_ns_init_one_object, 97 ACPI_UINT32_MAX, acpi_ns_init_one_object,
94 &info, NULL); 98 &info, NULL);
95 if (ACPI_FAILURE(status)) { 99 if (ACPI_FAILURE(status)) {
96 ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); 100 ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
97 } 101 }
98 102
99 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, 103 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
@@ -133,7 +137,7 @@ acpi_status acpi_ns_initialize_devices(void)
133 acpi_status status; 137 acpi_status status;
134 struct acpi_device_walk_info info; 138 struct acpi_device_walk_info info;
135 139
136 ACPI_FUNCTION_TRACE("ns_initialize_devices"); 140 ACPI_FUNCTION_TRACE(ns_initialize_devices);
137 141
138 /* Init counters */ 142 /* Init counters */
139 143
@@ -142,28 +146,29 @@ acpi_status acpi_ns_initialize_devices(void)
142 info.num_INI = 0; 146 info.num_INI = 0;
143 147
144 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, 148 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
145 "Executing all Device _STA and_INI methods:")); 149 "Initializing Device/Processor/Thermal objects by executing _INI methods:"));
150
151 /* Tree analysis: find all subtrees that contain _INI methods */
146 152
147 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 153 status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
154 ACPI_UINT32_MAX, FALSE,
155 acpi_ns_find_ini_methods, &info, NULL);
148 if (ACPI_FAILURE(status)) { 156 if (ACPI_FAILURE(status)) {
149 return_ACPI_STATUS(status); 157 ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
150 } 158 }
151 159
152 /* Walk namespace for all objects */ 160 /* Walk namespace to execute all _INIs on present devices */
153 161
154 status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 162 status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
155 ACPI_UINT32_MAX, TRUE, 163 ACPI_UINT32_MAX, FALSE,
156 acpi_ns_init_one_device, &info, NULL); 164 acpi_ns_init_one_device, &info, NULL);
157
158 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
159
160 if (ACPI_FAILURE(status)) { 165 if (ACPI_FAILURE(status)) {
161 ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace")); 166 ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
162 } 167 }
163 168
164 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, 169 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
165 "\n%hd Devices found - executed %hd _STA, %hd _INI methods\n", 170 "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n",
166 info.device_count, info.num_STA, info.num_INI)); 171 info.num_INI, info.num_STA, info.device_count));
167 172
168 return_ACPI_STATUS(status); 173 return_ACPI_STATUS(status);
169} 174}
@@ -200,7 +205,7 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
200 (struct acpi_namespace_node *)obj_handle; 205 (struct acpi_namespace_node *)obj_handle;
201 union acpi_operand_object *obj_desc; 206 union acpi_operand_object *obj_desc;
202 207
203 ACPI_FUNCTION_NAME("ns_init_one_object"); 208 ACPI_FUNCTION_NAME(ns_init_one_object);
204 209
205 info->object_count++; 210 info->object_count++;
206 211
@@ -311,6 +316,72 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
311 316
312/******************************************************************************* 317/*******************************************************************************
313 * 318 *
319 * FUNCTION: acpi_ns_find_ini_methods
320 *
321 * PARAMETERS: acpi_walk_callback
322 *
323 * RETURN: acpi_status
324 *
325 * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
326 * device/processor/thermal objects, and marks the entire subtree
327 * with a SUBTREE_HAS_INI flag. This flag is used during the
328 * subsequent device initialization walk to avoid entire subtrees
329 * that do not contain an _INI.
330 *
331 ******************************************************************************/
332
333static acpi_status
334acpi_ns_find_ini_methods(acpi_handle obj_handle,
335 u32 nesting_level, void *context, void **return_value)
336{
337 struct acpi_device_walk_info *info =
338 ACPI_CAST_PTR(struct acpi_device_walk_info, context);
339 struct acpi_namespace_node *node;
340 struct acpi_namespace_node *parent_node;
341
342 /* Keep count of device/processor/thermal objects */
343
344 node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
345 if ((node->type == ACPI_TYPE_DEVICE) ||
346 (node->type == ACPI_TYPE_PROCESSOR) ||
347 (node->type == ACPI_TYPE_THERMAL)) {
348 info->device_count++;
349 return (AE_OK);
350 }
351
352 /* We are only looking for methods named _INI */
353
354 if (!ACPI_COMPARE_NAME(node->name.ascii, METHOD_NAME__INI)) {
355 return (AE_OK);
356 }
357
358 /*
359 * The only _INI methods that we care about are those that are
360 * present under Device, Processor, and Thermal objects.
361 */
362 parent_node = acpi_ns_get_parent_node(node);
363 switch (parent_node->type) {
364 case ACPI_TYPE_DEVICE:
365 case ACPI_TYPE_PROCESSOR:
366 case ACPI_TYPE_THERMAL:
367
368 /* Mark parent and bubble up the INI present flag to the root */
369
370 while (parent_node) {
371 parent_node->flags |= ANOBJ_SUBTREE_HAS_INI;
372 parent_node = acpi_ns_get_parent_node(parent_node);
373 }
374 break;
375
376 default:
377 break;
378 }
379
380 return (AE_OK);
381}
382
383/*******************************************************************************
384 *
314 * FUNCTION: acpi_ns_init_one_device 385 * FUNCTION: acpi_ns_init_one_device
315 * 386 *
316 * PARAMETERS: acpi_walk_callback 387 * PARAMETERS: acpi_walk_callback
@@ -328,64 +399,49 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
328 u32 nesting_level, void *context, void **return_value) 399 u32 nesting_level, void *context, void **return_value)
329{ 400{
330 struct acpi_device_walk_info *info = 401 struct acpi_device_walk_info *info =
331 (struct acpi_device_walk_info *)context; 402 ACPI_CAST_PTR(struct acpi_device_walk_info, context);
332 struct acpi_parameter_info pinfo; 403 struct acpi_parameter_info pinfo;
333 u32 flags; 404 u32 flags;
334 acpi_status status; 405 acpi_status status;
335 struct acpi_namespace_node *ini_node;
336 struct acpi_namespace_node *device_node; 406 struct acpi_namespace_node *device_node;
337 407
338 ACPI_FUNCTION_TRACE("ns_init_one_device"); 408 ACPI_FUNCTION_TRACE(ns_init_one_device);
339 409
340 device_node = acpi_ns_map_handle_to_node(obj_handle); 410 /* We are interested in Devices, Processors and thermal_zones only */
341 if (!device_node) {
342 return_ACPI_STATUS(AE_BAD_PARAMETER);
343 }
344 411
345 /* 412 device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
346 * We will run _STA/_INI on Devices, Processors and thermal_zones only
347 */
348 if ((device_node->type != ACPI_TYPE_DEVICE) && 413 if ((device_node->type != ACPI_TYPE_DEVICE) &&
349 (device_node->type != ACPI_TYPE_PROCESSOR) && 414 (device_node->type != ACPI_TYPE_PROCESSOR) &&
350 (device_node->type != ACPI_TYPE_THERMAL)) { 415 (device_node->type != ACPI_TYPE_THERMAL)) {
351 return_ACPI_STATUS(AE_OK); 416 return_ACPI_STATUS(AE_OK);
352 } 417 }
353 418
354 if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
355 (!(acpi_dbg_level & ACPI_LV_INFO))) {
356 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
357 }
358
359 info->device_count++;
360
361 /* 419 /*
362 * Check if the _INI method exists for this device - 420 * Because of an earlier namespace analysis, all subtrees that contain an
363 * if _INI does not exist, there is no need to run _STA 421 * _INI method are tagged.
364 * No _INI means device requires no initialization 422 *
423 * If this device subtree does not contain any _INI methods, we
424 * can exit now and stop traversing this entire subtree.
365 */ 425 */
366 status = acpi_ns_search_node(*ACPI_CAST_PTR(u32, METHOD_NAME__INI), 426 if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) {
367 device_node, ACPI_TYPE_METHOD, &ini_node); 427 return_ACPI_STATUS(AE_CTRL_DEPTH);
368 if (ACPI_FAILURE(status)) {
369
370 /* No _INI method found - move on to next device */
371
372 return_ACPI_STATUS(AE_OK);
373 } 428 }
374 429
375 /* 430 /*
376 * Run _STA to determine if we can run _INI on the device - 431 * Run _STA to determine if this device is present and functioning. We
377 * the device must be present before _INI can be run. 432 * must know this information for two important reasons (from ACPI spec):
378 * However, _STA is not required - assume device present if no _STA 433 *
434 * 1) We can only run _INI if the device is present.
435 * 2) We must abort the device tree walk on this subtree if the device is
436 * not present and is not functional (we will not examine the children)
437 *
438 * The _STA method is not required to be present under the device, we
439 * assume the device is present if _STA does not exist.
379 */ 440 */
380 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD, 441 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
381 device_node, 442 (ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA));
382 METHOD_NAME__STA));
383 443
384 pinfo.node = device_node; 444 status = acpi_ut_execute_STA(device_node, &flags);
385 pinfo.parameters = NULL;
386 pinfo.parameter_type = ACPI_PARAM_ARGS;
387
388 status = acpi_ut_execute_STA(pinfo.node, &flags);
389 if (ACPI_FAILURE(status)) { 445 if (ACPI_FAILURE(status)) {
390 446
391 /* Ignore error and move on to next device */ 447 /* Ignore error and move on to next device */
@@ -393,55 +449,108 @@ acpi_ns_init_one_device(acpi_handle obj_handle,
393 return_ACPI_STATUS(AE_OK); 449 return_ACPI_STATUS(AE_OK);
394 } 450 }
395 451
452 /*
453 * Flags == -1 means that _STA was not found. In this case, we assume that
454 * the device is both present and functional.
455 *
456 * From the ACPI spec, description of _STA:
457 *
458 * "If a device object (including the processor object) does not have an
459 * _STA object, then OSPM assumes that all of the above bits are set (in
460 * other words, the device is present, ..., and functioning)"
461 */
396 if (flags != ACPI_UINT32_MAX) { 462 if (flags != ACPI_UINT32_MAX) {
397 info->num_STA++; 463 info->num_STA++;
398 } 464 }
399 465
466 /*
467 * Examine the PRESENT and FUNCTIONING status bits
468 *
469 * Note: ACPI spec does not seem to specify behavior for the present but
470 * not functioning case, so we assume functioning if present.
471 */
400 if (!(flags & ACPI_STA_DEVICE_PRESENT)) { 472 if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
401 473
402 /* Don't look at children of a not present device */ 474 /* Device is not present, we must examine the Functioning bit */
403 475
404 return_ACPI_STATUS(AE_CTRL_DEPTH); 476 if (flags & ACPI_STA_DEVICE_FUNCTIONING) {
477 /*
478 * Device is not present but is "functioning". In this case,
479 * we will not run _INI, but we continue to examine the children
480 * of this device.
481 *
482 * From the ACPI spec, description of _STA: (Note - no mention
483 * of whether to run _INI or not on the device in question)
484 *
485 * "_STA may return bit 0 clear (not present) with bit 3 set
486 * (device is functional). This case is used to indicate a valid
487 * device for which no device driver should be loaded (for example,
488 * a bridge device.) Children of this device may be present and
489 * valid. OSPM should continue enumeration below a device whose
490 * _STA returns this bit combination"
491 */
492 return_ACPI_STATUS(AE_OK);
493 } else {
494 /*
495 * Device is not present and is not functioning. We must abort the
496 * walk of this subtree immediately -- don't look at the children
497 * of such a device.
498 *
499 * From the ACPI spec, description of _INI:
500 *
501 * "If the _STA method indicates that the device is not present,
502 * OSPM will not run the _INI and will not examine the children
503 * of the device for _INI methods"
504 */
505 return_ACPI_STATUS(AE_CTRL_DEPTH);
506 }
405 } 507 }
406 508
407 /* 509 /*
408 * The device is present and _INI exists. Run the _INI method. 510 * The device is present or is assumed present if no _STA exists.
409 * (We already have the _INI node from above) 511 * Run the _INI if it exists (not required to exist)
512 *
513 * Note: We know there is an _INI within this subtree, but it may not be
514 * under this particular device, it may be lower in the branch.
410 */ 515 */
411 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD, 516 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
412 pinfo.node, 517 (ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI));
413 METHOD_NAME__INI));
414 518
415 pinfo.node = ini_node; 519 pinfo.node = device_node;
416 status = acpi_ns_evaluate_by_handle(&pinfo); 520 pinfo.parameters = NULL;
417 if (ACPI_FAILURE(status)) { 521 pinfo.parameter_type = ACPI_PARAM_ARGS;
418
419 /* Ignore error and move on to next device */
420
421#ifdef ACPI_DEBUG_OUTPUT
422 char *scope_name = acpi_ns_get_external_pathname(ini_node);
423 522
424 ACPI_WARNING((AE_INFO, "%s._INI failed: %s", 523 status = acpi_ns_evaluate_relative(METHOD_NAME__INI, &pinfo);
425 scope_name, acpi_format_exception(status))); 524 if (ACPI_SUCCESS(status)) {
426 525
427 ACPI_FREE(scope_name);
428#endif
429 } else {
430 /* Delete any return object (especially if implicit_return is enabled) */ 526 /* Delete any return object (especially if implicit_return is enabled) */
431 527
432 if (pinfo.return_object) { 528 if (pinfo.return_object) {
433 acpi_ut_remove_reference(pinfo.return_object); 529 acpi_ut_remove_reference(pinfo.return_object);
434 } 530 }
435 531
436 /* Count of successful INIs */
437
438 info->num_INI++; 532 info->num_INI++;
533 if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
534 (!(acpi_dbg_level & ACPI_LV_INFO))) {
535 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
536 }
439 } 537 }
538#ifdef ACPI_DEBUG_OUTPUT
539 else if (status != AE_NOT_FOUND) {
440 540
441 if (acpi_gbl_init_handler) { 541 /* Ignore error and move on to next device */
542
543 char *scope_name = acpi_ns_get_external_pathname(pinfo.node);
442 544
443 /* External initialization handler is present, call it */ 545 ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution",
546 scope_name));
547 ACPI_FREE(scope_name);
548 }
549#endif
444 550
551 /* If an external initialization handler is present, call it */
552
553 if (acpi_gbl_init_handler) {
445 status = 554 status =
446 acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI); 555 acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI);
447 } 556 }