diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 14:52:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 14:52:52 -0400 |
commit | 08acd4f8af42affd8cbed81cc1b69fa12ddb213f (patch) | |
tree | 988d15db6233b20db6a500cd5f590c6d2041462d /drivers/acpi/dispatcher/dsfield.c | |
parent | ccf2779544eecfcc5447e2028d1029b6d4ff7bb6 (diff) | |
parent | 008238b54ac2350babf195084ecedbcf7851a202 (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (179 commits)
ACPI: Fix acpi_processor_idle and idle= boot parameters interaction
acpi: fix section mismatch warning in pnpacpi
intel_menlo: fix build warning
ACPI: Cleanup: Remove unneeded, multiple local dummy variables
ACPI: video - fix permissions on some proc entries
ACPI: video - properly handle errors when registering proc elements
ACPI: video - do not store invalid entries in attached_array list
ACPI: re-name acpi_pm_ops to acpi_suspend_ops
ACER_WMI/ASUS_LAPTOP: fix build bug
thinkpad_acpi: fix possible NULL pointer dereference if kstrdup failed
ACPI: check a return value correctly in acpi_power_get_context()
#if 0 acpi/bay.c:eject_removable_drive()
eeepc-laptop: add hwmon fan control
eeepc-laptop: add backlight
eeepc-laptop: add base driver
ACPI: thinkpad-acpi: bump up version to 0.20
ACPI: thinkpad-acpi: fix selects in Kconfig
ACPI: thinkpad-acpi: use a private workqueue
ACPI: thinkpad-acpi: fluff really minor fix
ACPI: thinkpad-acpi: use uppercase for "LED" on user documentation
...
Fixed conflicts in drivers/acpi/video.c and drivers/misc/intel_menlow.c
manually.
Diffstat (limited to 'drivers/acpi/dispatcher/dsfield.c')
-rw-r--r-- | drivers/acpi/dispatcher/dsfield.c | 173 |
1 files changed, 100 insertions, 73 deletions
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index f049639bac35..c78078315be9 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, | |||
89 | 89 | ||
90 | ACPI_FUNCTION_TRACE(ds_create_buffer_field); | 90 | ACPI_FUNCTION_TRACE(ds_create_buffer_field); |
91 | 91 | ||
92 | /* Get the name_string argument */ | 92 | /* |
93 | 93 | * Get the name_string argument (name of the new buffer_field) | |
94 | */ | ||
94 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { | 95 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { |
96 | |||
97 | /* For create_field, name is the 4th argument */ | ||
98 | |||
95 | arg = acpi_ps_get_arg(op, 3); | 99 | arg = acpi_ps_get_arg(op, 3); |
96 | } else { | 100 | } else { |
97 | /* Create Bit/Byte/Word/Dword field */ | 101 | /* For all other create_xXXField operators, name is the 3rd argument */ |
98 | 102 | ||
99 | arg = acpi_ps_get_arg(op, 2); | 103 | arg = acpi_ps_get_arg(op, 2); |
100 | } | 104 | } |
@@ -107,26 +111,30 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, | |||
107 | node = walk_state->deferred_node; | 111 | node = walk_state->deferred_node; |
108 | status = AE_OK; | 112 | status = AE_OK; |
109 | } else { | 113 | } else { |
110 | /* | 114 | /* Execute flag should always be set when this function is entered */ |
111 | * During the load phase, we want to enter the name of the field into | 115 | |
112 | * the namespace. During the execute phase (when we evaluate the size | 116 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { |
113 | * operand), we want to lookup the name | 117 | return_ACPI_STATUS(AE_AML_INTERNAL); |
114 | */ | ||
115 | if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) { | ||
116 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE; | ||
117 | } else { | ||
118 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | ||
119 | ACPI_NS_ERROR_IF_FOUND; | ||
120 | } | 118 | } |
121 | 119 | ||
122 | /* | 120 | /* Creating new namespace node, should not already exist */ |
123 | * Enter the name_string into the namespace | 121 | |
124 | */ | 122 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | |
123 | ACPI_NS_ERROR_IF_FOUND; | ||
124 | |||
125 | /* Mark node temporary if we are executing a method */ | ||
126 | |||
127 | if (walk_state->method_node) { | ||
128 | flags |= ACPI_NS_TEMPORARY; | ||
129 | } | ||
130 | |||
131 | /* Enter the name_string into the namespace */ | ||
132 | |||
125 | status = | 133 | status = |
126 | acpi_ns_lookup(walk_state->scope_info, | 134 | acpi_ns_lookup(walk_state->scope_info, |
127 | arg->common.value.string, ACPI_TYPE_ANY, | 135 | arg->common.value.string, ACPI_TYPE_ANY, |
128 | ACPI_IMODE_LOAD_PASS1, flags, walk_state, | 136 | ACPI_IMODE_LOAD_PASS1, flags, walk_state, |
129 | &(node)); | 137 | &node); |
130 | if (ACPI_FAILURE(status)) { | 138 | if (ACPI_FAILURE(status)) { |
131 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | 139 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); |
132 | return_ACPI_STATUS(status); | 140 | return_ACPI_STATUS(status); |
@@ -136,13 +144,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, | |||
136 | /* | 144 | /* |
137 | * We could put the returned object (Node) on the object stack for later, | 145 | * We could put the returned object (Node) on the object stack for later, |
138 | * but for now, we will put it in the "op" object that the parser uses, | 146 | * but for now, we will put it in the "op" object that the parser uses, |
139 | * so we can get it again at the end of this scope | 147 | * so we can get it again at the end of this scope. |
140 | */ | 148 | */ |
141 | op->common.node = node; | 149 | op->common.node = node; |
142 | 150 | ||
143 | /* | 151 | /* |
144 | * If there is no object attached to the node, this node was just created | 152 | * If there is no object attached to the node, this node was just created |
145 | * and we need to create the field object. Otherwise, this was a lookup | 153 | * and we need to create the field object. Otherwise, this was a lookup |
146 | * of an existing node and we don't want to create the field object again. | 154 | * of an existing node and we don't want to create the field object again. |
147 | */ | 155 | */ |
148 | obj_desc = acpi_ns_get_attached_object(node); | 156 | obj_desc = acpi_ns_get_attached_object(node); |
@@ -164,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, | |||
164 | } | 172 | } |
165 | 173 | ||
166 | /* | 174 | /* |
167 | * Remember location in AML stream of the field unit | 175 | * Remember location in AML stream of the field unit opcode and operands -- |
168 | * opcode and operands -- since the buffer and index | 176 | * since the buffer and index operands must be evaluated. |
169 | * operands must be evaluated. | ||
170 | */ | 177 | */ |
171 | second_desc = obj_desc->common.next_object; | 178 | second_desc = obj_desc->common.next_object; |
172 | second_desc->extra.aml_start = op->named.data; | 179 | second_desc->extra.aml_start = op->named.data; |
@@ -261,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, | |||
261 | 268 | ||
262 | case AML_INT_NAMEDFIELD_OP: | 269 | case AML_INT_NAMEDFIELD_OP: |
263 | 270 | ||
264 | /* Lookup the name */ | 271 | /* Lookup the name, it should already exist */ |
265 | 272 | ||
266 | status = acpi_ns_lookup(walk_state->scope_info, | 273 | status = acpi_ns_lookup(walk_state->scope_info, |
267 | (char *)&arg->named.name, | 274 | (char *)&arg->named.name, |
@@ -272,20 +279,23 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, | |||
272 | if (ACPI_FAILURE(status)) { | 279 | if (ACPI_FAILURE(status)) { |
273 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | 280 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, |
274 | status); | 281 | status); |
275 | if (status != AE_ALREADY_EXISTS) { | 282 | return_ACPI_STATUS(status); |
276 | return_ACPI_STATUS(status); | ||
277 | } | ||
278 | |||
279 | /* Already exists, ignore error */ | ||
280 | } else { | 283 | } else { |
281 | arg->common.node = info->field_node; | 284 | arg->common.node = info->field_node; |
282 | info->field_bit_length = arg->common.value.size; | 285 | info->field_bit_length = arg->common.value.size; |
283 | 286 | ||
284 | /* Create and initialize an object for the new Field Node */ | 287 | /* |
285 | 288 | * If there is no object attached to the node, this node was | |
286 | status = acpi_ex_prep_field_value(info); | 289 | * just created and we need to create the field object. |
287 | if (ACPI_FAILURE(status)) { | 290 | * Otherwise, this was a lookup of an existing node and we |
288 | return_ACPI_STATUS(status); | 291 | * don't want to create the field object again. |
292 | */ | ||
293 | if (!acpi_ns_get_attached_object | ||
294 | (info->field_node)) { | ||
295 | status = acpi_ex_prep_field_value(info); | ||
296 | if (ACPI_FAILURE(status)) { | ||
297 | return_ACPI_STATUS(status); | ||
298 | } | ||
289 | } | 299 | } |
290 | } | 300 | } |
291 | 301 | ||
@@ -399,9 +409,27 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
399 | union acpi_parse_object *arg = NULL; | 409 | union acpi_parse_object *arg = NULL; |
400 | struct acpi_namespace_node *node; | 410 | struct acpi_namespace_node *node; |
401 | u8 type = 0; | 411 | u8 type = 0; |
412 | u32 flags; | ||
402 | 413 | ||
403 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); | 414 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); |
404 | 415 | ||
416 | /* Execute flag should always be set when this function is entered */ | ||
417 | |||
418 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { | ||
419 | if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { | ||
420 | |||
421 | /* bank_field Op is deferred, just return OK */ | ||
422 | |||
423 | return_ACPI_STATUS(AE_OK); | ||
424 | } | ||
425 | |||
426 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * Get the field_list argument for this opcode. This is the start of the | ||
431 | * list of field elements. | ||
432 | */ | ||
405 | switch (walk_state->opcode) { | 433 | switch (walk_state->opcode) { |
406 | case AML_FIELD_OP: | 434 | case AML_FIELD_OP: |
407 | arg = acpi_ps_get_arg(op, 2); | 435 | arg = acpi_ps_get_arg(op, 2); |
@@ -422,20 +450,33 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
422 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 450 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
423 | } | 451 | } |
424 | 452 | ||
453 | if (!arg) { | ||
454 | return_ACPI_STATUS(AE_AML_NO_OPERAND); | ||
455 | } | ||
456 | |||
457 | /* Creating new namespace node(s), should not already exist */ | ||
458 | |||
459 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | ||
460 | ACPI_NS_ERROR_IF_FOUND; | ||
461 | |||
462 | /* Mark node(s) temporary if we are executing a method */ | ||
463 | |||
464 | if (walk_state->method_node) { | ||
465 | flags |= ACPI_NS_TEMPORARY; | ||
466 | } | ||
467 | |||
425 | /* | 468 | /* |
426 | * Walk the list of entries in the field_list | 469 | * Walk the list of entries in the field_list |
427 | */ | 470 | */ |
428 | while (arg) { | 471 | while (arg) { |
429 | 472 | /* | |
430 | /* Ignore OFFSET and ACCESSAS terms here */ | 473 | * Ignore OFFSET and ACCESSAS terms here; we are only interested in the |
431 | 474 | * field names in order to enter them into the namespace. | |
475 | */ | ||
432 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | 476 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { |
433 | status = acpi_ns_lookup(walk_state->scope_info, | 477 | status = acpi_ns_lookup(walk_state->scope_info, |
434 | (char *)&arg->named.name, | 478 | (char *)&arg->named.name, type, |
435 | type, ACPI_IMODE_LOAD_PASS1, | 479 | ACPI_IMODE_LOAD_PASS1, flags, |
436 | ACPI_NS_NO_UPSEARCH | | ||
437 | ACPI_NS_DONT_OPEN_SCOPE | | ||
438 | ACPI_NS_ERROR_IF_FOUND, | ||
439 | walk_state, &node); | 480 | walk_state, &node); |
440 | if (ACPI_FAILURE(status)) { | 481 | if (ACPI_FAILURE(status)) { |
441 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | 482 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, |
@@ -452,7 +493,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
452 | arg->common.node = node; | 493 | arg->common.node = node; |
453 | } | 494 | } |
454 | 495 | ||
455 | /* Move to next field in the list */ | 496 | /* Get the next field element in the list */ |
456 | 497 | ||
457 | arg = arg->common.next; | 498 | arg = arg->common.next; |
458 | } | 499 | } |
@@ -466,7 +507,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
466 | * | 507 | * |
467 | * PARAMETERS: Op - Op containing the Field definition and args | 508 | * PARAMETERS: Op - Op containing the Field definition and args |
468 | * region_node - Object for the containing Operation Region | 509 | * region_node - Object for the containing Operation Region |
469 | * ` walk_state - Current method state | 510 | * walk_state - Current method state |
470 | * | 511 | * |
471 | * RETURN: Status | 512 | * RETURN: Status |
472 | * | 513 | * |
@@ -513,36 +554,13 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, | |||
513 | return_ACPI_STATUS(status); | 554 | return_ACPI_STATUS(status); |
514 | } | 555 | } |
515 | 556 | ||
516 | /* Third arg is the bank_value */ | 557 | /* |
517 | 558 | * Third arg is the bank_value | |
518 | /* TBD: This arg is a term_arg, not a constant, and must be evaluated */ | 559 | * This arg is a term_arg, not a constant |
519 | 560 | * It will be evaluated later, by acpi_ds_eval_bank_field_operands | |
561 | */ | ||
520 | arg = arg->common.next; | 562 | arg = arg->common.next; |
521 | 563 | ||
522 | /* Currently, only the following constants are supported */ | ||
523 | |||
524 | switch (arg->common.aml_opcode) { | ||
525 | case AML_ZERO_OP: | ||
526 | info.bank_value = 0; | ||
527 | break; | ||
528 | |||
529 | case AML_ONE_OP: | ||
530 | info.bank_value = 1; | ||
531 | break; | ||
532 | |||
533 | case AML_BYTE_OP: | ||
534 | case AML_WORD_OP: | ||
535 | case AML_DWORD_OP: | ||
536 | case AML_QWORD_OP: | ||
537 | info.bank_value = (u32) arg->common.value.integer; | ||
538 | break; | ||
539 | |||
540 | default: | ||
541 | info.bank_value = 0; | ||
542 | ACPI_ERROR((AE_INFO, | ||
543 | "Non-constant BankValue for BankField is not implemented")); | ||
544 | } | ||
545 | |||
546 | /* Fourth arg is the field flags */ | 564 | /* Fourth arg is the field flags */ |
547 | 565 | ||
548 | arg = arg->common.next; | 566 | arg = arg->common.next; |
@@ -553,8 +571,17 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, | |||
553 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; | 571 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; |
554 | info.region_node = region_node; | 572 | info.region_node = region_node; |
555 | 573 | ||
556 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | 574 | /* |
575 | * Use Info.data_register_node to store bank_field Op | ||
576 | * It's safe because data_register_node will never be used when create bank field | ||
577 | * We store aml_start and aml_length in the bank_field Op for late evaluation | ||
578 | * Used in acpi_ex_prep_field_value(Info) | ||
579 | * | ||
580 | * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? | ||
581 | */ | ||
582 | info.data_register_node = (struct acpi_namespace_node *)op; | ||
557 | 583 | ||
584 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | ||
558 | return_ACPI_STATUS(status); | 585 | return_ACPI_STATUS(status); |
559 | } | 586 | } |
560 | 587 | ||