xref: /freebsd/sys/contrib/dev/acpica/components/dispatcher/dsmethod.c (revision a159c266a93c3c4f229864954c5f963acd8f60f2)
1*a159c266SJung-uk Kim /******************************************************************************
2*a159c266SJung-uk Kim  *
3*a159c266SJung-uk Kim  * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
4*a159c266SJung-uk Kim  *
5*a159c266SJung-uk Kim  *****************************************************************************/
6*a159c266SJung-uk Kim 
7*a159c266SJung-uk Kim /*
8*a159c266SJung-uk Kim  * Copyright (C) 2000 - 2012, Intel Corp.
9*a159c266SJung-uk Kim  * All rights reserved.
10*a159c266SJung-uk Kim  *
11*a159c266SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
12*a159c266SJung-uk Kim  * modification, are permitted provided that the following conditions
13*a159c266SJung-uk Kim  * are met:
14*a159c266SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
15*a159c266SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
16*a159c266SJung-uk Kim  *    without modification.
17*a159c266SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*a159c266SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
19*a159c266SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
20*a159c266SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
21*a159c266SJung-uk Kim  *    binary redistribution.
22*a159c266SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
23*a159c266SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
24*a159c266SJung-uk Kim  *    from this software without specific prior written permission.
25*a159c266SJung-uk Kim  *
26*a159c266SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
27*a159c266SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
28*a159c266SJung-uk Kim  * Software Foundation.
29*a159c266SJung-uk Kim  *
30*a159c266SJung-uk Kim  * NO WARRANTY
31*a159c266SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*a159c266SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*a159c266SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*a159c266SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*a159c266SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*a159c266SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*a159c266SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*a159c266SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*a159c266SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*a159c266SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*a159c266SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
42*a159c266SJung-uk Kim  */
43*a159c266SJung-uk Kim 
44*a159c266SJung-uk Kim #define __DSMETHOD_C__
45*a159c266SJung-uk Kim 
46*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
47*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
48*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acdispat.h>
49*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acinterp.h>
50*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h>
51*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acdisasm.h>
52*a159c266SJung-uk Kim 
53*a159c266SJung-uk Kim 
54*a159c266SJung-uk Kim #define _COMPONENT          ACPI_DISPATCHER
55*a159c266SJung-uk Kim         ACPI_MODULE_NAME    ("dsmethod")
56*a159c266SJung-uk Kim 
57*a159c266SJung-uk Kim /* Local prototypes */
58*a159c266SJung-uk Kim 
59*a159c266SJung-uk Kim static ACPI_STATUS
60*a159c266SJung-uk Kim AcpiDsCreateMethodMutex (
61*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *MethodDesc);
62*a159c266SJung-uk Kim 
63*a159c266SJung-uk Kim 
64*a159c266SJung-uk Kim /*******************************************************************************
65*a159c266SJung-uk Kim  *
66*a159c266SJung-uk Kim  * FUNCTION:    AcpiDsMethodError
67*a159c266SJung-uk Kim  *
68*a159c266SJung-uk Kim  * PARAMETERS:  Status          - Execution status
69*a159c266SJung-uk Kim  *              WalkState       - Current state
70*a159c266SJung-uk Kim  *
71*a159c266SJung-uk Kim  * RETURN:      Status
72*a159c266SJung-uk Kim  *
73*a159c266SJung-uk Kim  * DESCRIPTION: Called on method error. Invoke the global exception handler if
74*a159c266SJung-uk Kim  *              present, dump the method data if the disassembler is configured
75*a159c266SJung-uk Kim  *
76*a159c266SJung-uk Kim  *              Note: Allows the exception handler to change the status code
77*a159c266SJung-uk Kim  *
78*a159c266SJung-uk Kim  ******************************************************************************/
79*a159c266SJung-uk Kim 
80*a159c266SJung-uk Kim ACPI_STATUS
81*a159c266SJung-uk Kim AcpiDsMethodError (
82*a159c266SJung-uk Kim     ACPI_STATUS             Status,
83*a159c266SJung-uk Kim     ACPI_WALK_STATE         *WalkState)
84*a159c266SJung-uk Kim {
85*a159c266SJung-uk Kim     ACPI_FUNCTION_ENTRY ();
86*a159c266SJung-uk Kim 
87*a159c266SJung-uk Kim 
88*a159c266SJung-uk Kim     /* Ignore AE_OK and control exception codes */
89*a159c266SJung-uk Kim 
90*a159c266SJung-uk Kim     if (ACPI_SUCCESS (Status) ||
91*a159c266SJung-uk Kim         (Status & AE_CODE_CONTROL))
92*a159c266SJung-uk Kim     {
93*a159c266SJung-uk Kim         return (Status);
94*a159c266SJung-uk Kim     }
95*a159c266SJung-uk Kim 
96*a159c266SJung-uk Kim     /* Invoke the global exception handler */
97*a159c266SJung-uk Kim 
98*a159c266SJung-uk Kim     if (AcpiGbl_ExceptionHandler)
99*a159c266SJung-uk Kim     {
100*a159c266SJung-uk Kim         /* Exit the interpreter, allow handler to execute methods */
101*a159c266SJung-uk Kim 
102*a159c266SJung-uk Kim         AcpiExExitInterpreter ();
103*a159c266SJung-uk Kim 
104*a159c266SJung-uk Kim         /*
105*a159c266SJung-uk Kim          * Handler can map the exception code to anything it wants, including
106*a159c266SJung-uk Kim          * AE_OK, in which case the executing method will not be aborted.
107*a159c266SJung-uk Kim          */
108*a159c266SJung-uk Kim         Status = AcpiGbl_ExceptionHandler (Status,
109*a159c266SJung-uk Kim                     WalkState->MethodNode ?
110*a159c266SJung-uk Kim                         WalkState->MethodNode->Name.Integer : 0,
111*a159c266SJung-uk Kim                     WalkState->Opcode, WalkState->AmlOffset, NULL);
112*a159c266SJung-uk Kim         AcpiExEnterInterpreter ();
113*a159c266SJung-uk Kim     }
114*a159c266SJung-uk Kim 
115*a159c266SJung-uk Kim     AcpiDsClearImplicitReturn (WalkState);
116*a159c266SJung-uk Kim 
117*a159c266SJung-uk Kim #ifdef ACPI_DISASSEMBLER
118*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
119*a159c266SJung-uk Kim     {
120*a159c266SJung-uk Kim         /* Display method locals/args if disassembler is present */
121*a159c266SJung-uk Kim 
122*a159c266SJung-uk Kim         AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op);
123*a159c266SJung-uk Kim     }
124*a159c266SJung-uk Kim #endif
125*a159c266SJung-uk Kim 
126*a159c266SJung-uk Kim     return (Status);
127*a159c266SJung-uk Kim }
128*a159c266SJung-uk Kim 
129*a159c266SJung-uk Kim 
130*a159c266SJung-uk Kim /*******************************************************************************
131*a159c266SJung-uk Kim  *
132*a159c266SJung-uk Kim  * FUNCTION:    AcpiDsCreateMethodMutex
133*a159c266SJung-uk Kim  *
134*a159c266SJung-uk Kim  * PARAMETERS:  ObjDesc             - The method object
135*a159c266SJung-uk Kim  *
136*a159c266SJung-uk Kim  * RETURN:      Status
137*a159c266SJung-uk Kim  *
138*a159c266SJung-uk Kim  * DESCRIPTION: Create a mutex object for a serialized control method
139*a159c266SJung-uk Kim  *
140*a159c266SJung-uk Kim  ******************************************************************************/
141*a159c266SJung-uk Kim 
142*a159c266SJung-uk Kim static ACPI_STATUS
143*a159c266SJung-uk Kim AcpiDsCreateMethodMutex (
144*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *MethodDesc)
145*a159c266SJung-uk Kim {
146*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *MutexDesc;
147*a159c266SJung-uk Kim     ACPI_STATUS             Status;
148*a159c266SJung-uk Kim 
149*a159c266SJung-uk Kim 
150*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (DsCreateMethodMutex);
151*a159c266SJung-uk Kim 
152*a159c266SJung-uk Kim 
153*a159c266SJung-uk Kim     /* Create the new mutex object */
154*a159c266SJung-uk Kim 
155*a159c266SJung-uk Kim     MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX);
156*a159c266SJung-uk Kim     if (!MutexDesc)
157*a159c266SJung-uk Kim     {
158*a159c266SJung-uk Kim         return_ACPI_STATUS (AE_NO_MEMORY);
159*a159c266SJung-uk Kim     }
160*a159c266SJung-uk Kim 
161*a159c266SJung-uk Kim     /* Create the actual OS Mutex */
162*a159c266SJung-uk Kim 
163*a159c266SJung-uk Kim     Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
164*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
165*a159c266SJung-uk Kim     {
166*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
167*a159c266SJung-uk Kim     }
168*a159c266SJung-uk Kim 
169*a159c266SJung-uk Kim     MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel;
170*a159c266SJung-uk Kim     MethodDesc->Method.Mutex = MutexDesc;
171*a159c266SJung-uk Kim     return_ACPI_STATUS (AE_OK);
172*a159c266SJung-uk Kim }
173*a159c266SJung-uk Kim 
174*a159c266SJung-uk Kim 
175*a159c266SJung-uk Kim /*******************************************************************************
176*a159c266SJung-uk Kim  *
177*a159c266SJung-uk Kim  * FUNCTION:    AcpiDsBeginMethodExecution
178*a159c266SJung-uk Kim  *
179*a159c266SJung-uk Kim  * PARAMETERS:  MethodNode          - Node of the method
180*a159c266SJung-uk Kim  *              ObjDesc             - The method object
181*a159c266SJung-uk Kim  *              WalkState           - current state, NULL if not yet executing
182*a159c266SJung-uk Kim  *                                    a method.
183*a159c266SJung-uk Kim  *
184*a159c266SJung-uk Kim  * RETURN:      Status
185*a159c266SJung-uk Kim  *
186*a159c266SJung-uk Kim  * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
187*a159c266SJung-uk Kim  *              increments the thread count, and waits at the method semaphore
188*a159c266SJung-uk Kim  *              for clearance to execute.
189*a159c266SJung-uk Kim  *
190*a159c266SJung-uk Kim  ******************************************************************************/
191*a159c266SJung-uk Kim 
192*a159c266SJung-uk Kim ACPI_STATUS
193*a159c266SJung-uk Kim AcpiDsBeginMethodExecution (
194*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *MethodNode,
195*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *ObjDesc,
196*a159c266SJung-uk Kim     ACPI_WALK_STATE         *WalkState)
197*a159c266SJung-uk Kim {
198*a159c266SJung-uk Kim     ACPI_STATUS             Status = AE_OK;
199*a159c266SJung-uk Kim 
200*a159c266SJung-uk Kim 
201*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode);
202*a159c266SJung-uk Kim 
203*a159c266SJung-uk Kim 
204*a159c266SJung-uk Kim     if (!MethodNode)
205*a159c266SJung-uk Kim     {
206*a159c266SJung-uk Kim         return_ACPI_STATUS (AE_NULL_ENTRY);
207*a159c266SJung-uk Kim     }
208*a159c266SJung-uk Kim 
209*a159c266SJung-uk Kim     /* Prevent wraparound of thread count */
210*a159c266SJung-uk Kim 
211*a159c266SJung-uk Kim     if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX)
212*a159c266SJung-uk Kim     {
213*a159c266SJung-uk Kim         ACPI_ERROR ((AE_INFO,
214*a159c266SJung-uk Kim             "Method reached maximum reentrancy limit (255)"));
215*a159c266SJung-uk Kim         return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
216*a159c266SJung-uk Kim     }
217*a159c266SJung-uk Kim 
218*a159c266SJung-uk Kim     /*
219*a159c266SJung-uk Kim      * If this method is serialized, we need to acquire the method mutex.
220*a159c266SJung-uk Kim      */
221*a159c266SJung-uk Kim     if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED)
222*a159c266SJung-uk Kim     {
223*a159c266SJung-uk Kim         /*
224*a159c266SJung-uk Kim          * Create a mutex for the method if it is defined to be Serialized
225*a159c266SJung-uk Kim          * and a mutex has not already been created. We defer the mutex creation
226*a159c266SJung-uk Kim          * until a method is actually executed, to minimize the object count
227*a159c266SJung-uk Kim          */
228*a159c266SJung-uk Kim         if (!ObjDesc->Method.Mutex)
229*a159c266SJung-uk Kim         {
230*a159c266SJung-uk Kim             Status = AcpiDsCreateMethodMutex (ObjDesc);
231*a159c266SJung-uk Kim             if (ACPI_FAILURE (Status))
232*a159c266SJung-uk Kim             {
233*a159c266SJung-uk Kim                 return_ACPI_STATUS (Status);
234*a159c266SJung-uk Kim             }
235*a159c266SJung-uk Kim         }
236*a159c266SJung-uk Kim 
237*a159c266SJung-uk Kim         /*
238*a159c266SJung-uk Kim          * The CurrentSyncLevel (per-thread) must be less than or equal to
239*a159c266SJung-uk Kim          * the sync level of the method. This mechanism provides some
240*a159c266SJung-uk Kim          * deadlock prevention
241*a159c266SJung-uk Kim          *
242*a159c266SJung-uk Kim          * Top-level method invocation has no walk state at this point
243*a159c266SJung-uk Kim          */
244*a159c266SJung-uk Kim         if (WalkState &&
245*a159c266SJung-uk Kim             (WalkState->Thread->CurrentSyncLevel > ObjDesc->Method.Mutex->Mutex.SyncLevel))
246*a159c266SJung-uk Kim         {
247*a159c266SJung-uk Kim             ACPI_ERROR ((AE_INFO,
248*a159c266SJung-uk Kim                 "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",
249*a159c266SJung-uk Kim                 AcpiUtGetNodeName (MethodNode),
250*a159c266SJung-uk Kim                 WalkState->Thread->CurrentSyncLevel));
251*a159c266SJung-uk Kim 
252*a159c266SJung-uk Kim             return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
253*a159c266SJung-uk Kim         }
254*a159c266SJung-uk Kim 
255*a159c266SJung-uk Kim         /*
256*a159c266SJung-uk Kim          * Obtain the method mutex if necessary. Do not acquire mutex for a
257*a159c266SJung-uk Kim          * recursive call.
258*a159c266SJung-uk Kim          */
259*a159c266SJung-uk Kim         if (!WalkState ||
260*a159c266SJung-uk Kim             !ObjDesc->Method.Mutex->Mutex.ThreadId ||
261*a159c266SJung-uk Kim             (WalkState->Thread->ThreadId != ObjDesc->Method.Mutex->Mutex.ThreadId))
262*a159c266SJung-uk Kim         {
263*a159c266SJung-uk Kim             /*
264*a159c266SJung-uk Kim              * Acquire the method mutex. This releases the interpreter if we
265*a159c266SJung-uk Kim              * block (and reacquires it before it returns)
266*a159c266SJung-uk Kim              */
267*a159c266SJung-uk Kim             Status = AcpiExSystemWaitMutex (ObjDesc->Method.Mutex->Mutex.OsMutex,
268*a159c266SJung-uk Kim                         ACPI_WAIT_FOREVER);
269*a159c266SJung-uk Kim             if (ACPI_FAILURE (Status))
270*a159c266SJung-uk Kim             {
271*a159c266SJung-uk Kim                 return_ACPI_STATUS (Status);
272*a159c266SJung-uk Kim             }
273*a159c266SJung-uk Kim 
274*a159c266SJung-uk Kim             /* Update the mutex and walk info and save the original SyncLevel */
275*a159c266SJung-uk Kim 
276*a159c266SJung-uk Kim             if (WalkState)
277*a159c266SJung-uk Kim             {
278*a159c266SJung-uk Kim                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
279*a159c266SJung-uk Kim                     WalkState->Thread->CurrentSyncLevel;
280*a159c266SJung-uk Kim 
281*a159c266SJung-uk Kim                 ObjDesc->Method.Mutex->Mutex.ThreadId = WalkState->Thread->ThreadId;
282*a159c266SJung-uk Kim                 WalkState->Thread->CurrentSyncLevel = ObjDesc->Method.SyncLevel;
283*a159c266SJung-uk Kim             }
284*a159c266SJung-uk Kim             else
285*a159c266SJung-uk Kim             {
286*a159c266SJung-uk Kim                 ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel =
287*a159c266SJung-uk Kim                     ObjDesc->Method.Mutex->Mutex.SyncLevel;
288*a159c266SJung-uk Kim             }
289*a159c266SJung-uk Kim         }
290*a159c266SJung-uk Kim 
291*a159c266SJung-uk Kim         /* Always increase acquisition depth */
292*a159c266SJung-uk Kim 
293*a159c266SJung-uk Kim         ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++;
294*a159c266SJung-uk Kim     }
295*a159c266SJung-uk Kim 
296*a159c266SJung-uk Kim     /*
297*a159c266SJung-uk Kim      * Allocate an Owner ID for this method, only if this is the first thread
298*a159c266SJung-uk Kim      * to begin concurrent execution. We only need one OwnerId, even if the
299*a159c266SJung-uk Kim      * method is invoked recursively.
300*a159c266SJung-uk Kim      */
301*a159c266SJung-uk Kim     if (!ObjDesc->Method.OwnerId)
302*a159c266SJung-uk Kim     {
303*a159c266SJung-uk Kim         Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId);
304*a159c266SJung-uk Kim         if (ACPI_FAILURE (Status))
305*a159c266SJung-uk Kim         {
306*a159c266SJung-uk Kim             goto Cleanup;
307*a159c266SJung-uk Kim         }
308*a159c266SJung-uk Kim     }
309*a159c266SJung-uk Kim 
310*a159c266SJung-uk Kim     /*
311*a159c266SJung-uk Kim      * Increment the method parse tree thread count since it has been
312*a159c266SJung-uk Kim      * reentered one more time (even if it is the same thread)
313*a159c266SJung-uk Kim      */
314*a159c266SJung-uk Kim     ObjDesc->Method.ThreadCount++;
315*a159c266SJung-uk Kim     AcpiMethodCount++;
316*a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
317*a159c266SJung-uk Kim 
318*a159c266SJung-uk Kim 
319*a159c266SJung-uk Kim Cleanup:
320*a159c266SJung-uk Kim     /* On error, must release the method mutex (if present) */
321*a159c266SJung-uk Kim 
322*a159c266SJung-uk Kim     if (ObjDesc->Method.Mutex)
323*a159c266SJung-uk Kim     {
324*a159c266SJung-uk Kim         AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex);
325*a159c266SJung-uk Kim     }
326*a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
327*a159c266SJung-uk Kim }
328*a159c266SJung-uk Kim 
329*a159c266SJung-uk Kim 
330*a159c266SJung-uk Kim /*******************************************************************************
331*a159c266SJung-uk Kim  *
332*a159c266SJung-uk Kim  * FUNCTION:    AcpiDsCallControlMethod
333*a159c266SJung-uk Kim  *
334*a159c266SJung-uk Kim  * PARAMETERS:  Thread              - Info for this thread
335*a159c266SJung-uk Kim  *              ThisWalkState       - Current walk state
336*a159c266SJung-uk Kim  *              Op                  - Current Op to be walked
337*a159c266SJung-uk Kim  *
338*a159c266SJung-uk Kim  * RETURN:      Status
339*a159c266SJung-uk Kim  *
340*a159c266SJung-uk Kim  * DESCRIPTION: Transfer execution to a called control method
341*a159c266SJung-uk Kim  *
342*a159c266SJung-uk Kim  ******************************************************************************/
343*a159c266SJung-uk Kim 
344*a159c266SJung-uk Kim ACPI_STATUS
345*a159c266SJung-uk Kim AcpiDsCallControlMethod (
346*a159c266SJung-uk Kim     ACPI_THREAD_STATE       *Thread,
347*a159c266SJung-uk Kim     ACPI_WALK_STATE         *ThisWalkState,
348*a159c266SJung-uk Kim     ACPI_PARSE_OBJECT       *Op)
349*a159c266SJung-uk Kim {
350*a159c266SJung-uk Kim     ACPI_STATUS             Status;
351*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *MethodNode;
352*a159c266SJung-uk Kim     ACPI_WALK_STATE         *NextWalkState = NULL;
353*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *ObjDesc;
354*a159c266SJung-uk Kim     ACPI_EVALUATE_INFO      *Info;
355*a159c266SJung-uk Kim     UINT32                  i;
356*a159c266SJung-uk Kim 
357*a159c266SJung-uk Kim 
358*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE_PTR (DsCallControlMethod, ThisWalkState);
359*a159c266SJung-uk Kim 
360*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n",
361*a159c266SJung-uk Kim         ThisWalkState->PrevOp, ThisWalkState));
362*a159c266SJung-uk Kim 
363*a159c266SJung-uk Kim     /*
364*a159c266SJung-uk Kim      * Get the namespace entry for the control method we are about to call
365*a159c266SJung-uk Kim      */
366*a159c266SJung-uk Kim     MethodNode = ThisWalkState->MethodCallNode;
367*a159c266SJung-uk Kim     if (!MethodNode)
368*a159c266SJung-uk Kim     {
369*a159c266SJung-uk Kim         return_ACPI_STATUS (AE_NULL_ENTRY);
370*a159c266SJung-uk Kim     }
371*a159c266SJung-uk Kim 
372*a159c266SJung-uk Kim     ObjDesc = AcpiNsGetAttachedObject (MethodNode);
373*a159c266SJung-uk Kim     if (!ObjDesc)
374*a159c266SJung-uk Kim     {
375*a159c266SJung-uk Kim         return_ACPI_STATUS (AE_NULL_OBJECT);
376*a159c266SJung-uk Kim     }
377*a159c266SJung-uk Kim 
378*a159c266SJung-uk Kim     /* Init for new method, possibly wait on method mutex */
379*a159c266SJung-uk Kim 
380*a159c266SJung-uk Kim     Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc,
381*a159c266SJung-uk Kim                 ThisWalkState);
382*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
383*a159c266SJung-uk Kim     {
384*a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
385*a159c266SJung-uk Kim     }
386*a159c266SJung-uk Kim 
387*a159c266SJung-uk Kim     /* Begin method parse/execution. Create a new walk state */
388*a159c266SJung-uk Kim 
389*a159c266SJung-uk Kim     NextWalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwnerId,
390*a159c266SJung-uk Kim                         NULL, ObjDesc, Thread);
391*a159c266SJung-uk Kim     if (!NextWalkState)
392*a159c266SJung-uk Kim     {
393*a159c266SJung-uk Kim         Status = AE_NO_MEMORY;
394*a159c266SJung-uk Kim         goto Cleanup;
395*a159c266SJung-uk Kim     }
396*a159c266SJung-uk Kim 
397*a159c266SJung-uk Kim     /*
398*a159c266SJung-uk Kim      * The resolved arguments were put on the previous walk state's operand
399*a159c266SJung-uk Kim      * stack. Operands on the previous walk state stack always
400*a159c266SJung-uk Kim      * start at index 0. Also, null terminate the list of arguments
401*a159c266SJung-uk Kim      */
402*a159c266SJung-uk Kim     ThisWalkState->Operands [ThisWalkState->NumOperands] = NULL;
403*a159c266SJung-uk Kim 
404*a159c266SJung-uk Kim     /*
405*a159c266SJung-uk Kim      * Allocate and initialize the evaluation information block
406*a159c266SJung-uk Kim      * TBD: this is somewhat inefficient, should change interface to
407*a159c266SJung-uk Kim      * DsInitAmlWalk. For now, keeps this struct off the CPU stack
408*a159c266SJung-uk Kim      */
409*a159c266SJung-uk Kim     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
410*a159c266SJung-uk Kim     if (!Info)
411*a159c266SJung-uk Kim     {
412*a159c266SJung-uk Kim         return_ACPI_STATUS (AE_NO_MEMORY);
413*a159c266SJung-uk Kim     }
414*a159c266SJung-uk Kim 
415*a159c266SJung-uk Kim     Info->Parameters = &ThisWalkState->Operands[0];
416*a159c266SJung-uk Kim 
417*a159c266SJung-uk Kim     Status = AcpiDsInitAmlWalk (NextWalkState, NULL, MethodNode,
418*a159c266SJung-uk Kim                 ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength,
419*a159c266SJung-uk Kim                 Info, ACPI_IMODE_EXECUTE);
420*a159c266SJung-uk Kim 
421*a159c266SJung-uk Kim     ACPI_FREE (Info);
422*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
423*a159c266SJung-uk Kim     {
424*a159c266SJung-uk Kim         goto Cleanup;
425*a159c266SJung-uk Kim     }
426*a159c266SJung-uk Kim 
427*a159c266SJung-uk Kim     /*
428*a159c266SJung-uk Kim      * Delete the operands on the previous walkstate operand stack
429*a159c266SJung-uk Kim      * (they were copied to new objects)
430*a159c266SJung-uk Kim      */
431*a159c266SJung-uk Kim     for (i = 0; i < ObjDesc->Method.ParamCount; i++)
432*a159c266SJung-uk Kim     {
433*a159c266SJung-uk Kim         AcpiUtRemoveReference (ThisWalkState->Operands [i]);
434*a159c266SJung-uk Kim         ThisWalkState->Operands [i] = NULL;
435*a159c266SJung-uk Kim     }
436*a159c266SJung-uk Kim 
437*a159c266SJung-uk Kim     /* Clear the operand stack */
438*a159c266SJung-uk Kim 
439*a159c266SJung-uk Kim     ThisWalkState->NumOperands = 0;
440*a159c266SJung-uk Kim 
441*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
442*a159c266SJung-uk Kim         "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
443*a159c266SJung-uk Kim         MethodNode->Name.Ascii, NextWalkState));
444*a159c266SJung-uk Kim 
445*a159c266SJung-uk Kim     /* Invoke an internal method if necessary */
446*a159c266SJung-uk Kim 
447*a159c266SJung-uk Kim     if (ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY)
448*a159c266SJung-uk Kim     {
449*a159c266SJung-uk Kim         Status = ObjDesc->Method.Dispatch.Implementation (NextWalkState);
450*a159c266SJung-uk Kim         if (Status == AE_OK)
451*a159c266SJung-uk Kim         {
452*a159c266SJung-uk Kim             Status = AE_CTRL_TERMINATE;
453*a159c266SJung-uk Kim         }
454*a159c266SJung-uk Kim     }
455*a159c266SJung-uk Kim 
456*a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
457*a159c266SJung-uk Kim 
458*a159c266SJung-uk Kim 
459*a159c266SJung-uk Kim Cleanup:
460*a159c266SJung-uk Kim 
461*a159c266SJung-uk Kim     /* On error, we must terminate the method properly */
462*a159c266SJung-uk Kim 
463*a159c266SJung-uk Kim     AcpiDsTerminateControlMethod (ObjDesc, NextWalkState);
464*a159c266SJung-uk Kim     if (NextWalkState)
465*a159c266SJung-uk Kim     {
466*a159c266SJung-uk Kim         AcpiDsDeleteWalkState (NextWalkState);
467*a159c266SJung-uk Kim     }
468*a159c266SJung-uk Kim 
469*a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
470*a159c266SJung-uk Kim }
471*a159c266SJung-uk Kim 
472*a159c266SJung-uk Kim 
473*a159c266SJung-uk Kim /*******************************************************************************
474*a159c266SJung-uk Kim  *
475*a159c266SJung-uk Kim  * FUNCTION:    AcpiDsRestartControlMethod
476*a159c266SJung-uk Kim  *
477*a159c266SJung-uk Kim  * PARAMETERS:  WalkState           - State for preempted method (caller)
478*a159c266SJung-uk Kim  *              ReturnDesc          - Return value from the called method
479*a159c266SJung-uk Kim  *
480*a159c266SJung-uk Kim  * RETURN:      Status
481*a159c266SJung-uk Kim  *
482*a159c266SJung-uk Kim  * DESCRIPTION: Restart a method that was preempted by another (nested) method
483*a159c266SJung-uk Kim  *              invocation.  Handle the return value (if any) from the callee.
484*a159c266SJung-uk Kim  *
485*a159c266SJung-uk Kim  ******************************************************************************/
486*a159c266SJung-uk Kim 
487*a159c266SJung-uk Kim ACPI_STATUS
488*a159c266SJung-uk Kim AcpiDsRestartControlMethod (
489*a159c266SJung-uk Kim     ACPI_WALK_STATE         *WalkState,
490*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *ReturnDesc)
491*a159c266SJung-uk Kim {
492*a159c266SJung-uk Kim     ACPI_STATUS             Status;
493*a159c266SJung-uk Kim     int                     SameAsImplicitReturn;
494*a159c266SJung-uk Kim 
495*a159c266SJung-uk Kim 
496*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState);
497*a159c266SJung-uk Kim 
498*a159c266SJung-uk Kim 
499*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
500*a159c266SJung-uk Kim         "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
501*a159c266SJung-uk Kim         AcpiUtGetNodeName (WalkState->MethodNode),
502*a159c266SJung-uk Kim         WalkState->MethodCallOp, ReturnDesc));
503*a159c266SJung-uk Kim 
504*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
505*a159c266SJung-uk Kim         "    ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
506*a159c266SJung-uk Kim         WalkState->ReturnUsed,
507*a159c266SJung-uk Kim         WalkState->Results, WalkState));
508*a159c266SJung-uk Kim 
509*a159c266SJung-uk Kim     /* Did the called method return a value? */
510*a159c266SJung-uk Kim 
511*a159c266SJung-uk Kim     if (ReturnDesc)
512*a159c266SJung-uk Kim     {
513*a159c266SJung-uk Kim         /* Is the implicit return object the same as the return desc? */
514*a159c266SJung-uk Kim 
515*a159c266SJung-uk Kim         SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc);
516*a159c266SJung-uk Kim 
517*a159c266SJung-uk Kim         /* Are we actually going to use the return value? */
518*a159c266SJung-uk Kim 
519*a159c266SJung-uk Kim         if (WalkState->ReturnUsed)
520*a159c266SJung-uk Kim         {
521*a159c266SJung-uk Kim             /* Save the return value from the previous method */
522*a159c266SJung-uk Kim 
523*a159c266SJung-uk Kim             Status = AcpiDsResultPush (ReturnDesc, WalkState);
524*a159c266SJung-uk Kim             if (ACPI_FAILURE (Status))
525*a159c266SJung-uk Kim             {
526*a159c266SJung-uk Kim                 AcpiUtRemoveReference (ReturnDesc);
527*a159c266SJung-uk Kim                 return_ACPI_STATUS (Status);
528*a159c266SJung-uk Kim             }
529*a159c266SJung-uk Kim 
530*a159c266SJung-uk Kim             /*
531*a159c266SJung-uk Kim              * Save as THIS method's return value in case it is returned
532*a159c266SJung-uk Kim              * immediately to yet another method
533*a159c266SJung-uk Kim              */
534*a159c266SJung-uk Kim             WalkState->ReturnDesc = ReturnDesc;
535*a159c266SJung-uk Kim         }
536*a159c266SJung-uk Kim 
537*a159c266SJung-uk Kim         /*
538*a159c266SJung-uk Kim          * The following code is the optional support for the so-called
539*a159c266SJung-uk Kim          * "implicit return". Some AML code assumes that the last value of the
540*a159c266SJung-uk Kim          * method is "implicitly" returned to the caller, in the absence of an
541*a159c266SJung-uk Kim          * explicit return value.
542*a159c266SJung-uk Kim          *
543*a159c266SJung-uk Kim          * Just save the last result of the method as the return value.
544*a159c266SJung-uk Kim          *
545*a159c266SJung-uk Kim          * NOTE: this is optional because the ASL language does not actually
546*a159c266SJung-uk Kim          * support this behavior.
547*a159c266SJung-uk Kim          */
548*a159c266SJung-uk Kim         else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) ||
549*a159c266SJung-uk Kim                  SameAsImplicitReturn)
550*a159c266SJung-uk Kim         {
551*a159c266SJung-uk Kim             /*
552*a159c266SJung-uk Kim              * Delete the return value if it will not be used by the
553*a159c266SJung-uk Kim              * calling method or remove one reference if the explicit return
554*a159c266SJung-uk Kim              * is the same as the implicit return value.
555*a159c266SJung-uk Kim              */
556*a159c266SJung-uk Kim             AcpiUtRemoveReference (ReturnDesc);
557*a159c266SJung-uk Kim         }
558*a159c266SJung-uk Kim     }
559*a159c266SJung-uk Kim 
560*a159c266SJung-uk Kim     return_ACPI_STATUS (AE_OK);
561*a159c266SJung-uk Kim }
562*a159c266SJung-uk Kim 
563*a159c266SJung-uk Kim 
564*a159c266SJung-uk Kim /*******************************************************************************
565*a159c266SJung-uk Kim  *
566*a159c266SJung-uk Kim  * FUNCTION:    AcpiDsTerminateControlMethod
567*a159c266SJung-uk Kim  *
568*a159c266SJung-uk Kim  * PARAMETERS:  MethodDesc          - Method object
569*a159c266SJung-uk Kim  *              WalkState           - State associated with the method
570*a159c266SJung-uk Kim  *
571*a159c266SJung-uk Kim  * RETURN:      None
572*a159c266SJung-uk Kim  *
573*a159c266SJung-uk Kim  * DESCRIPTION: Terminate a control method.  Delete everything that the method
574*a159c266SJung-uk Kim  *              created, delete all locals and arguments, and delete the parse
575*a159c266SJung-uk Kim  *              tree if requested.
576*a159c266SJung-uk Kim  *
577*a159c266SJung-uk Kim  * MUTEX:       Interpreter is locked
578*a159c266SJung-uk Kim  *
579*a159c266SJung-uk Kim  ******************************************************************************/
580*a159c266SJung-uk Kim 
581*a159c266SJung-uk Kim void
582*a159c266SJung-uk Kim AcpiDsTerminateControlMethod (
583*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *MethodDesc,
584*a159c266SJung-uk Kim     ACPI_WALK_STATE         *WalkState)
585*a159c266SJung-uk Kim {
586*a159c266SJung-uk Kim 
587*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);
588*a159c266SJung-uk Kim 
589*a159c266SJung-uk Kim 
590*a159c266SJung-uk Kim     /* MethodDesc is required, WalkState is optional */
591*a159c266SJung-uk Kim 
592*a159c266SJung-uk Kim     if (!MethodDesc)
593*a159c266SJung-uk Kim     {
594*a159c266SJung-uk Kim         return_VOID;
595*a159c266SJung-uk Kim     }
596*a159c266SJung-uk Kim 
597*a159c266SJung-uk Kim     if (WalkState)
598*a159c266SJung-uk Kim     {
599*a159c266SJung-uk Kim         /* Delete all arguments and locals */
600*a159c266SJung-uk Kim 
601*a159c266SJung-uk Kim         AcpiDsMethodDataDeleteAll (WalkState);
602*a159c266SJung-uk Kim 
603*a159c266SJung-uk Kim         /*
604*a159c266SJung-uk Kim          * If method is serialized, release the mutex and restore the
605*a159c266SJung-uk Kim          * current sync level for this thread
606*a159c266SJung-uk Kim          */
607*a159c266SJung-uk Kim         if (MethodDesc->Method.Mutex)
608*a159c266SJung-uk Kim         {
609*a159c266SJung-uk Kim             /* Acquisition Depth handles recursive calls */
610*a159c266SJung-uk Kim 
611*a159c266SJung-uk Kim             MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;
612*a159c266SJung-uk Kim             if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)
613*a159c266SJung-uk Kim             {
614*a159c266SJung-uk Kim                 WalkState->Thread->CurrentSyncLevel =
615*a159c266SJung-uk Kim                     MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;
616*a159c266SJung-uk Kim 
617*a159c266SJung-uk Kim                 AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex);
618*a159c266SJung-uk Kim                 MethodDesc->Method.Mutex->Mutex.ThreadId = 0;
619*a159c266SJung-uk Kim             }
620*a159c266SJung-uk Kim         }
621*a159c266SJung-uk Kim 
622*a159c266SJung-uk Kim         /*
623*a159c266SJung-uk Kim          * Delete any namespace objects created anywhere within the
624*a159c266SJung-uk Kim          * namespace by the execution of this method. Unless:
625*a159c266SJung-uk Kim          * 1) This method is a module-level executable code method, in which
626*a159c266SJung-uk Kim          *    case we want make the objects permanent.
627*a159c266SJung-uk Kim          * 2) There are other threads executing the method, in which case we
628*a159c266SJung-uk Kim          *    will wait until the last thread has completed.
629*a159c266SJung-uk Kim          */
630*a159c266SJung-uk Kim         if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) &&
631*a159c266SJung-uk Kim              (MethodDesc->Method.ThreadCount == 1))
632*a159c266SJung-uk Kim         {
633*a159c266SJung-uk Kim             /* Delete any direct children of (created by) this method */
634*a159c266SJung-uk Kim 
635*a159c266SJung-uk Kim             AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode);
636*a159c266SJung-uk Kim 
637*a159c266SJung-uk Kim             /*
638*a159c266SJung-uk Kim              * Delete any objects that were created by this method
639*a159c266SJung-uk Kim              * elsewhere in the namespace (if any were created).
640*a159c266SJung-uk Kim              * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
641*a159c266SJung-uk Kim              * deletion such that we don't have to perform an entire
642*a159c266SJung-uk Kim              * namespace walk for every control method execution.
643*a159c266SJung-uk Kim              */
644*a159c266SJung-uk Kim             if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE)
645*a159c266SJung-uk Kim             {
646*a159c266SJung-uk Kim                 AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId);
647*a159c266SJung-uk Kim                 MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_MODIFIED_NAMESPACE;
648*a159c266SJung-uk Kim             }
649*a159c266SJung-uk Kim         }
650*a159c266SJung-uk Kim     }
651*a159c266SJung-uk Kim 
652*a159c266SJung-uk Kim     /* Decrement the thread count on the method */
653*a159c266SJung-uk Kim 
654*a159c266SJung-uk Kim     if (MethodDesc->Method.ThreadCount)
655*a159c266SJung-uk Kim     {
656*a159c266SJung-uk Kim         MethodDesc->Method.ThreadCount--;
657*a159c266SJung-uk Kim     }
658*a159c266SJung-uk Kim     else
659*a159c266SJung-uk Kim     {
660*a159c266SJung-uk Kim         ACPI_ERROR ((AE_INFO,
661*a159c266SJung-uk Kim             "Invalid zero thread count in method"));
662*a159c266SJung-uk Kim     }
663*a159c266SJung-uk Kim 
664*a159c266SJung-uk Kim     /* Are there any other threads currently executing this method? */
665*a159c266SJung-uk Kim 
666*a159c266SJung-uk Kim     if (MethodDesc->Method.ThreadCount)
667*a159c266SJung-uk Kim     {
668*a159c266SJung-uk Kim         /*
669*a159c266SJung-uk Kim          * Additional threads. Do not release the OwnerId in this case,
670*a159c266SJung-uk Kim          * we immediately reuse it for the next thread executing this method
671*a159c266SJung-uk Kim          */
672*a159c266SJung-uk Kim         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
673*a159c266SJung-uk Kim             "*** Completed execution of one thread, %u threads remaining\n",
674*a159c266SJung-uk Kim             MethodDesc->Method.ThreadCount));
675*a159c266SJung-uk Kim     }
676*a159c266SJung-uk Kim     else
677*a159c266SJung-uk Kim     {
678*a159c266SJung-uk Kim         /* This is the only executing thread for this method */
679*a159c266SJung-uk Kim 
680*a159c266SJung-uk Kim         /*
681*a159c266SJung-uk Kim          * Support to dynamically change a method from NotSerialized to
682*a159c266SJung-uk Kim          * Serialized if it appears that the method is incorrectly written and
683*a159c266SJung-uk Kim          * does not support multiple thread execution. The best example of this
684*a159c266SJung-uk Kim          * is if such a method creates namespace objects and blocks. A second
685*a159c266SJung-uk Kim          * thread will fail with an AE_ALREADY_EXISTS exception.
686*a159c266SJung-uk Kim          *
687*a159c266SJung-uk Kim          * This code is here because we must wait until the last thread exits
688*a159c266SJung-uk Kim          * before marking the method as serialized.
689*a159c266SJung-uk Kim          */
690*a159c266SJung-uk Kim         if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING)
691*a159c266SJung-uk Kim         {
692*a159c266SJung-uk Kim             if (WalkState)
693*a159c266SJung-uk Kim             {
694*a159c266SJung-uk Kim                 ACPI_INFO ((AE_INFO,
695*a159c266SJung-uk Kim                     "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
696*a159c266SJung-uk Kim                     WalkState->MethodNode->Name.Ascii));
697*a159c266SJung-uk Kim             }
698*a159c266SJung-uk Kim 
699*a159c266SJung-uk Kim             /*
700*a159c266SJung-uk Kim              * Method tried to create an object twice and was marked as
701*a159c266SJung-uk Kim              * "pending serialized". The probable cause is that the method
702*a159c266SJung-uk Kim              * cannot handle reentrancy.
703*a159c266SJung-uk Kim              *
704*a159c266SJung-uk Kim              * The method was created as NotSerialized, but it tried to create
705*a159c266SJung-uk Kim              * a named object and then blocked, causing the second thread
706*a159c266SJung-uk Kim              * entrance to begin and then fail. Workaround this problem by
707*a159c266SJung-uk Kim              * marking the method permanently as Serialized when the last
708*a159c266SJung-uk Kim              * thread exits here.
709*a159c266SJung-uk Kim              */
710*a159c266SJung-uk Kim             MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_SERIALIZED_PENDING;
711*a159c266SJung-uk Kim             MethodDesc->Method.InfoFlags |= ACPI_METHOD_SERIALIZED;
712*a159c266SJung-uk Kim             MethodDesc->Method.SyncLevel = 0;
713*a159c266SJung-uk Kim         }
714*a159c266SJung-uk Kim 
715*a159c266SJung-uk Kim         /* No more threads, we can free the OwnerId */
716*a159c266SJung-uk Kim 
717*a159c266SJung-uk Kim         if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL))
718*a159c266SJung-uk Kim         {
719*a159c266SJung-uk Kim             AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
720*a159c266SJung-uk Kim         }
721*a159c266SJung-uk Kim     }
722*a159c266SJung-uk Kim 
723*a159c266SJung-uk Kim     return_VOID;
724*a159c266SJung-uk Kim }
725*a159c266SJung-uk Kim 
726*a159c266SJung-uk Kim 
727