Commit 152c300d007c70c4a1847dad39ecdaba22e7d457

Authored by Bob Moore
Committed by Len Brown
1 parent 92d499d991

ACPICA: fix acpi-cpufreq boot crash due to _PSD return-by-reference

Changed resolution of named references in packages

Fixed a problem with the Package operator where all named
references were created as object references and left otherwise
unresolved. According to the ACPI specification, a Package can
only contain Data Objects or references to control methods. The
implication is that named references to Data Objects (Integer,
Buffer, String, Package, BufferField, Field) should be resolved
immediately upon package creation. This is the approach taken
with this change. References to all other named objects (Methods,
Devices, Scopes, etc.) are all now properly created as reference objects.

http://bugzilla.kernel.org/show_bug.cgi?id=5328
http://bugzilla.kernel.org/show_bug.cgi?id=9429

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>

Showing 1 changed file with 85 additions and 6 deletions Side-by-side Diff

drivers/acpi/dispatcher/dsobject.c
... ... @@ -137,6 +137,71 @@
137 137 return_ACPI_STATUS(status);
138 138 }
139 139 }
  140 +
  141 + /* Special object resolution for elements of a package */
  142 +
  143 + if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
  144 + (op->common.parent->common.aml_opcode ==
  145 + AML_VAR_PACKAGE_OP)) {
  146 + /*
  147 + * Attempt to resolve the node to a value before we insert it into
  148 + * the package. If this is a reference to a common data type,
  149 + * resolve it immediately. According to the ACPI spec, package
  150 + * elements can only be "data objects" or method references.
  151 + * Attempt to resolve to an Integer, Buffer, String or Package.
  152 + * If cannot, return the named reference (for things like Devices,
  153 + * Methods, etc.) Buffer Fields and Fields will resolve to simple
  154 + * objects (int/buf/str/pkg).
  155 + *
  156 + * NOTE: References to things like Devices, Methods, Mutexes, etc.
  157 + * will remain as named references. This behavior is not described
  158 + * in the ACPI spec, but it appears to be an oversight.
  159 + */
  160 + obj_desc = (union acpi_operand_object *)op->common.node;
  161 +
  162 + status =
  163 + acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
  164 + (struct
  165 + acpi_namespace_node,
  166 + &obj_desc),
  167 + walk_state);
  168 + if (ACPI_FAILURE(status)) {
  169 + return_ACPI_STATUS(status);
  170 + }
  171 +
  172 + switch (op->common.node->type) {
  173 + /*
  174 + * For these types, we need the actual node, not the subobject.
  175 + * However, the subobject got an extra reference count above.
  176 + */
  177 + case ACPI_TYPE_MUTEX:
  178 + case ACPI_TYPE_METHOD:
  179 + case ACPI_TYPE_POWER:
  180 + case ACPI_TYPE_PROCESSOR:
  181 + case ACPI_TYPE_EVENT:
  182 + case ACPI_TYPE_REGION:
  183 + case ACPI_TYPE_DEVICE:
  184 + case ACPI_TYPE_THERMAL:
  185 +
  186 + obj_desc =
  187 + (union acpi_operand_object *)op->common.
  188 + node;
  189 + break;
  190 +
  191 + default:
  192 + break;
  193 + }
  194 +
  195 + /*
  196 + * If above resolved to an operand object, we are done. Otherwise,
  197 + * we have a NS node, we must create the package entry as a named
  198 + * reference.
  199 + */
  200 + if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) !=
  201 + ACPI_DESC_TYPE_NAMED) {
  202 + goto exit;
  203 + }
  204 + }
140 205 }
141 206  
142 207 /* Create and init a new internal ACPI object */
... ... @@ -156,6 +221,7 @@
156 221 return_ACPI_STATUS(status);
157 222 }
158 223  
  224 + exit:
159 225 *obj_desc_ptr = obj_desc;
160 226 return_ACPI_STATUS(AE_OK);
161 227 }
162 228  
... ... @@ -356,12 +422,25 @@
356 422 arg = arg->common.next;
357 423 for (i = 0; arg && (i < element_count); i++) {
358 424 if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
  425 + if (arg->common.node->type == ACPI_TYPE_METHOD) {
  426 + /*
  427 + * A method reference "looks" to the parser to be a method
  428 + * invocation, so we special case it here
  429 + */
  430 + arg->common.aml_opcode = AML_INT_NAMEPATH_OP;
  431 + status =
  432 + acpi_ds_build_internal_object(walk_state,
  433 + arg,
  434 + &obj_desc->
  435 + package.
  436 + elements[i]);
  437 + } else {
  438 + /* This package element is already built, just get it */
359 439  
360   - /* This package element is already built, just get it */
361   -
362   - obj_desc->package.elements[i] =
363   - ACPI_CAST_PTR(union acpi_operand_object,
364   - arg->common.node);
  440 + obj_desc->package.elements[i] =
  441 + ACPI_CAST_PTR(union acpi_operand_object,
  442 + arg->common.node);
  443 + }
365 444 } else {
366 445 status = acpi_ds_build_internal_object(walk_state, arg,
367 446 &obj_desc->