1a159c266SJung-uk Kim /****************************************************************************** 2a159c266SJung-uk Kim * 3a159c266SJung-uk Kim * Module Name: dsmethod - Parser/Interpreter interface - control method parsing 4a159c266SJung-uk Kim * 5a159c266SJung-uk Kim *****************************************************************************/ 6a159c266SJung-uk Kim 70d84335fSJung-uk Kim /****************************************************************************** 80d84335fSJung-uk Kim * 90d84335fSJung-uk Kim * 1. Copyright Notice 100d84335fSJung-uk Kim * 11*804fe266SJung-uk Kim * Some or all of this work - Copyright (c) 1999 - 2024, Intel Corp. 12a159c266SJung-uk Kim * All rights reserved. 13a159c266SJung-uk Kim * 140d84335fSJung-uk Kim * 2. License 150d84335fSJung-uk Kim * 160d84335fSJung-uk Kim * 2.1. This is your license from Intel Corp. under its intellectual property 170d84335fSJung-uk Kim * rights. You may have additional license terms from the party that provided 180d84335fSJung-uk Kim * you this software, covering your right to use that party's intellectual 190d84335fSJung-uk Kim * property rights. 200d84335fSJung-uk Kim * 210d84335fSJung-uk Kim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 220d84335fSJung-uk Kim * copy of the source code appearing in this file ("Covered Code") an 230d84335fSJung-uk Kim * irrevocable, perpetual, worldwide license under Intel's copyrights in the 240d84335fSJung-uk Kim * base code distributed originally by Intel ("Original Intel Code") to copy, 250d84335fSJung-uk Kim * make derivatives, distribute, use and display any portion of the Covered 260d84335fSJung-uk Kim * Code in any form, with the right to sublicense such rights; and 270d84335fSJung-uk Kim * 280d84335fSJung-uk Kim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 290d84335fSJung-uk Kim * license (with the right to sublicense), under only those claims of Intel 300d84335fSJung-uk Kim * patents that are infringed by the Original Intel Code, to make, use, sell, 310d84335fSJung-uk Kim * offer to sell, and import the Covered Code and derivative works thereof 320d84335fSJung-uk Kim * solely to the minimum extent necessary to exercise the above copyright 330d84335fSJung-uk Kim * license, and in no event shall the patent license extend to any additions 340d84335fSJung-uk Kim * to or modifications of the Original Intel Code. No other license or right 350d84335fSJung-uk Kim * is granted directly or by implication, estoppel or otherwise; 360d84335fSJung-uk Kim * 370d84335fSJung-uk Kim * The above copyright and patent license is granted only if the following 380d84335fSJung-uk Kim * conditions are met: 390d84335fSJung-uk Kim * 400d84335fSJung-uk Kim * 3. Conditions 410d84335fSJung-uk Kim * 420d84335fSJung-uk Kim * 3.1. Redistribution of Source with Rights to Further Distribute Source. 430d84335fSJung-uk Kim * Redistribution of source code of any substantial portion of the Covered 440d84335fSJung-uk Kim * Code or modification with rights to further distribute source must include 450d84335fSJung-uk Kim * the above Copyright Notice, the above License, this list of Conditions, 460d84335fSJung-uk Kim * and the following Disclaimer and Export Compliance provision. In addition, 470d84335fSJung-uk Kim * Licensee must cause all Covered Code to which Licensee contributes to 480d84335fSJung-uk Kim * contain a file documenting the changes Licensee made to create that Covered 490d84335fSJung-uk Kim * Code and the date of any change. Licensee must include in that file the 500d84335fSJung-uk Kim * documentation of any changes made by any predecessor Licensee. Licensee 510d84335fSJung-uk Kim * must include a prominent statement that the modification is derived, 520d84335fSJung-uk Kim * directly or indirectly, from Original Intel Code. 530d84335fSJung-uk Kim * 540d84335fSJung-uk Kim * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 550d84335fSJung-uk Kim * Redistribution of source code of any substantial portion of the Covered 560d84335fSJung-uk Kim * Code or modification without rights to further distribute source must 570d84335fSJung-uk Kim * include the following Disclaimer and Export Compliance provision in the 580d84335fSJung-uk Kim * documentation and/or other materials provided with distribution. In 590d84335fSJung-uk Kim * addition, Licensee may not authorize further sublicense of source of any 600d84335fSJung-uk Kim * portion of the Covered Code, and must include terms to the effect that the 610d84335fSJung-uk Kim * license from Licensee to its licensee is limited to the intellectual 620d84335fSJung-uk Kim * property embodied in the software Licensee provides to its licensee, and 630d84335fSJung-uk Kim * not to intellectual property embodied in modifications its licensee may 640d84335fSJung-uk Kim * make. 650d84335fSJung-uk Kim * 660d84335fSJung-uk Kim * 3.3. Redistribution of Executable. Redistribution in executable form of any 670d84335fSJung-uk Kim * substantial portion of the Covered Code or modification must reproduce the 680d84335fSJung-uk Kim * above Copyright Notice, and the following Disclaimer and Export Compliance 690d84335fSJung-uk Kim * provision in the documentation and/or other materials provided with the 700d84335fSJung-uk Kim * distribution. 710d84335fSJung-uk Kim * 720d84335fSJung-uk Kim * 3.4. Intel retains all right, title, and interest in and to the Original 730d84335fSJung-uk Kim * Intel Code. 740d84335fSJung-uk Kim * 750d84335fSJung-uk Kim * 3.5. Neither the name Intel nor any other trademark owned or controlled by 760d84335fSJung-uk Kim * Intel shall be used in advertising or otherwise to promote the sale, use or 770d84335fSJung-uk Kim * other dealings in products derived from or relating to the Covered Code 780d84335fSJung-uk Kim * without prior written authorization from Intel. 790d84335fSJung-uk Kim * 800d84335fSJung-uk Kim * 4. Disclaimer and Export Compliance 810d84335fSJung-uk Kim * 820d84335fSJung-uk Kim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 830d84335fSJung-uk Kim * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 840d84335fSJung-uk Kim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 850d84335fSJung-uk Kim * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 860d84335fSJung-uk Kim * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 870d84335fSJung-uk Kim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 880d84335fSJung-uk Kim * PARTICULAR PURPOSE. 890d84335fSJung-uk Kim * 900d84335fSJung-uk Kim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 910d84335fSJung-uk Kim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 920d84335fSJung-uk Kim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 930d84335fSJung-uk Kim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 940d84335fSJung-uk Kim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 950d84335fSJung-uk Kim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 960d84335fSJung-uk Kim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 970d84335fSJung-uk Kim * LIMITED REMEDY. 980d84335fSJung-uk Kim * 990d84335fSJung-uk Kim * 4.3. Licensee shall not export, either directly or indirectly, any of this 1000d84335fSJung-uk Kim * software or system incorporating such software without first obtaining any 1010d84335fSJung-uk Kim * required license or other approval from the U. S. Department of Commerce or 1020d84335fSJung-uk Kim * any other agency or department of the United States Government. In the 1030d84335fSJung-uk Kim * event Licensee exports any such software from the United States or 1040d84335fSJung-uk Kim * re-exports any such software from a foreign destination, Licensee shall 1050d84335fSJung-uk Kim * ensure that the distribution and export/re-export of the software is in 1060d84335fSJung-uk Kim * compliance with all laws, regulations, orders, or other restrictions of the 1070d84335fSJung-uk Kim * U.S. Export Administration Regulations. Licensee agrees that neither it nor 1080d84335fSJung-uk Kim * any of its subsidiaries will export/re-export any technical data, process, 1090d84335fSJung-uk Kim * software, or service, directly or indirectly, to any country for which the 1100d84335fSJung-uk Kim * United States government or any agency thereof requires an export license, 1110d84335fSJung-uk Kim * other governmental approval, or letter of assurance, without first obtaining 1120d84335fSJung-uk Kim * such license, approval or letter. 1130d84335fSJung-uk Kim * 1140d84335fSJung-uk Kim ***************************************************************************** 1150d84335fSJung-uk Kim * 1160d84335fSJung-uk Kim * Alternatively, you may choose to be licensed under the terms of the 1170d84335fSJung-uk Kim * following license: 1180d84335fSJung-uk Kim * 119a159c266SJung-uk Kim * Redistribution and use in source and binary forms, with or without 120a159c266SJung-uk Kim * modification, are permitted provided that the following conditions 121a159c266SJung-uk Kim * are met: 122a159c266SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 123a159c266SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 124a159c266SJung-uk Kim * without modification. 125a159c266SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126a159c266SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 127a159c266SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 128a159c266SJung-uk Kim * including a substantially similar Disclaimer requirement for further 129a159c266SJung-uk Kim * binary redistribution. 130a159c266SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 131a159c266SJung-uk Kim * of any contributors may be used to endorse or promote products derived 132a159c266SJung-uk Kim * from this software without specific prior written permission. 133a159c266SJung-uk Kim * 1340d84335fSJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1350d84335fSJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1360d84335fSJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1370d84335fSJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1380d84335fSJung-uk Kim * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1390d84335fSJung-uk Kim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1400d84335fSJung-uk Kim * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1410d84335fSJung-uk Kim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1420d84335fSJung-uk Kim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1430d84335fSJung-uk Kim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1440d84335fSJung-uk Kim * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1450d84335fSJung-uk Kim * 1460d84335fSJung-uk Kim * Alternatively, you may choose to be licensed under the terms of the 147a159c266SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 148a159c266SJung-uk Kim * Software Foundation. 149a159c266SJung-uk Kim * 1500d84335fSJung-uk Kim *****************************************************************************/ 151a159c266SJung-uk Kim 152a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 153a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 154a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acdispat.h> 155a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acinterp.h> 156a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h> 157313a0c13SJung-uk Kim #include <contrib/dev/acpica/include/acparser.h> 158313a0c13SJung-uk Kim #include <contrib/dev/acpica/include/amlcode.h> 159fe0f0bbbSJung-uk Kim #include <contrib/dev/acpica/include/acdebug.h> 160a159c266SJung-uk Kim 161a159c266SJung-uk Kim 162a159c266SJung-uk Kim #define _COMPONENT ACPI_DISPATCHER 163a159c266SJung-uk Kim ACPI_MODULE_NAME ("dsmethod") 164a159c266SJung-uk Kim 165a159c266SJung-uk Kim /* Local prototypes */ 166a159c266SJung-uk Kim 167a159c266SJung-uk Kim static ACPI_STATUS 168313a0c13SJung-uk Kim AcpiDsDetectNamedOpcodes ( 169313a0c13SJung-uk Kim ACPI_WALK_STATE *WalkState, 170313a0c13SJung-uk Kim ACPI_PARSE_OBJECT **OutOp); 171313a0c13SJung-uk Kim 172313a0c13SJung-uk Kim static ACPI_STATUS 173a159c266SJung-uk Kim AcpiDsCreateMethodMutex ( 174a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *MethodDesc); 175a159c266SJung-uk Kim 176a159c266SJung-uk Kim 177a159c266SJung-uk Kim /******************************************************************************* 178a159c266SJung-uk Kim * 179313a0c13SJung-uk Kim * FUNCTION: AcpiDsAutoSerializeMethod 180313a0c13SJung-uk Kim * 181313a0c13SJung-uk Kim * PARAMETERS: Node - Namespace Node of the method 182313a0c13SJung-uk Kim * ObjDesc - Method object attached to node 183313a0c13SJung-uk Kim * 184313a0c13SJung-uk Kim * RETURN: Status 185313a0c13SJung-uk Kim * 186313a0c13SJung-uk Kim * DESCRIPTION: Parse a control method AML to scan for control methods that 187313a0c13SJung-uk Kim * need serialization due to the creation of named objects. 188313a0c13SJung-uk Kim * 189313a0c13SJung-uk Kim * NOTE: It is a bit of overkill to mark all such methods serialized, since 190313a0c13SJung-uk Kim * there is only a problem if the method actually blocks during execution. 191313a0c13SJung-uk Kim * A blocking operation is, for example, a Sleep() operation, or any access 192313a0c13SJung-uk Kim * to an operation region. However, it is probably not possible to easily 193313a0c13SJung-uk Kim * detect whether a method will block or not, so we simply mark all suspicious 194313a0c13SJung-uk Kim * methods as serialized. 195313a0c13SJung-uk Kim * 196313a0c13SJung-uk Kim * NOTE2: This code is essentially a generic routine for parsing a single 197313a0c13SJung-uk Kim * control method. 198313a0c13SJung-uk Kim * 199313a0c13SJung-uk Kim ******************************************************************************/ 200313a0c13SJung-uk Kim 201313a0c13SJung-uk Kim ACPI_STATUS 202313a0c13SJung-uk Kim AcpiDsAutoSerializeMethod ( 203313a0c13SJung-uk Kim ACPI_NAMESPACE_NODE *Node, 204313a0c13SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc) 205313a0c13SJung-uk Kim { 206313a0c13SJung-uk Kim ACPI_STATUS Status; 207313a0c13SJung-uk Kim ACPI_PARSE_OBJECT *Op = NULL; 208313a0c13SJung-uk Kim ACPI_WALK_STATE *WalkState; 209313a0c13SJung-uk Kim 210313a0c13SJung-uk Kim 211313a0c13SJung-uk Kim ACPI_FUNCTION_TRACE_PTR (DsAutoSerializeMethod, Node); 212313a0c13SJung-uk Kim 213313a0c13SJung-uk Kim 214313a0c13SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, 215313a0c13SJung-uk Kim "Method auto-serialization parse [%4.4s] %p\n", 216313a0c13SJung-uk Kim AcpiUtGetNodeName (Node), Node)); 217313a0c13SJung-uk Kim 218313a0c13SJung-uk Kim /* Create/Init a root op for the method parse tree */ 219313a0c13SJung-uk Kim 220fe0f0bbbSJung-uk Kim Op = AcpiPsAllocOp (AML_METHOD_OP, ObjDesc->Method.AmlStart); 221313a0c13SJung-uk Kim if (!Op) 222313a0c13SJung-uk Kim { 2231cc50d6bSJung-uk Kim return_ACPI_STATUS (AE_NO_MEMORY); 224313a0c13SJung-uk Kim } 225313a0c13SJung-uk Kim 226313a0c13SJung-uk Kim AcpiPsSetName (Op, Node->Name.Integer); 227313a0c13SJung-uk Kim Op->Common.Node = Node; 228313a0c13SJung-uk Kim 229313a0c13SJung-uk Kim /* Create and initialize a new walk state */ 230313a0c13SJung-uk Kim 231313a0c13SJung-uk Kim WalkState = AcpiDsCreateWalkState (Node->OwnerId, NULL, NULL, NULL); 232313a0c13SJung-uk Kim if (!WalkState) 233313a0c13SJung-uk Kim { 234a371a5fdSJung-uk Kim AcpiPsFreeOp (Op); 2351cc50d6bSJung-uk Kim return_ACPI_STATUS (AE_NO_MEMORY); 236313a0c13SJung-uk Kim } 237313a0c13SJung-uk Kim 238f8146b88SJung-uk Kim Status = AcpiDsInitAmlWalk (WalkState, Op, Node, 239f8146b88SJung-uk Kim ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, NULL, 0); 240313a0c13SJung-uk Kim if (ACPI_FAILURE (Status)) 241313a0c13SJung-uk Kim { 242313a0c13SJung-uk Kim AcpiDsDeleteWalkState (WalkState); 243a371a5fdSJung-uk Kim AcpiPsFreeOp (Op); 244313a0c13SJung-uk Kim return_ACPI_STATUS (Status); 245313a0c13SJung-uk Kim } 246313a0c13SJung-uk Kim 247313a0c13SJung-uk Kim WalkState->DescendingCallback = AcpiDsDetectNamedOpcodes; 248313a0c13SJung-uk Kim 249313a0c13SJung-uk Kim /* Parse the method, scan for creation of named objects */ 250313a0c13SJung-uk Kim 251313a0c13SJung-uk Kim Status = AcpiPsParseAml (WalkState); 252313a0c13SJung-uk Kim 253313a0c13SJung-uk Kim AcpiPsDeleteParseTree (Op); 254313a0c13SJung-uk Kim return_ACPI_STATUS (Status); 255313a0c13SJung-uk Kim } 256313a0c13SJung-uk Kim 257313a0c13SJung-uk Kim 258313a0c13SJung-uk Kim /******************************************************************************* 259313a0c13SJung-uk Kim * 260313a0c13SJung-uk Kim * FUNCTION: AcpiDsDetectNamedOpcodes 261313a0c13SJung-uk Kim * 262313a0c13SJung-uk Kim * PARAMETERS: WalkState - Current state of the parse tree walk 263313a0c13SJung-uk Kim * OutOp - Unused, required for parser interface 264313a0c13SJung-uk Kim * 265313a0c13SJung-uk Kim * RETURN: Status 266313a0c13SJung-uk Kim * 267313a0c13SJung-uk Kim * DESCRIPTION: Descending callback used during the loading of ACPI tables. 268313a0c13SJung-uk Kim * Currently used to detect methods that must be marked serialized 269313a0c13SJung-uk Kim * in order to avoid problems with the creation of named objects. 270313a0c13SJung-uk Kim * 271313a0c13SJung-uk Kim ******************************************************************************/ 272313a0c13SJung-uk Kim 273313a0c13SJung-uk Kim static ACPI_STATUS 274313a0c13SJung-uk Kim AcpiDsDetectNamedOpcodes ( 275313a0c13SJung-uk Kim ACPI_WALK_STATE *WalkState, 276313a0c13SJung-uk Kim ACPI_PARSE_OBJECT **OutOp) 277313a0c13SJung-uk Kim { 278313a0c13SJung-uk Kim 279313a0c13SJung-uk Kim ACPI_FUNCTION_NAME (AcpiDsDetectNamedOpcodes); 280313a0c13SJung-uk Kim 281313a0c13SJung-uk Kim 282313a0c13SJung-uk Kim /* We are only interested in opcodes that create a new name */ 283313a0c13SJung-uk Kim 284313a0c13SJung-uk Kim if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_FIELD))) 285313a0c13SJung-uk Kim { 286313a0c13SJung-uk Kim return (AE_OK); 287313a0c13SJung-uk Kim } 288313a0c13SJung-uk Kim 289313a0c13SJung-uk Kim /* 290313a0c13SJung-uk Kim * At this point, we know we have a Named object opcode. 291313a0c13SJung-uk Kim * Mark the method as serialized. Later code will create a mutex for 292313a0c13SJung-uk Kim * this method to enforce serialization. 293313a0c13SJung-uk Kim * 294313a0c13SJung-uk Kim * Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the 295313a0c13SJung-uk Kim * Sync Level mechanism for this method, even though it is now serialized. 296313a0c13SJung-uk Kim * Otherwise, there can be conflicts with existing ASL code that actually 297313a0c13SJung-uk Kim * uses sync levels. 298313a0c13SJung-uk Kim */ 299313a0c13SJung-uk Kim WalkState->MethodDesc->Method.SyncLevel = 0; 300313a0c13SJung-uk Kim WalkState->MethodDesc->Method.InfoFlags |= 301313a0c13SJung-uk Kim (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL); 302313a0c13SJung-uk Kim 303313a0c13SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 304313a0c13SJung-uk Kim "Method serialized [%4.4s] %p - [%s] (%4.4X)\n", 305313a0c13SJung-uk Kim WalkState->MethodNode->Name.Ascii, WalkState->MethodNode, 306313a0c13SJung-uk Kim WalkState->OpInfo->Name, WalkState->Opcode)); 307313a0c13SJung-uk Kim 308313a0c13SJung-uk Kim /* Abort the parse, no need to examine this method any further */ 309313a0c13SJung-uk Kim 310313a0c13SJung-uk Kim return (AE_CTRL_TERMINATE); 311313a0c13SJung-uk Kim } 312313a0c13SJung-uk Kim 313313a0c13SJung-uk Kim 314313a0c13SJung-uk Kim /******************************************************************************* 315313a0c13SJung-uk Kim * 316a159c266SJung-uk Kim * FUNCTION: AcpiDsMethodError 317a159c266SJung-uk Kim * 318a159c266SJung-uk Kim * PARAMETERS: Status - Execution status 319a159c266SJung-uk Kim * WalkState - Current state 320a159c266SJung-uk Kim * 321a159c266SJung-uk Kim * RETURN: Status 322a159c266SJung-uk Kim * 323a159c266SJung-uk Kim * DESCRIPTION: Called on method error. Invoke the global exception handler if 324fe0f0bbbSJung-uk Kim * present, dump the method data if the debugger is configured 325a159c266SJung-uk Kim * 326a159c266SJung-uk Kim * Note: Allows the exception handler to change the status code 327a159c266SJung-uk Kim * 328a159c266SJung-uk Kim ******************************************************************************/ 329a159c266SJung-uk Kim 330a159c266SJung-uk Kim ACPI_STATUS 331a159c266SJung-uk Kim AcpiDsMethodError ( 332a159c266SJung-uk Kim ACPI_STATUS Status, 333a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 334a159c266SJung-uk Kim { 335fe0f0bbbSJung-uk Kim UINT32 AmlOffset; 336af051161SJung-uk Kim ACPI_NAME Name = 0; 337fe0f0bbbSJung-uk Kim 338fe0f0bbbSJung-uk Kim 339a159c266SJung-uk Kim ACPI_FUNCTION_ENTRY (); 340a159c266SJung-uk Kim 341a159c266SJung-uk Kim 342a159c266SJung-uk Kim /* Ignore AE_OK and control exception codes */ 343a159c266SJung-uk Kim 344a159c266SJung-uk Kim if (ACPI_SUCCESS (Status) || 345a159c266SJung-uk Kim (Status & AE_CODE_CONTROL)) 346a159c266SJung-uk Kim { 347a159c266SJung-uk Kim return (Status); 348a159c266SJung-uk Kim } 349a159c266SJung-uk Kim 350a159c266SJung-uk Kim /* Invoke the global exception handler */ 351a159c266SJung-uk Kim 352a159c266SJung-uk Kim if (AcpiGbl_ExceptionHandler) 353a159c266SJung-uk Kim { 354a159c266SJung-uk Kim /* Exit the interpreter, allow handler to execute methods */ 355a159c266SJung-uk Kim 356a159c266SJung-uk Kim AcpiExExitInterpreter (); 357a159c266SJung-uk Kim 358a159c266SJung-uk Kim /* 359a159c266SJung-uk Kim * Handler can map the exception code to anything it wants, including 360a159c266SJung-uk Kim * AE_OK, in which case the executing method will not be aborted. 361a159c266SJung-uk Kim */ 362fe0f0bbbSJung-uk Kim AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml, 363fe0f0bbbSJung-uk Kim WalkState->ParserState.AmlStart); 364fe0f0bbbSJung-uk Kim 365af051161SJung-uk Kim if (WalkState->MethodNode) 366af051161SJung-uk Kim { 367af051161SJung-uk Kim Name = WalkState->MethodNode->Name.Integer; 368af051161SJung-uk Kim } 369af051161SJung-uk Kim else if (WalkState->DeferredNode) 370af051161SJung-uk Kim { 371af051161SJung-uk Kim Name = WalkState->DeferredNode->Name.Integer; 372af051161SJung-uk Kim } 373af051161SJung-uk Kim 374af051161SJung-uk Kim Status = AcpiGbl_ExceptionHandler (Status, Name, 375fe0f0bbbSJung-uk Kim WalkState->Opcode, AmlOffset, NULL); 376a159c266SJung-uk Kim AcpiExEnterInterpreter (); 377a159c266SJung-uk Kim } 378a159c266SJung-uk Kim 379a159c266SJung-uk Kim AcpiDsClearImplicitReturn (WalkState); 380a159c266SJung-uk Kim 381a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 382a159c266SJung-uk Kim { 383fe0f0bbbSJung-uk Kim AcpiDsDumpMethodStack (Status, WalkState, WalkState->Op); 384a159c266SJung-uk Kim 385fe0f0bbbSJung-uk Kim /* Display method locals/args if debugger is present */ 386fe0f0bbbSJung-uk Kim 387fe0f0bbbSJung-uk Kim #ifdef ACPI_DEBUGGER 388fe0f0bbbSJung-uk Kim AcpiDbDumpMethodInfo (Status, WalkState); 389a159c266SJung-uk Kim #endif 390fe0f0bbbSJung-uk Kim } 391a159c266SJung-uk Kim 392a159c266SJung-uk Kim return (Status); 393a159c266SJung-uk Kim } 394a159c266SJung-uk Kim 395a159c266SJung-uk Kim 396a159c266SJung-uk Kim /******************************************************************************* 397a159c266SJung-uk Kim * 398a159c266SJung-uk Kim * FUNCTION: AcpiDsCreateMethodMutex 399a159c266SJung-uk Kim * 400a159c266SJung-uk Kim * PARAMETERS: ObjDesc - The method object 401a159c266SJung-uk Kim * 402a159c266SJung-uk Kim * RETURN: Status 403a159c266SJung-uk Kim * 404a159c266SJung-uk Kim * DESCRIPTION: Create a mutex object for a serialized control method 405a159c266SJung-uk Kim * 406a159c266SJung-uk Kim ******************************************************************************/ 407a159c266SJung-uk Kim 408a159c266SJung-uk Kim static ACPI_STATUS 409a159c266SJung-uk Kim AcpiDsCreateMethodMutex ( 410a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *MethodDesc) 411a159c266SJung-uk Kim { 412a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *MutexDesc; 413a159c266SJung-uk Kim ACPI_STATUS Status; 414a159c266SJung-uk Kim 415a159c266SJung-uk Kim 416a159c266SJung-uk Kim ACPI_FUNCTION_TRACE (DsCreateMethodMutex); 417a159c266SJung-uk Kim 418a159c266SJung-uk Kim 419a159c266SJung-uk Kim /* Create the new mutex object */ 420a159c266SJung-uk Kim 421a159c266SJung-uk Kim MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX); 422a159c266SJung-uk Kim if (!MutexDesc) 423a159c266SJung-uk Kim { 424a159c266SJung-uk Kim return_ACPI_STATUS (AE_NO_MEMORY); 425a159c266SJung-uk Kim } 426a159c266SJung-uk Kim 427a159c266SJung-uk Kim /* Create the actual OS Mutex */ 428a159c266SJung-uk Kim 429a159c266SJung-uk Kim Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex); 430a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 431a159c266SJung-uk Kim { 432efcc2a30SJung-uk Kim AcpiUtDeleteObjectDesc (MutexDesc); 433a159c266SJung-uk Kim return_ACPI_STATUS (Status); 434a159c266SJung-uk Kim } 435a159c266SJung-uk Kim 436a159c266SJung-uk Kim MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel; 437a159c266SJung-uk Kim MethodDesc->Method.Mutex = MutexDesc; 438a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 439a159c266SJung-uk Kim } 440a159c266SJung-uk Kim 441a159c266SJung-uk Kim 442a159c266SJung-uk Kim /******************************************************************************* 443a159c266SJung-uk Kim * 444a159c266SJung-uk Kim * FUNCTION: AcpiDsBeginMethodExecution 445a159c266SJung-uk Kim * 446a159c266SJung-uk Kim * PARAMETERS: MethodNode - Node of the method 447a159c266SJung-uk Kim * ObjDesc - The method object 448a159c266SJung-uk Kim * WalkState - current state, NULL if not yet executing 449a159c266SJung-uk Kim * a method. 450a159c266SJung-uk Kim * 451a159c266SJung-uk Kim * RETURN: Status 452a159c266SJung-uk Kim * 453a159c266SJung-uk Kim * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, 454a159c266SJung-uk Kim * increments the thread count, and waits at the method semaphore 455a159c266SJung-uk Kim * for clearance to execute. 456a159c266SJung-uk Kim * 457a159c266SJung-uk Kim ******************************************************************************/ 458a159c266SJung-uk Kim 459a159c266SJung-uk Kim ACPI_STATUS 460a159c266SJung-uk Kim AcpiDsBeginMethodExecution ( 461a159c266SJung-uk Kim ACPI_NAMESPACE_NODE *MethodNode, 462a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc, 463a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 464a159c266SJung-uk Kim { 465a159c266SJung-uk Kim ACPI_STATUS Status = AE_OK; 466a159c266SJung-uk Kim 467a159c266SJung-uk Kim 468a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode); 469a159c266SJung-uk Kim 470a159c266SJung-uk Kim 471a159c266SJung-uk Kim if (!MethodNode) 472a159c266SJung-uk Kim { 473a159c266SJung-uk Kim return_ACPI_STATUS (AE_NULL_ENTRY); 474a159c266SJung-uk Kim } 475a159c266SJung-uk Kim 476fe0f0bbbSJung-uk Kim AcpiExStartTraceMethod (MethodNode, ObjDesc, WalkState); 477fe0f0bbbSJung-uk Kim 478a159c266SJung-uk Kim /* Prevent wraparound of thread count */ 479a159c266SJung-uk Kim 480a159c266SJung-uk Kim if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX) 481a159c266SJung-uk Kim { 482a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 483a159c266SJung-uk Kim "Method reached maximum reentrancy limit (255)")); 484a159c266SJung-uk Kim return_ACPI_STATUS (AE_AML_METHOD_LIMIT); 485a159c266SJung-uk Kim } 486a159c266SJung-uk Kim 487a159c266SJung-uk Kim /* 488a159c266SJung-uk Kim * If this method is serialized, we need to acquire the method mutex. 489a159c266SJung-uk Kim */ 490a159c266SJung-uk Kim if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) 491a159c266SJung-uk Kim { 492a159c266SJung-uk Kim /* 493a159c266SJung-uk Kim * Create a mutex for the method if it is defined to be Serialized 494a159c266SJung-uk Kim * and a mutex has not already been created. We defer the mutex creation 495a159c266SJung-uk Kim * until a method is actually executed, to minimize the object count 496a159c266SJung-uk Kim */ 497a159c266SJung-uk Kim if (!ObjDesc->Method.Mutex) 498a159c266SJung-uk Kim { 499a159c266SJung-uk Kim Status = AcpiDsCreateMethodMutex (ObjDesc); 500a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 501a159c266SJung-uk Kim { 502a159c266SJung-uk Kim return_ACPI_STATUS (Status); 503a159c266SJung-uk Kim } 504a159c266SJung-uk Kim } 505a159c266SJung-uk Kim 506a159c266SJung-uk Kim /* 507a159c266SJung-uk Kim * The CurrentSyncLevel (per-thread) must be less than or equal to 508a159c266SJung-uk Kim * the sync level of the method. This mechanism provides some 509313a0c13SJung-uk Kim * deadlock prevention. 510313a0c13SJung-uk Kim * 511313a0c13SJung-uk Kim * If the method was auto-serialized, we just ignore the sync level 512313a0c13SJung-uk Kim * mechanism, because auto-serialization of methods can interfere 513313a0c13SJung-uk Kim * with ASL code that actually uses sync levels. 514a159c266SJung-uk Kim * 515a159c266SJung-uk Kim * Top-level method invocation has no walk state at this point 516a159c266SJung-uk Kim */ 517a159c266SJung-uk Kim if (WalkState && 518313a0c13SJung-uk Kim (!(ObjDesc->Method.InfoFlags & ACPI_METHOD_IGNORE_SYNC_LEVEL)) && 519f8146b88SJung-uk Kim (WalkState->Thread->CurrentSyncLevel > 520f8146b88SJung-uk Kim ObjDesc->Method.Mutex->Mutex.SyncLevel)) 521a159c266SJung-uk Kim { 522a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 523f8146b88SJung-uk Kim "Cannot acquire Mutex for method [%4.4s]" 524f8146b88SJung-uk Kim ", current SyncLevel is too large (%u)", 525a159c266SJung-uk Kim AcpiUtGetNodeName (MethodNode), 526a159c266SJung-uk Kim WalkState->Thread->CurrentSyncLevel)); 527a159c266SJung-uk Kim 528a159c266SJung-uk Kim return_ACPI_STATUS (AE_AML_MUTEX_ORDER); 529a159c266SJung-uk Kim } 530a159c266SJung-uk Kim 531a159c266SJung-uk Kim /* 532a159c266SJung-uk Kim * Obtain the method mutex if necessary. Do not acquire mutex for a 533a159c266SJung-uk Kim * recursive call. 534a159c266SJung-uk Kim */ 535a159c266SJung-uk Kim if (!WalkState || 536a159c266SJung-uk Kim !ObjDesc->Method.Mutex->Mutex.ThreadId || 537f8146b88SJung-uk Kim (WalkState->Thread->ThreadId != 538f8146b88SJung-uk Kim ObjDesc->Method.Mutex->Mutex.ThreadId)) 539a159c266SJung-uk Kim { 540a159c266SJung-uk Kim /* 541a159c266SJung-uk Kim * Acquire the method mutex. This releases the interpreter if we 542a159c266SJung-uk Kim * block (and reacquires it before it returns) 543a159c266SJung-uk Kim */ 544f8146b88SJung-uk Kim Status = AcpiExSystemWaitMutex ( 545f8146b88SJung-uk Kim ObjDesc->Method.Mutex->Mutex.OsMutex, ACPI_WAIT_FOREVER); 546a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 547a159c266SJung-uk Kim { 548a159c266SJung-uk Kim return_ACPI_STATUS (Status); 549a159c266SJung-uk Kim } 550a159c266SJung-uk Kim 551a159c266SJung-uk Kim /* Update the mutex and walk info and save the original SyncLevel */ 552a159c266SJung-uk Kim 553a159c266SJung-uk Kim if (WalkState) 554a159c266SJung-uk Kim { 555a159c266SJung-uk Kim ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = 556a159c266SJung-uk Kim WalkState->Thread->CurrentSyncLevel; 557a159c266SJung-uk Kim 558f8146b88SJung-uk Kim ObjDesc->Method.Mutex->Mutex.ThreadId = 559f8146b88SJung-uk Kim WalkState->Thread->ThreadId; 560f8146b88SJung-uk Kim 561f8146b88SJung-uk Kim /* 562f8146b88SJung-uk Kim * Update the current SyncLevel only if this is not an auto- 563f8146b88SJung-uk Kim * serialized method. In the auto case, we have to ignore 564f8146b88SJung-uk Kim * the sync level for the method mutex (created for the 565f8146b88SJung-uk Kim * auto-serialization) because we have no idea of what the 566f8146b88SJung-uk Kim * sync level should be. Therefore, just ignore it. 567f8146b88SJung-uk Kim */ 568f8146b88SJung-uk Kim if (!(ObjDesc->Method.InfoFlags & 569f8146b88SJung-uk Kim ACPI_METHOD_IGNORE_SYNC_LEVEL)) 570f8146b88SJung-uk Kim { 571f8146b88SJung-uk Kim WalkState->Thread->CurrentSyncLevel = 572f8146b88SJung-uk Kim ObjDesc->Method.SyncLevel; 573f8146b88SJung-uk Kim } 574a159c266SJung-uk Kim } 575a159c266SJung-uk Kim else 576a159c266SJung-uk Kim { 577a159c266SJung-uk Kim ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = 578a159c266SJung-uk Kim ObjDesc->Method.Mutex->Mutex.SyncLevel; 579f8146b88SJung-uk Kim 580f8146b88SJung-uk Kim ObjDesc->Method.Mutex->Mutex.ThreadId = 581f8146b88SJung-uk Kim AcpiOsGetThreadId (); 582a159c266SJung-uk Kim } 583a159c266SJung-uk Kim } 584a159c266SJung-uk Kim 585a159c266SJung-uk Kim /* Always increase acquisition depth */ 586a159c266SJung-uk Kim 587a159c266SJung-uk Kim ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++; 588a159c266SJung-uk Kim } 589a159c266SJung-uk Kim 590a159c266SJung-uk Kim /* 591a159c266SJung-uk Kim * Allocate an Owner ID for this method, only if this is the first thread 592a159c266SJung-uk Kim * to begin concurrent execution. We only need one OwnerId, even if the 593a159c266SJung-uk Kim * method is invoked recursively. 594a159c266SJung-uk Kim */ 595a159c266SJung-uk Kim if (!ObjDesc->Method.OwnerId) 596a159c266SJung-uk Kim { 597a159c266SJung-uk Kim Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); 598a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 599a159c266SJung-uk Kim { 600a159c266SJung-uk Kim goto Cleanup; 601a159c266SJung-uk Kim } 602a159c266SJung-uk Kim } 603a159c266SJung-uk Kim 604a159c266SJung-uk Kim /* 605a159c266SJung-uk Kim * Increment the method parse tree thread count since it has been 606a159c266SJung-uk Kim * reentered one more time (even if it is the same thread) 607a159c266SJung-uk Kim */ 608a159c266SJung-uk Kim ObjDesc->Method.ThreadCount++; 609a159c266SJung-uk Kim AcpiMethodCount++; 610a159c266SJung-uk Kim return_ACPI_STATUS (Status); 611a159c266SJung-uk Kim 612a159c266SJung-uk Kim 613a159c266SJung-uk Kim Cleanup: 614a159c266SJung-uk Kim /* On error, must release the method mutex (if present) */ 615a159c266SJung-uk Kim 616a159c266SJung-uk Kim if (ObjDesc->Method.Mutex) 617a159c266SJung-uk Kim { 618a159c266SJung-uk Kim AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex); 619a159c266SJung-uk Kim } 620a159c266SJung-uk Kim return_ACPI_STATUS (Status); 621a159c266SJung-uk Kim } 622a159c266SJung-uk Kim 623a159c266SJung-uk Kim 624a159c266SJung-uk Kim /******************************************************************************* 625a159c266SJung-uk Kim * 626a159c266SJung-uk Kim * FUNCTION: AcpiDsCallControlMethod 627a159c266SJung-uk Kim * 628a159c266SJung-uk Kim * PARAMETERS: Thread - Info for this thread 629a159c266SJung-uk Kim * ThisWalkState - Current walk state 630a159c266SJung-uk Kim * Op - Current Op to be walked 631a159c266SJung-uk Kim * 632a159c266SJung-uk Kim * RETURN: Status 633a159c266SJung-uk Kim * 634a159c266SJung-uk Kim * DESCRIPTION: Transfer execution to a called control method 635a159c266SJung-uk Kim * 636a159c266SJung-uk Kim ******************************************************************************/ 637a159c266SJung-uk Kim 638a159c266SJung-uk Kim ACPI_STATUS 639a159c266SJung-uk Kim AcpiDsCallControlMethod ( 640a159c266SJung-uk Kim ACPI_THREAD_STATE *Thread, 641a159c266SJung-uk Kim ACPI_WALK_STATE *ThisWalkState, 642a159c266SJung-uk Kim ACPI_PARSE_OBJECT *Op) 643a159c266SJung-uk Kim { 644a159c266SJung-uk Kim ACPI_STATUS Status; 645a159c266SJung-uk Kim ACPI_NAMESPACE_NODE *MethodNode; 646a159c266SJung-uk Kim ACPI_WALK_STATE *NextWalkState = NULL; 647a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ObjDesc; 648a159c266SJung-uk Kim ACPI_EVALUATE_INFO *Info; 649a159c266SJung-uk Kim UINT32 i; 650a159c266SJung-uk Kim 651a159c266SJung-uk Kim 652a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState); 653a159c266SJung-uk Kim 654f8146b88SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 655f8146b88SJung-uk Kim "Calling method %p, currentstate=%p\n", 656a159c266SJung-uk Kim ThisWalkState->PrevOp, ThisWalkState)); 657a159c266SJung-uk Kim 658a159c266SJung-uk Kim /* 659a159c266SJung-uk Kim * Get the namespace entry for the control method we are about to call 660a159c266SJung-uk Kim */ 661a159c266SJung-uk Kim MethodNode = ThisWalkState->MethodCallNode; 662a159c266SJung-uk Kim if (!MethodNode) 663a159c266SJung-uk Kim { 664a159c266SJung-uk Kim return_ACPI_STATUS (AE_NULL_ENTRY); 665a159c266SJung-uk Kim } 666a159c266SJung-uk Kim 667a159c266SJung-uk Kim ObjDesc = AcpiNsGetAttachedObject (MethodNode); 668a159c266SJung-uk Kim if (!ObjDesc) 669a159c266SJung-uk Kim { 670a159c266SJung-uk Kim return_ACPI_STATUS (AE_NULL_OBJECT); 671a159c266SJung-uk Kim } 672a159c266SJung-uk Kim 673a159c266SJung-uk Kim /* Init for new method, possibly wait on method mutex */ 674a159c266SJung-uk Kim 675f8146b88SJung-uk Kim Status = AcpiDsBeginMethodExecution ( 676f8146b88SJung-uk Kim MethodNode, ObjDesc, ThisWalkState); 677a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 678a159c266SJung-uk Kim { 679a159c266SJung-uk Kim return_ACPI_STATUS (Status); 680a159c266SJung-uk Kim } 681a159c266SJung-uk Kim 682a159c266SJung-uk Kim /* Begin method parse/execution. Create a new walk state */ 683a159c266SJung-uk Kim 684f8146b88SJung-uk Kim NextWalkState = AcpiDsCreateWalkState ( 685f8146b88SJung-uk Kim ObjDesc->Method.OwnerId, NULL, ObjDesc, Thread); 686a159c266SJung-uk Kim if (!NextWalkState) 687a159c266SJung-uk Kim { 688a159c266SJung-uk Kim Status = AE_NO_MEMORY; 689a159c266SJung-uk Kim goto Cleanup; 690a159c266SJung-uk Kim } 691a159c266SJung-uk Kim 692a159c266SJung-uk Kim /* 693a159c266SJung-uk Kim * The resolved arguments were put on the previous walk state's operand 694a159c266SJung-uk Kim * stack. Operands on the previous walk state stack always 695a159c266SJung-uk Kim * start at index 0. Also, null terminate the list of arguments 696a159c266SJung-uk Kim */ 697a159c266SJung-uk Kim ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL; 698a159c266SJung-uk Kim 699a159c266SJung-uk Kim /* 700a159c266SJung-uk Kim * Allocate and initialize the evaluation information block 701a159c266SJung-uk Kim * TBD: this is somewhat inefficient, should change interface to 702a159c266SJung-uk Kim * DsInitAmlWalk. For now, keeps this struct off the CPU stack 703a159c266SJung-uk Kim */ 704a159c266SJung-uk Kim Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 705a159c266SJung-uk Kim if (!Info) 706a159c266SJung-uk Kim { 707ed17e06eSJung-uk Kim Status = AE_NO_MEMORY; 708722b1667SJung-uk Kim goto PopWalkState; 709a159c266SJung-uk Kim } 710a159c266SJung-uk Kim 711a159c266SJung-uk Kim Info->Parameters = &ThisWalkState->Operands[0]; 712a159c266SJung-uk Kim 713a159c266SJung-uk Kim Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode, 714a159c266SJung-uk Kim ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, 715a159c266SJung-uk Kim Info, ACPI_IMODE_EXECUTE); 716a159c266SJung-uk Kim 717a159c266SJung-uk Kim ACPI_FREE (Info); 718a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 719a159c266SJung-uk Kim { 720722b1667SJung-uk Kim goto PopWalkState; 721a159c266SJung-uk Kim } 722a159c266SJung-uk Kim 72390b566fdSJung-uk Kim NextWalkState->MethodNestingDepth = ThisWalkState->MethodNestingDepth + 1; 72490b566fdSJung-uk Kim 725a159c266SJung-uk Kim /* 726a159c266SJung-uk Kim * Delete the operands on the previous walkstate operand stack 727a159c266SJung-uk Kim * (they were copied to new objects) 728a159c266SJung-uk Kim */ 729a159c266SJung-uk Kim for (i = 0; i < ObjDesc->Method.ParamCount; i++) 730a159c266SJung-uk Kim { 731a159c266SJung-uk Kim AcpiUtRemoveReference (ThisWalkState->Operands [i]); 732a159c266SJung-uk Kim ThisWalkState->Operands [i] = NULL; 733a159c266SJung-uk Kim } 734a159c266SJung-uk Kim 735a159c266SJung-uk Kim /* Clear the operand stack */ 736a159c266SJung-uk Kim 737a159c266SJung-uk Kim ThisWalkState->NumOperands = 0; 738a159c266SJung-uk Kim 739a159c266SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 740a159c266SJung-uk Kim "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", 741a159c266SJung-uk Kim MethodNode->Name.Ascii, NextWalkState)); 742a159c266SJung-uk Kim 74390b566fdSJung-uk Kim ThisWalkState->MethodPathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); 74490b566fdSJung-uk Kim ThisWalkState->MethodIsNested = TRUE; 74590b566fdSJung-uk Kim 74690b566fdSJung-uk Kim /* Optional object evaluation log */ 74790b566fdSJung-uk Kim 74890b566fdSJung-uk Kim ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION, 74990b566fdSJung-uk Kim "%-26s: %*s%s\n", " Nested method call", 75090b566fdSJung-uk Kim NextWalkState->MethodNestingDepth * 3, " ", 75190b566fdSJung-uk Kim &ThisWalkState->MethodPathname[1])); 75290b566fdSJung-uk Kim 753a159c266SJung-uk Kim /* Invoke an internal method if necessary */ 754a159c266SJung-uk Kim 755a159c266SJung-uk Kim if (ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY) 756a159c266SJung-uk Kim { 757a159c266SJung-uk Kim Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState); 758a159c266SJung-uk Kim if (Status == AE_OK) 759a159c266SJung-uk Kim { 760a159c266SJung-uk Kim Status = AE_CTRL_TERMINATE; 761a159c266SJung-uk Kim } 762a159c266SJung-uk Kim } 763a159c266SJung-uk Kim 764a159c266SJung-uk Kim return_ACPI_STATUS (Status); 765a159c266SJung-uk Kim 766a159c266SJung-uk Kim 767722b1667SJung-uk Kim PopWalkState: 768722b1667SJung-uk Kim 769722b1667SJung-uk Kim /* On error, pop the walk state to be deleted from thread */ 770722b1667SJung-uk Kim 771722b1667SJung-uk Kim AcpiDsPopWalkState(Thread); 772722b1667SJung-uk Kim 773a159c266SJung-uk Kim Cleanup: 774a159c266SJung-uk Kim 775a159c266SJung-uk Kim /* On error, we must terminate the method properly */ 776a159c266SJung-uk Kim 777a159c266SJung-uk Kim AcpiDsTerminateControlMethod (ObjDesc, NextWalkState); 778a159c266SJung-uk Kim AcpiDsDeleteWalkState (NextWalkState); 779a159c266SJung-uk Kim 780a159c266SJung-uk Kim return_ACPI_STATUS (Status); 781a159c266SJung-uk Kim } 782a159c266SJung-uk Kim 783a159c266SJung-uk Kim 784a159c266SJung-uk Kim /******************************************************************************* 785a159c266SJung-uk Kim * 786a159c266SJung-uk Kim * FUNCTION: AcpiDsRestartControlMethod 787a159c266SJung-uk Kim * 788a159c266SJung-uk Kim * PARAMETERS: WalkState - State for preempted method (caller) 789a159c266SJung-uk Kim * ReturnDesc - Return value from the called method 790a159c266SJung-uk Kim * 791a159c266SJung-uk Kim * RETURN: Status 792a159c266SJung-uk Kim * 793a159c266SJung-uk Kim * DESCRIPTION: Restart a method that was preempted by another (nested) method 794a159c266SJung-uk Kim * invocation. Handle the return value (if any) from the callee. 795a159c266SJung-uk Kim * 796a159c266SJung-uk Kim ******************************************************************************/ 797a159c266SJung-uk Kim 798a159c266SJung-uk Kim ACPI_STATUS 799a159c266SJung-uk Kim AcpiDsRestartControlMethod ( 800a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState, 801a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *ReturnDesc) 802a159c266SJung-uk Kim { 803a159c266SJung-uk Kim ACPI_STATUS Status; 804a159c266SJung-uk Kim int SameAsImplicitReturn; 805a159c266SJung-uk Kim 806a159c266SJung-uk Kim 807a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState); 808a159c266SJung-uk Kim 809a159c266SJung-uk Kim 810a159c266SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 811a159c266SJung-uk Kim "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", 812a159c266SJung-uk Kim AcpiUtGetNodeName (WalkState->MethodNode), 813a159c266SJung-uk Kim WalkState->MethodCallOp, ReturnDesc)); 814a159c266SJung-uk Kim 815a159c266SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 816a159c266SJung-uk Kim " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", 817a159c266SJung-uk Kim WalkState->ReturnUsed, 818a159c266SJung-uk Kim WalkState->Results, WalkState)); 819a159c266SJung-uk Kim 820a159c266SJung-uk Kim /* Did the called method return a value? */ 821a159c266SJung-uk Kim 822a159c266SJung-uk Kim if (ReturnDesc) 823a159c266SJung-uk Kim { 824a159c266SJung-uk Kim /* Is the implicit return object the same as the return desc? */ 825a159c266SJung-uk Kim 826a159c266SJung-uk Kim SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc); 827a159c266SJung-uk Kim 828a159c266SJung-uk Kim /* Are we actually going to use the return value? */ 829a159c266SJung-uk Kim 830a159c266SJung-uk Kim if (WalkState->ReturnUsed) 831a159c266SJung-uk Kim { 832a159c266SJung-uk Kim /* Save the return value from the previous method */ 833a159c266SJung-uk Kim 834a159c266SJung-uk Kim Status = AcpiDsResultPush (ReturnDesc, WalkState); 835a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 836a159c266SJung-uk Kim { 837a159c266SJung-uk Kim AcpiUtRemoveReference (ReturnDesc); 838a159c266SJung-uk Kim return_ACPI_STATUS (Status); 839a159c266SJung-uk Kim } 840a159c266SJung-uk Kim 841a159c266SJung-uk Kim /* 842a159c266SJung-uk Kim * Save as THIS method's return value in case it is returned 843a159c266SJung-uk Kim * immediately to yet another method 844a159c266SJung-uk Kim */ 845a159c266SJung-uk Kim WalkState->ReturnDesc = ReturnDesc; 846a159c266SJung-uk Kim } 847a159c266SJung-uk Kim 848a159c266SJung-uk Kim /* 849a159c266SJung-uk Kim * The following code is the optional support for the so-called 850a159c266SJung-uk Kim * "implicit return". Some AML code assumes that the last value of the 851a159c266SJung-uk Kim * method is "implicitly" returned to the caller, in the absence of an 852a159c266SJung-uk Kim * explicit return value. 853a159c266SJung-uk Kim * 854a159c266SJung-uk Kim * Just save the last result of the method as the return value. 855a159c266SJung-uk Kim * 856a159c266SJung-uk Kim * NOTE: this is optional because the ASL language does not actually 857a159c266SJung-uk Kim * support this behavior. 858a159c266SJung-uk Kim */ 859a159c266SJung-uk Kim else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) || 860a159c266SJung-uk Kim SameAsImplicitReturn) 861a159c266SJung-uk Kim { 862a159c266SJung-uk Kim /* 863a159c266SJung-uk Kim * Delete the return value if it will not be used by the 864a159c266SJung-uk Kim * calling method or remove one reference if the explicit return 865a159c266SJung-uk Kim * is the same as the implicit return value. 866a159c266SJung-uk Kim */ 867a159c266SJung-uk Kim AcpiUtRemoveReference (ReturnDesc); 868a159c266SJung-uk Kim } 869a159c266SJung-uk Kim } 870a159c266SJung-uk Kim 871a159c266SJung-uk Kim return_ACPI_STATUS (AE_OK); 872a159c266SJung-uk Kim } 873a159c266SJung-uk Kim 874a159c266SJung-uk Kim 875a159c266SJung-uk Kim /******************************************************************************* 876a159c266SJung-uk Kim * 877a159c266SJung-uk Kim * FUNCTION: AcpiDsTerminateControlMethod 878a159c266SJung-uk Kim * 879a159c266SJung-uk Kim * PARAMETERS: MethodDesc - Method object 880a159c266SJung-uk Kim * WalkState - State associated with the method 881a159c266SJung-uk Kim * 882a159c266SJung-uk Kim * RETURN: None 883a159c266SJung-uk Kim * 884a159c266SJung-uk Kim * DESCRIPTION: Terminate a control method. Delete everything that the method 885a159c266SJung-uk Kim * created, delete all locals and arguments, and delete the parse 886a159c266SJung-uk Kim * tree if requested. 887a159c266SJung-uk Kim * 888a159c266SJung-uk Kim * MUTEX: Interpreter is locked 889a159c266SJung-uk Kim * 890a159c266SJung-uk Kim ******************************************************************************/ 891a159c266SJung-uk Kim 892a159c266SJung-uk Kim void 893a159c266SJung-uk Kim AcpiDsTerminateControlMethod ( 894a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *MethodDesc, 895a159c266SJung-uk Kim ACPI_WALK_STATE *WalkState) 896a159c266SJung-uk Kim { 897a159c266SJung-uk Kim 898a159c266SJung-uk Kim ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState); 899a159c266SJung-uk Kim 900a159c266SJung-uk Kim 901a159c266SJung-uk Kim /* MethodDesc is required, WalkState is optional */ 902a159c266SJung-uk Kim 903a159c266SJung-uk Kim if (!MethodDesc) 904a159c266SJung-uk Kim { 905a159c266SJung-uk Kim return_VOID; 906a159c266SJung-uk Kim } 907a159c266SJung-uk Kim 908a159c266SJung-uk Kim if (WalkState) 909a159c266SJung-uk Kim { 910a159c266SJung-uk Kim /* Delete all arguments and locals */ 911a159c266SJung-uk Kim 912a159c266SJung-uk Kim AcpiDsMethodDataDeleteAll (WalkState); 913a159c266SJung-uk Kim 914a159c266SJung-uk Kim /* 915a159c266SJung-uk Kim * Delete any namespace objects created anywhere within the 916a159c266SJung-uk Kim * namespace by the execution of this method. Unless: 917a159c266SJung-uk Kim * 1) This method is a module-level executable code method, in which 918a159c266SJung-uk Kim * case we want make the objects permanent. 919a159c266SJung-uk Kim * 2) There are other threads executing the method, in which case we 920a159c266SJung-uk Kim * will wait until the last thread has completed. 921a159c266SJung-uk Kim */ 922a159c266SJung-uk Kim if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) && 923a159c266SJung-uk Kim (MethodDesc->Method.ThreadCount == 1)) 924a159c266SJung-uk Kim { 925a159c266SJung-uk Kim /* Delete any direct children of (created by) this method */ 926a159c266SJung-uk Kim 927493deb39SJung-uk Kim (void) AcpiExExitInterpreter (); 928a159c266SJung-uk Kim AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode); 929493deb39SJung-uk Kim (void) AcpiExEnterInterpreter (); 930a159c266SJung-uk Kim 931a159c266SJung-uk Kim /* 932a159c266SJung-uk Kim * Delete any objects that were created by this method 933a159c266SJung-uk Kim * elsewhere in the namespace (if any were created). 934a159c266SJung-uk Kim * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the 935a159c266SJung-uk Kim * deletion such that we don't have to perform an entire 936a159c266SJung-uk Kim * namespace walk for every control method execution. 937a159c266SJung-uk Kim */ 938a159c266SJung-uk Kim if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE) 939a159c266SJung-uk Kim { 940493deb39SJung-uk Kim (void) AcpiExExitInterpreter (); 941a159c266SJung-uk Kim AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId); 942493deb39SJung-uk Kim (void) AcpiExEnterInterpreter (); 943f8146b88SJung-uk Kim MethodDesc->Method.InfoFlags &= 944f8146b88SJung-uk Kim ~ACPI_METHOD_MODIFIED_NAMESPACE; 945a159c266SJung-uk Kim } 946a159c266SJung-uk Kim } 9471cc50d6bSJung-uk Kim 9481cc50d6bSJung-uk Kim /* 9491cc50d6bSJung-uk Kim * If method is serialized, release the mutex and restore the 9501cc50d6bSJung-uk Kim * current sync level for this thread 9511cc50d6bSJung-uk Kim */ 9521cc50d6bSJung-uk Kim if (MethodDesc->Method.Mutex) 9531cc50d6bSJung-uk Kim { 9541cc50d6bSJung-uk Kim /* Acquisition Depth handles recursive calls */ 9551cc50d6bSJung-uk Kim 9561cc50d6bSJung-uk Kim MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--; 9571cc50d6bSJung-uk Kim if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth) 9581cc50d6bSJung-uk Kim { 9591cc50d6bSJung-uk Kim WalkState->Thread->CurrentSyncLevel = 9601cc50d6bSJung-uk Kim MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel; 9611cc50d6bSJung-uk Kim 9621cc50d6bSJung-uk Kim AcpiOsReleaseMutex ( 9631cc50d6bSJung-uk Kim MethodDesc->Method.Mutex->Mutex.OsMutex); 9641cc50d6bSJung-uk Kim MethodDesc->Method.Mutex->Mutex.ThreadId = 0; 9651cc50d6bSJung-uk Kim } 9661cc50d6bSJung-uk Kim } 967a159c266SJung-uk Kim } 968a159c266SJung-uk Kim 969a159c266SJung-uk Kim /* Decrement the thread count on the method */ 970a159c266SJung-uk Kim 971a159c266SJung-uk Kim if (MethodDesc->Method.ThreadCount) 972a159c266SJung-uk Kim { 973a159c266SJung-uk Kim MethodDesc->Method.ThreadCount--; 974a159c266SJung-uk Kim } 975a159c266SJung-uk Kim else 976a159c266SJung-uk Kim { 977a159c266SJung-uk Kim ACPI_ERROR ((AE_INFO, 978a159c266SJung-uk Kim "Invalid zero thread count in method")); 979a159c266SJung-uk Kim } 980a159c266SJung-uk Kim 981a159c266SJung-uk Kim /* Are there any other threads currently executing this method? */ 982a159c266SJung-uk Kim 983a159c266SJung-uk Kim if (MethodDesc->Method.ThreadCount) 984a159c266SJung-uk Kim { 985a159c266SJung-uk Kim /* 986a159c266SJung-uk Kim * Additional threads. Do not release the OwnerId in this case, 987a159c266SJung-uk Kim * we immediately reuse it for the next thread executing this method 988a159c266SJung-uk Kim */ 989a159c266SJung-uk Kim ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 990a159c266SJung-uk Kim "*** Completed execution of one thread, %u threads remaining\n", 991a159c266SJung-uk Kim MethodDesc->Method.ThreadCount)); 992a159c266SJung-uk Kim } 993a159c266SJung-uk Kim else 994a159c266SJung-uk Kim { 995a159c266SJung-uk Kim /* This is the only executing thread for this method */ 996a159c266SJung-uk Kim 997a159c266SJung-uk Kim /* 998a159c266SJung-uk Kim * Support to dynamically change a method from NotSerialized to 999a159c266SJung-uk Kim * Serialized if it appears that the method is incorrectly written and 1000a159c266SJung-uk Kim * does not support multiple thread execution. The best example of this 1001a159c266SJung-uk Kim * is if such a method creates namespace objects and blocks. A second 1002a159c266SJung-uk Kim * thread will fail with an AE_ALREADY_EXISTS exception. 1003a159c266SJung-uk Kim * 1004a159c266SJung-uk Kim * This code is here because we must wait until the last thread exits 1005a159c266SJung-uk Kim * before marking the method as serialized. 1006a159c266SJung-uk Kim */ 1007a159c266SJung-uk Kim if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING) 1008a159c266SJung-uk Kim { 1009a159c266SJung-uk Kim if (WalkState) 1010a159c266SJung-uk Kim { 1011f8146b88SJung-uk Kim ACPI_INFO (( 1012f8146b88SJung-uk Kim "Marking method %4.4s as Serialized " 1013f8146b88SJung-uk Kim "because of AE_ALREADY_EXISTS error", 1014a159c266SJung-uk Kim WalkState->MethodNode->Name.Ascii)); 1015a159c266SJung-uk Kim } 1016a159c266SJung-uk Kim 1017a159c266SJung-uk Kim /* 1018a159c266SJung-uk Kim * Method tried to create an object twice and was marked as 1019a159c266SJung-uk Kim * "pending serialized". The probable cause is that the method 1020a159c266SJung-uk Kim * cannot handle reentrancy. 1021a159c266SJung-uk Kim * 1022a159c266SJung-uk Kim * The method was created as NotSerialized, but it tried to create 1023a159c266SJung-uk Kim * a named object and then blocked, causing the second thread 1024a159c266SJung-uk Kim * entrance to begin and then fail. Workaround this problem by 1025a159c266SJung-uk Kim * marking the method permanently as Serialized when the last 1026a159c266SJung-uk Kim * thread exits here. 1027a159c266SJung-uk Kim */ 1028f8146b88SJung-uk Kim MethodDesc->Method.InfoFlags &= 1029f8146b88SJung-uk Kim ~ACPI_METHOD_SERIALIZED_PENDING; 1030f8146b88SJung-uk Kim 1031313a0c13SJung-uk Kim MethodDesc->Method.InfoFlags |= 1032313a0c13SJung-uk Kim (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL); 1033a159c266SJung-uk Kim MethodDesc->Method.SyncLevel = 0; 1034a159c266SJung-uk Kim } 1035a159c266SJung-uk Kim 1036a159c266SJung-uk Kim /* No more threads, we can free the OwnerId */ 1037a159c266SJung-uk Kim 1038a159c266SJung-uk Kim if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)) 1039a159c266SJung-uk Kim { 1040a159c266SJung-uk Kim AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId); 1041a159c266SJung-uk Kim } 1042a159c266SJung-uk Kim } 1043a159c266SJung-uk Kim 1044fe0f0bbbSJung-uk Kim AcpiExStopTraceMethod ((ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node, 1045fe0f0bbbSJung-uk Kim MethodDesc, WalkState); 1046fe0f0bbbSJung-uk Kim 1047a159c266SJung-uk Kim return_VOID; 1048a159c266SJung-uk Kim } 1049