linux/drivers/acpi/acpica/psxface.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: psxface - Parser external interfaces
   5 *
   6 * Copyright (C) 2000 - 2018, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "acparser.h"
  13#include "acdispat.h"
  14#include "acinterp.h"
  15#include "actables.h"
  16#include "acnamesp.h"
  17
  18#define _COMPONENT          ACPI_PARSER
  19ACPI_MODULE_NAME("psxface")
  20
  21/* Local Prototypes */
  22static void
  23acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
  24
  25/*******************************************************************************
  26 *
  27 * FUNCTION:    acpi_debug_trace
  28 *
  29 * PARAMETERS:  method_name     - Valid ACPI name string
  30 *              debug_level     - Optional level mask. 0 to use default
  31 *              debug_layer     - Optional layer mask. 0 to use default
  32 *              flags           - bit 1: one shot(1) or persistent(0)
  33 *
  34 * RETURN:      Status
  35 *
  36 * DESCRIPTION: External interface to enable debug tracing during control
  37 *              method execution
  38 *
  39 ******************************************************************************/
  40
  41acpi_status
  42acpi_debug_trace(const char *name, u32 debug_level, u32 debug_layer, u32 flags)
  43{
  44        acpi_status status;
  45
  46        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  47        if (ACPI_FAILURE(status)) {
  48                return (status);
  49        }
  50
  51        acpi_gbl_trace_method_name = name;
  52        acpi_gbl_trace_flags = flags;
  53        acpi_gbl_trace_dbg_level = debug_level;
  54        acpi_gbl_trace_dbg_layer = debug_layer;
  55        status = AE_OK;
  56
  57        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  58        return (status);
  59}
  60
  61/*******************************************************************************
  62 *
  63 * FUNCTION:    acpi_ps_execute_method
  64 *
  65 * PARAMETERS:  info            - Method info block, contains:
  66 *                  node            - Method Node to execute
  67 *                  obj_desc        - Method object
  68 *                  parameters      - List of parameters to pass to the method,
  69 *                                    terminated by NULL. Params itself may be
  70 *                                    NULL if no parameters are being passed.
  71 *                  return_object   - Where to put method's return value (if
  72 *                                    any). If NULL, no value is returned.
  73 *                  parameter_type  - Type of Parameter list
  74 *                  return_object   - Where to put method's return value (if
  75 *                                    any). If NULL, no value is returned.
  76 *                  pass_number     - Parse or execute pass
  77 *
  78 * RETURN:      Status
  79 *
  80 * DESCRIPTION: Execute a control method
  81 *
  82 ******************************************************************************/
  83
  84acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
  85{
  86        acpi_status status;
  87        union acpi_parse_object *op;
  88        struct acpi_walk_state *walk_state;
  89
  90        ACPI_FUNCTION_TRACE(ps_execute_method);
  91
  92        /* Quick validation of DSDT header */
  93
  94        acpi_tb_check_dsdt_header();
  95
  96        /* Validate the Info and method Node */
  97
  98        if (!info || !info->node) {
  99                return_ACPI_STATUS(AE_NULL_ENTRY);
 100        }
 101
 102        /* Init for new method, wait on concurrency semaphore */
 103
 104        status =
 105            acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL);
 106        if (ACPI_FAILURE(status)) {
 107                return_ACPI_STATUS(status);
 108        }
 109
 110        /*
 111         * The caller "owns" the parameters, so give each one an extra reference
 112         */
 113        acpi_ps_update_parameter_list(info, REF_INCREMENT);
 114
 115        /*
 116         * Execute the method. Performs parse simultaneously
 117         */
 118        ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 119                          "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n",
 120                          info->node->name.ascii, info->node, info->obj_desc));
 121
 122        /* Create and init a Root Node */
 123
 124        op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
 125        if (!op) {
 126                status = AE_NO_MEMORY;
 127                goto cleanup;
 128        }
 129
 130        /* Create and initialize a new walk state */
 131
 132        info->pass_number = ACPI_IMODE_EXECUTE;
 133        walk_state =
 134            acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
 135                                      NULL, NULL);
 136        if (!walk_state) {
 137                status = AE_NO_MEMORY;
 138                goto cleanup;
 139        }
 140
 141        status = acpi_ds_init_aml_walk(walk_state, op, info->node,
 142                                       info->obj_desc->method.aml_start,
 143                                       info->obj_desc->method.aml_length, info,
 144                                       info->pass_number);
 145        if (ACPI_FAILURE(status)) {
 146                acpi_ds_delete_walk_state(walk_state);
 147                goto cleanup;
 148        }
 149
 150        if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
 151                walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
 152        }
 153
 154        /* Invoke an internal method if necessary */
 155
 156        if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
 157                status =
 158                    info->obj_desc->method.dispatch.implementation(walk_state);
 159                info->return_object = walk_state->return_desc;
 160
 161                /* Cleanup states */
 162
 163                acpi_ds_scope_stack_clear(walk_state);
 164                acpi_ps_cleanup_scope(&walk_state->parser_state);
 165                acpi_ds_terminate_control_method(walk_state->method_desc,
 166                                                 walk_state);
 167                acpi_ds_delete_walk_state(walk_state);
 168                goto cleanup;
 169        }
 170
 171        /*
 172         * Start method evaluation with an implicit return of zero.
 173         * This is done for Windows compatibility.
 174         */
 175        if (acpi_gbl_enable_interpreter_slack) {
 176                walk_state->implicit_return_obj =
 177                    acpi_ut_create_integer_object((u64) 0);
 178                if (!walk_state->implicit_return_obj) {
 179                        status = AE_NO_MEMORY;
 180                        acpi_ds_delete_walk_state(walk_state);
 181                        goto cleanup;
 182                }
 183        }
 184
 185        /* Parse the AML */
 186
 187        status = acpi_ps_parse_aml(walk_state);
 188
 189        /* walk_state was deleted by parse_aml */
 190
 191cleanup:
 192        acpi_ps_delete_parse_tree(op);
 193
 194        /* Take away the extra reference that we gave the parameters above */
 195
 196        acpi_ps_update_parameter_list(info, REF_DECREMENT);
 197
 198        /* Exit now if error above */
 199
 200        if (ACPI_FAILURE(status)) {
 201                return_ACPI_STATUS(status);
 202        }
 203
 204        /*
 205         * If the method has returned an object, signal this to the caller with
 206         * a control exception code
 207         */
 208        if (info->return_object) {
 209                ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
 210                                  info->return_object));
 211                ACPI_DUMP_STACK_ENTRY(info->return_object);
 212
 213                status = AE_CTRL_RETURN_VALUE;
 214        }
 215
 216        return_ACPI_STATUS(status);
 217}
 218
 219/*******************************************************************************
 220 *
 221 * FUNCTION:    acpi_ps_execute_table
 222 *
 223 * PARAMETERS:  info            - Method info block, contains:
 224 *              node            - Node to where the is entered into the
 225 *                                namespace
 226 *              obj_desc        - Pseudo method object describing the AML
 227 *                                code of the entire table
 228 *              pass_number     - Parse or execute pass
 229 *
 230 * RETURN:      Status
 231 *
 232 * DESCRIPTION: Execute a table
 233 *
 234 ******************************************************************************/
 235
 236acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info)
 237{
 238        acpi_status status;
 239        union acpi_parse_object *op = NULL;
 240        struct acpi_walk_state *walk_state = NULL;
 241
 242        ACPI_FUNCTION_TRACE(ps_execute_table);
 243
 244        /* Create and init a Root Node */
 245
 246        op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
 247        if (!op) {
 248                status = AE_NO_MEMORY;
 249                goto cleanup;
 250        }
 251
 252        /* Create and initialize a new walk state */
 253
 254        walk_state =
 255            acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
 256                                      NULL, NULL);
 257        if (!walk_state) {
 258                status = AE_NO_MEMORY;
 259                goto cleanup;
 260        }
 261
 262        status = acpi_ds_init_aml_walk(walk_state, op, info->node,
 263                                       info->obj_desc->method.aml_start,
 264                                       info->obj_desc->method.aml_length, info,
 265                                       info->pass_number);
 266        if (ACPI_FAILURE(status)) {
 267                goto cleanup;
 268        }
 269
 270        if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
 271                walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
 272        }
 273
 274        /* Info->Node is the default location to load the table  */
 275
 276        if (info->node && info->node != acpi_gbl_root_node) {
 277                status =
 278                    acpi_ds_scope_stack_push(info->node, ACPI_TYPE_METHOD,
 279                                             walk_state);
 280                if (ACPI_FAILURE(status)) {
 281                        goto cleanup;
 282                }
 283        }
 284
 285        /*
 286         * Parse the AML, walk_state will be deleted by parse_aml
 287         */
 288        acpi_ex_enter_interpreter();
 289        status = acpi_ps_parse_aml(walk_state);
 290        acpi_ex_exit_interpreter();
 291        walk_state = NULL;
 292
 293cleanup:
 294        if (walk_state) {
 295                acpi_ds_delete_walk_state(walk_state);
 296        }
 297        if (op) {
 298                acpi_ps_delete_parse_tree(op);
 299        }
 300        return_ACPI_STATUS(status);
 301}
 302
 303/*******************************************************************************
 304 *
 305 * FUNCTION:    acpi_ps_update_parameter_list
 306 *
 307 * PARAMETERS:  info            - See struct acpi_evaluate_info
 308 *                                (Used: parameter_type and Parameters)
 309 *              action          - Add or Remove reference
 310 *
 311 * RETURN:      Status
 312 *
 313 * DESCRIPTION: Update reference count on all method parameter objects
 314 *
 315 ******************************************************************************/
 316
 317static void
 318acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
 319{
 320        u32 i;
 321
 322        if (info->parameters) {
 323
 324                /* Update reference count for each parameter */
 325
 326                for (i = 0; info->parameters[i]; i++) {
 327
 328                        /* Ignore errors, just do them all */
 329
 330                        (void)acpi_ut_update_object_reference(info->
 331                                                              parameters[i],
 332                                                              action);
 333                }
 334        }
 335}
 336