diff options
Diffstat (limited to 'drivers/acpi/dispatcher/dsobject.c')
| -rw-r--r-- | drivers/acpi/dispatcher/dsobject.c | 91 |
1 files changed, 85 insertions, 6 deletions
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index a474ca2334d5..954ac8ce958a 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c | |||
| @@ -137,6 +137,71 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
| 137 | return_ACPI_STATUS(status); | 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 | /* Create and init a new internal ACPI object */ | 207 | /* Create and init a new internal ACPI object */ |
| @@ -156,6 +221,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
| 156 | return_ACPI_STATUS(status); | 221 | return_ACPI_STATUS(status); |
| 157 | } | 222 | } |
| 158 | 223 | ||
| 224 | exit: | ||
| 159 | *obj_desc_ptr = obj_desc; | 225 | *obj_desc_ptr = obj_desc; |
| 160 | return_ACPI_STATUS(AE_OK); | 226 | return_ACPI_STATUS(AE_OK); |
| 161 | } | 227 | } |
| @@ -356,12 +422,25 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
| 356 | arg = arg->common.next; | 422 | arg = arg->common.next; |
| 357 | for (i = 0; arg && (i < element_count); i++) { | 423 | for (i = 0; arg && (i < element_count); i++) { |
| 358 | if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { | 424 | if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { |
| 359 | 425 | if (arg->common.node->type == ACPI_TYPE_METHOD) { | |
| 360 | /* This package element is already built, just get it */ | 426 | /* |
| 361 | 427 | * A method reference "looks" to the parser to be a method | |
| 362 | obj_desc->package.elements[i] = | 428 | * invocation, so we special case it here |
| 363 | ACPI_CAST_PTR(union acpi_operand_object, | 429 | */ |
| 364 | arg->common.node); | 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 */ | ||
| 439 | |||
| 440 | obj_desc->package.elements[i] = | ||
| 441 | ACPI_CAST_PTR(union acpi_operand_object, | ||
| 442 | arg->common.node); | ||
| 443 | } | ||
| 365 | } else { | 444 | } else { |
| 366 | status = acpi_ds_build_internal_object(walk_state, arg, | 445 | status = acpi_ds_build_internal_object(walk_state, arg, |
| 367 | &obj_desc-> | 446 | &obj_desc-> |
