1*bc36eafdSMike Gerdts /****************************************************************************** 2*bc36eafdSMike Gerdts * 3*bc36eafdSMike Gerdts * Module Name: evglock - Global Lock support 4*bc36eafdSMike Gerdts * 5*bc36eafdSMike Gerdts *****************************************************************************/ 6*bc36eafdSMike Gerdts 7*bc36eafdSMike Gerdts /* 8*bc36eafdSMike Gerdts * Copyright (C) 2000 - 2016, Intel Corp. 9*bc36eafdSMike Gerdts * All rights reserved. 10*bc36eafdSMike Gerdts * 11*bc36eafdSMike Gerdts * Redistribution and use in source and binary forms, with or without 12*bc36eafdSMike Gerdts * modification, are permitted provided that the following conditions 13*bc36eafdSMike Gerdts * are met: 14*bc36eafdSMike Gerdts * 1. Redistributions of source code must retain the above copyright 15*bc36eafdSMike Gerdts * notice, this list of conditions, and the following disclaimer, 16*bc36eafdSMike Gerdts * without modification. 17*bc36eafdSMike Gerdts * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18*bc36eafdSMike Gerdts * substantially similar to the "NO WARRANTY" disclaimer below 19*bc36eafdSMike Gerdts * ("Disclaimer") and any redistribution must be conditioned upon 20*bc36eafdSMike Gerdts * including a substantially similar Disclaimer requirement for further 21*bc36eafdSMike Gerdts * binary redistribution. 22*bc36eafdSMike Gerdts * 3. Neither the names of the above-listed copyright holders nor the names 23*bc36eafdSMike Gerdts * of any contributors may be used to endorse or promote products derived 24*bc36eafdSMike Gerdts * from this software without specific prior written permission. 25*bc36eafdSMike Gerdts * 26*bc36eafdSMike Gerdts * Alternatively, this software may be distributed under the terms of the 27*bc36eafdSMike Gerdts * GNU General Public License ("GPL") version 2 as published by the Free 28*bc36eafdSMike Gerdts * Software Foundation. 29*bc36eafdSMike Gerdts * 30*bc36eafdSMike Gerdts * NO WARRANTY 31*bc36eafdSMike Gerdts * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32*bc36eafdSMike Gerdts * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33*bc36eafdSMike Gerdts * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34*bc36eafdSMike Gerdts * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35*bc36eafdSMike Gerdts * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36*bc36eafdSMike Gerdts * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37*bc36eafdSMike Gerdts * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38*bc36eafdSMike Gerdts * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39*bc36eafdSMike Gerdts * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40*bc36eafdSMike Gerdts * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41*bc36eafdSMike Gerdts * POSSIBILITY OF SUCH DAMAGES. 42*bc36eafdSMike Gerdts */ 43*bc36eafdSMike Gerdts 44*bc36eafdSMike Gerdts #include "acpi.h" 45*bc36eafdSMike Gerdts #include "accommon.h" 46*bc36eafdSMike Gerdts #include "acevents.h" 47*bc36eafdSMike Gerdts #include "acinterp.h" 48*bc36eafdSMike Gerdts 49*bc36eafdSMike Gerdts #define _COMPONENT ACPI_EVENTS 50*bc36eafdSMike Gerdts ACPI_MODULE_NAME ("evglock") 51*bc36eafdSMike Gerdts 52*bc36eafdSMike Gerdts #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 53*bc36eafdSMike Gerdts 54*bc36eafdSMike Gerdts /* Local prototypes */ 55*bc36eafdSMike Gerdts 56*bc36eafdSMike Gerdts static UINT32 57*bc36eafdSMike Gerdts AcpiEvGlobalLockHandler ( 58*bc36eafdSMike Gerdts void *Context); 59*bc36eafdSMike Gerdts 60*bc36eafdSMike Gerdts 61*bc36eafdSMike Gerdts /******************************************************************************* 62*bc36eafdSMike Gerdts * 63*bc36eafdSMike Gerdts * FUNCTION: AcpiEvInitGlobalLockHandler 64*bc36eafdSMike Gerdts * 65*bc36eafdSMike Gerdts * PARAMETERS: None 66*bc36eafdSMike Gerdts * 67*bc36eafdSMike Gerdts * RETURN: Status 68*bc36eafdSMike Gerdts * 69*bc36eafdSMike Gerdts * DESCRIPTION: Install a handler for the global lock release event 70*bc36eafdSMike Gerdts * 71*bc36eafdSMike Gerdts ******************************************************************************/ 72*bc36eafdSMike Gerdts 73*bc36eafdSMike Gerdts ACPI_STATUS 74*bc36eafdSMike Gerdts AcpiEvInitGlobalLockHandler ( 75*bc36eafdSMike Gerdts void) 76*bc36eafdSMike Gerdts { 77*bc36eafdSMike Gerdts ACPI_STATUS Status; 78*bc36eafdSMike Gerdts 79*bc36eafdSMike Gerdts 80*bc36eafdSMike Gerdts ACPI_FUNCTION_TRACE (EvInitGlobalLockHandler); 81*bc36eafdSMike Gerdts 82*bc36eafdSMike Gerdts 83*bc36eafdSMike Gerdts /* If Hardware Reduced flag is set, there is no global lock */ 84*bc36eafdSMike Gerdts 85*bc36eafdSMike Gerdts if (AcpiGbl_ReducedHardware) 86*bc36eafdSMike Gerdts { 87*bc36eafdSMike Gerdts return_ACPI_STATUS (AE_OK); 88*bc36eafdSMike Gerdts } 89*bc36eafdSMike Gerdts 90*bc36eafdSMike Gerdts /* Attempt installation of the global lock handler */ 91*bc36eafdSMike Gerdts 92*bc36eafdSMike Gerdts Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, 93*bc36eafdSMike Gerdts AcpiEvGlobalLockHandler, NULL); 94*bc36eafdSMike Gerdts 95*bc36eafdSMike Gerdts /* 96*bc36eafdSMike Gerdts * If the global lock does not exist on this platform, the attempt to 97*bc36eafdSMike Gerdts * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). 98*bc36eafdSMike Gerdts * Map to AE_OK, but mark global lock as not present. Any attempt to 99*bc36eafdSMike Gerdts * actually use the global lock will be flagged with an error. 100*bc36eafdSMike Gerdts */ 101*bc36eafdSMike Gerdts AcpiGbl_GlobalLockPresent = FALSE; 102*bc36eafdSMike Gerdts if (Status == AE_NO_HARDWARE_RESPONSE) 103*bc36eafdSMike Gerdts { 104*bc36eafdSMike Gerdts ACPI_ERROR ((AE_INFO, 105*bc36eafdSMike Gerdts "No response from Global Lock hardware, disabling lock")); 106*bc36eafdSMike Gerdts 107*bc36eafdSMike Gerdts return_ACPI_STATUS (AE_OK); 108*bc36eafdSMike Gerdts } 109*bc36eafdSMike Gerdts 110*bc36eafdSMike Gerdts Status = AcpiOsCreateLock (&AcpiGbl_GlobalLockPendingLock); 111*bc36eafdSMike Gerdts if (ACPI_FAILURE (Status)) 112*bc36eafdSMike Gerdts { 113*bc36eafdSMike Gerdts return_ACPI_STATUS (Status); 114*bc36eafdSMike Gerdts } 115*bc36eafdSMike Gerdts 116*bc36eafdSMike Gerdts AcpiGbl_GlobalLockPending = FALSE; 117*bc36eafdSMike Gerdts AcpiGbl_GlobalLockPresent = TRUE; 118*bc36eafdSMike Gerdts return_ACPI_STATUS (Status); 119*bc36eafdSMike Gerdts } 120*bc36eafdSMike Gerdts 121*bc36eafdSMike Gerdts 122*bc36eafdSMike Gerdts /******************************************************************************* 123*bc36eafdSMike Gerdts * 124*bc36eafdSMike Gerdts * FUNCTION: AcpiEvRemoveGlobalLockHandler 125*bc36eafdSMike Gerdts * 126*bc36eafdSMike Gerdts * PARAMETERS: None 127*bc36eafdSMike Gerdts * 128*bc36eafdSMike Gerdts * RETURN: Status 129*bc36eafdSMike Gerdts * 130*bc36eafdSMike Gerdts * DESCRIPTION: Remove the handler for the Global Lock 131*bc36eafdSMike Gerdts * 132*bc36eafdSMike Gerdts ******************************************************************************/ 133*bc36eafdSMike Gerdts 134*bc36eafdSMike Gerdts ACPI_STATUS 135*bc36eafdSMike Gerdts AcpiEvRemoveGlobalLockHandler ( 136*bc36eafdSMike Gerdts void) 137*bc36eafdSMike Gerdts { 138*bc36eafdSMike Gerdts ACPI_STATUS Status; 139*bc36eafdSMike Gerdts 140*bc36eafdSMike Gerdts 141*bc36eafdSMike Gerdts ACPI_FUNCTION_TRACE (EvRemoveGlobalLockHandler); 142*bc36eafdSMike Gerdts 143*bc36eafdSMike Gerdts 144*bc36eafdSMike Gerdts AcpiGbl_GlobalLockPresent = FALSE; 145*bc36eafdSMike Gerdts Status = AcpiRemoveFixedEventHandler (ACPI_EVENT_GLOBAL, 146*bc36eafdSMike Gerdts AcpiEvGlobalLockHandler); 147*bc36eafdSMike Gerdts 148*bc36eafdSMike Gerdts AcpiOsDeleteLock (AcpiGbl_GlobalLockPendingLock); 149*bc36eafdSMike Gerdts return_ACPI_STATUS (Status); 150*bc36eafdSMike Gerdts } 151*bc36eafdSMike Gerdts 152*bc36eafdSMike Gerdts 153*bc36eafdSMike Gerdts /******************************************************************************* 154*bc36eafdSMike Gerdts * 155*bc36eafdSMike Gerdts * FUNCTION: AcpiEvGlobalLockHandler 156*bc36eafdSMike Gerdts * 157*bc36eafdSMike Gerdts * PARAMETERS: Context - From thread interface, not used 158*bc36eafdSMike Gerdts * 159*bc36eafdSMike Gerdts * RETURN: ACPI_INTERRUPT_HANDLED 160*bc36eafdSMike Gerdts * 161*bc36eafdSMike Gerdts * DESCRIPTION: Invoked directly from the SCI handler when a global lock 162*bc36eafdSMike Gerdts * release interrupt occurs. If there is actually a pending 163*bc36eafdSMike Gerdts * request for the lock, signal the waiting thread. 164*bc36eafdSMike Gerdts * 165*bc36eafdSMike Gerdts ******************************************************************************/ 166*bc36eafdSMike Gerdts 167*bc36eafdSMike Gerdts static UINT32 168*bc36eafdSMike Gerdts AcpiEvGlobalLockHandler ( 169*bc36eafdSMike Gerdts void *Context) 170*bc36eafdSMike Gerdts { 171*bc36eafdSMike Gerdts ACPI_STATUS Status; 172*bc36eafdSMike Gerdts ACPI_CPU_FLAGS Flags; 173*bc36eafdSMike Gerdts 174*bc36eafdSMike Gerdts 175*bc36eafdSMike Gerdts Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); 176*bc36eafdSMike Gerdts 177*bc36eafdSMike Gerdts /* 178*bc36eafdSMike Gerdts * If a request for the global lock is not actually pending, 179*bc36eafdSMike Gerdts * we are done. This handles "spurious" global lock interrupts 180*bc36eafdSMike Gerdts * which are possible (and have been seen) with bad BIOSs. 181*bc36eafdSMike Gerdts */ 182*bc36eafdSMike Gerdts if (!AcpiGbl_GlobalLockPending) 183*bc36eafdSMike Gerdts { 184*bc36eafdSMike Gerdts goto CleanupAndExit; 185*bc36eafdSMike Gerdts } 186*bc36eafdSMike Gerdts 187*bc36eafdSMike Gerdts /* 188*bc36eafdSMike Gerdts * Send a unit to the global lock semaphore. The actual acquisition 189*bc36eafdSMike Gerdts * of the global lock will be performed by the waiting thread. 190*bc36eafdSMike Gerdts */ 191*bc36eafdSMike Gerdts Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 1); 192*bc36eafdSMike Gerdts if (ACPI_FAILURE (Status)) 193*bc36eafdSMike Gerdts { 194*bc36eafdSMike Gerdts ACPI_ERROR ((AE_INFO, "Could not signal Global Lock semaphore")); 195*bc36eafdSMike Gerdts } 196*bc36eafdSMike Gerdts 197*bc36eafdSMike Gerdts AcpiGbl_GlobalLockPending = FALSE; 198*bc36eafdSMike Gerdts 199*bc36eafdSMike Gerdts 200*bc36eafdSMike Gerdts CleanupAndExit: 201*bc36eafdSMike Gerdts 202*bc36eafdSMike Gerdts AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); 203*bc36eafdSMike Gerdts return (ACPI_INTERRUPT_HANDLED); 204*bc36eafdSMike Gerdts } 205*bc36eafdSMike Gerdts 206*bc36eafdSMike Gerdts 207*bc36eafdSMike Gerdts /****************************************************************************** 208*bc36eafdSMike Gerdts * 209*bc36eafdSMike Gerdts * FUNCTION: AcpiEvAcquireGlobalLock 210*bc36eafdSMike Gerdts * 211*bc36eafdSMike Gerdts * PARAMETERS: Timeout - Max time to wait for the lock, in millisec. 212*bc36eafdSMike Gerdts * 213*bc36eafdSMike Gerdts * RETURN: Status 214*bc36eafdSMike Gerdts * 215*bc36eafdSMike Gerdts * DESCRIPTION: Attempt to gain ownership of the Global Lock. 216*bc36eafdSMike Gerdts * 217*bc36eafdSMike Gerdts * MUTEX: Interpreter must be locked 218*bc36eafdSMike Gerdts * 219*bc36eafdSMike Gerdts * Note: The original implementation allowed multiple threads to "acquire" the 220*bc36eafdSMike Gerdts * Global Lock, and the OS would hold the lock until the last thread had 221*bc36eafdSMike Gerdts * released it. However, this could potentially starve the BIOS out of the 222*bc36eafdSMike Gerdts * lock, especially in the case where there is a tight handshake between the 223*bc36eafdSMike Gerdts * Embedded Controller driver and the BIOS. Therefore, this implementation 224*bc36eafdSMike Gerdts * allows only one thread to acquire the HW Global Lock at a time, and makes 225*bc36eafdSMike Gerdts * the global lock appear as a standard mutex on the OS side. 226*bc36eafdSMike Gerdts * 227*bc36eafdSMike Gerdts *****************************************************************************/ 228*bc36eafdSMike Gerdts 229*bc36eafdSMike Gerdts ACPI_STATUS 230*bc36eafdSMike Gerdts AcpiEvAcquireGlobalLock ( 231*bc36eafdSMike Gerdts UINT16 Timeout) 232*bc36eafdSMike Gerdts { 233*bc36eafdSMike Gerdts ACPI_CPU_FLAGS Flags; 234*bc36eafdSMike Gerdts ACPI_STATUS Status; 235*bc36eafdSMike Gerdts BOOLEAN Acquired = FALSE; 236*bc36eafdSMike Gerdts 237*bc36eafdSMike Gerdts 238*bc36eafdSMike Gerdts ACPI_FUNCTION_TRACE (EvAcquireGlobalLock); 239*bc36eafdSMike Gerdts 240*bc36eafdSMike Gerdts 241*bc36eafdSMike Gerdts /* 242*bc36eafdSMike Gerdts * Only one thread can acquire the GL at a time, the GlobalLockMutex 243*bc36eafdSMike Gerdts * enforces this. This interface releases the interpreter if we must wait. 244*bc36eafdSMike Gerdts */ 245*bc36eafdSMike Gerdts Status = AcpiExSystemWaitMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex, 246*bc36eafdSMike Gerdts Timeout); 247*bc36eafdSMike Gerdts if (ACPI_FAILURE (Status)) 248*bc36eafdSMike Gerdts { 249*bc36eafdSMike Gerdts return_ACPI_STATUS (Status); 250*bc36eafdSMike Gerdts } 251*bc36eafdSMike Gerdts 252*bc36eafdSMike Gerdts /* 253*bc36eafdSMike Gerdts * Update the global lock handle and check for wraparound. The handle is 254*bc36eafdSMike Gerdts * only used for the external global lock interfaces, but it is updated 255*bc36eafdSMike Gerdts * here to properly handle the case where a single thread may acquire the 256*bc36eafdSMike Gerdts * lock via both the AML and the AcpiAcquireGlobalLock interfaces. The 257*bc36eafdSMike Gerdts * handle is therefore updated on the first acquire from a given thread 258*bc36eafdSMike Gerdts * regardless of where the acquisition request originated. 259*bc36eafdSMike Gerdts */ 260*bc36eafdSMike Gerdts AcpiGbl_GlobalLockHandle++; 261*bc36eafdSMike Gerdts if (AcpiGbl_GlobalLockHandle == 0) 262*bc36eafdSMike Gerdts { 263*bc36eafdSMike Gerdts AcpiGbl_GlobalLockHandle = 1; 264*bc36eafdSMike Gerdts } 265*bc36eafdSMike Gerdts 266*bc36eafdSMike Gerdts /* 267*bc36eafdSMike Gerdts * Make sure that a global lock actually exists. If not, just 268*bc36eafdSMike Gerdts * treat the lock as a standard mutex. 269*bc36eafdSMike Gerdts */ 270*bc36eafdSMike Gerdts if (!AcpiGbl_GlobalLockPresent) 271*bc36eafdSMike Gerdts { 272*bc36eafdSMike Gerdts AcpiGbl_GlobalLockAcquired = TRUE; 273*bc36eafdSMike Gerdts return_ACPI_STATUS (AE_OK); 274*bc36eafdSMike Gerdts } 275*bc36eafdSMike Gerdts 276*bc36eafdSMike Gerdts Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); 277*bc36eafdSMike Gerdts 278*bc36eafdSMike Gerdts do 279*bc36eafdSMike Gerdts { 280*bc36eafdSMike Gerdts /* Attempt to acquire the actual hardware lock */ 281*bc36eafdSMike Gerdts 282*bc36eafdSMike Gerdts ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired); 283*bc36eafdSMike Gerdts if (Acquired) 284*bc36eafdSMike Gerdts { 285*bc36eafdSMike Gerdts AcpiGbl_GlobalLockAcquired = TRUE; 286*bc36eafdSMike Gerdts ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 287*bc36eafdSMike Gerdts "Acquired hardware Global Lock\n")); 288*bc36eafdSMike Gerdts break; 289*bc36eafdSMike Gerdts } 290*bc36eafdSMike Gerdts 291*bc36eafdSMike Gerdts /* 292*bc36eafdSMike Gerdts * Did not get the lock. The pending bit was set above, and 293*bc36eafdSMike Gerdts * we must now wait until we receive the global lock 294*bc36eafdSMike Gerdts * released interrupt. 295*bc36eafdSMike Gerdts */ 296*bc36eafdSMike Gerdts AcpiGbl_GlobalLockPending = TRUE; 297*bc36eafdSMike Gerdts AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); 298*bc36eafdSMike Gerdts 299*bc36eafdSMike Gerdts ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 300*bc36eafdSMike Gerdts "Waiting for hardware Global Lock\n")); 301*bc36eafdSMike Gerdts 302*bc36eafdSMike Gerdts /* 303*bc36eafdSMike Gerdts * Wait for handshake with the global lock interrupt handler. 304*bc36eafdSMike Gerdts * This interface releases the interpreter if we must wait. 305*bc36eafdSMike Gerdts */ 306*bc36eafdSMike Gerdts Status = AcpiExSystemWaitSemaphore ( 307*bc36eafdSMike Gerdts AcpiGbl_GlobalLockSemaphore, ACPI_WAIT_FOREVER); 308*bc36eafdSMike Gerdts 309*bc36eafdSMike Gerdts Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); 310*bc36eafdSMike Gerdts 311*bc36eafdSMike Gerdts } while (ACPI_SUCCESS (Status)); 312*bc36eafdSMike Gerdts 313*bc36eafdSMike Gerdts AcpiGbl_GlobalLockPending = FALSE; 314*bc36eafdSMike Gerdts AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); 315*bc36eafdSMike Gerdts 316*bc36eafdSMike Gerdts return_ACPI_STATUS (Status); 317*bc36eafdSMike Gerdts } 318*bc36eafdSMike Gerdts 319*bc36eafdSMike Gerdts 320*bc36eafdSMike Gerdts /******************************************************************************* 321*bc36eafdSMike Gerdts * 322*bc36eafdSMike Gerdts * FUNCTION: AcpiEvReleaseGlobalLock 323*bc36eafdSMike Gerdts * 324*bc36eafdSMike Gerdts * PARAMETERS: None 325*bc36eafdSMike Gerdts * 326*bc36eafdSMike Gerdts * RETURN: Status 327*bc36eafdSMike Gerdts * 328*bc36eafdSMike Gerdts * DESCRIPTION: Releases ownership of the Global Lock. 329*bc36eafdSMike Gerdts * 330*bc36eafdSMike Gerdts ******************************************************************************/ 331*bc36eafdSMike Gerdts 332*bc36eafdSMike Gerdts ACPI_STATUS 333*bc36eafdSMike Gerdts AcpiEvReleaseGlobalLock ( 334*bc36eafdSMike Gerdts void) 335*bc36eafdSMike Gerdts { 336*bc36eafdSMike Gerdts BOOLEAN Pending = FALSE; 337*bc36eafdSMike Gerdts ACPI_STATUS Status = AE_OK; 338*bc36eafdSMike Gerdts 339*bc36eafdSMike Gerdts 340*bc36eafdSMike Gerdts ACPI_FUNCTION_TRACE (EvReleaseGlobalLock); 341*bc36eafdSMike Gerdts 342*bc36eafdSMike Gerdts 343*bc36eafdSMike Gerdts /* Lock must be already acquired */ 344*bc36eafdSMike Gerdts 345*bc36eafdSMike Gerdts if (!AcpiGbl_GlobalLockAcquired) 346*bc36eafdSMike Gerdts { 347*bc36eafdSMike Gerdts ACPI_WARNING ((AE_INFO, 348*bc36eafdSMike Gerdts "Cannot release the ACPI Global Lock, it has not been acquired")); 349*bc36eafdSMike Gerdts return_ACPI_STATUS (AE_NOT_ACQUIRED); 350*bc36eafdSMike Gerdts } 351*bc36eafdSMike Gerdts 352*bc36eafdSMike Gerdts if (AcpiGbl_GlobalLockPresent) 353*bc36eafdSMike Gerdts { 354*bc36eafdSMike Gerdts /* Allow any thread to release the lock */ 355*bc36eafdSMike Gerdts 356*bc36eafdSMike Gerdts ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_FACS, Pending); 357*bc36eafdSMike Gerdts 358*bc36eafdSMike Gerdts /* 359*bc36eafdSMike Gerdts * If the pending bit was set, we must write GBL_RLS to the control 360*bc36eafdSMike Gerdts * register 361*bc36eafdSMike Gerdts */ 362*bc36eafdSMike Gerdts if (Pending) 363*bc36eafdSMike Gerdts { 364*bc36eafdSMike Gerdts Status = AcpiWriteBitRegister ( 365*bc36eafdSMike Gerdts ACPI_BITREG_GLOBAL_LOCK_RELEASE, ACPI_ENABLE_EVENT); 366*bc36eafdSMike Gerdts } 367*bc36eafdSMike Gerdts 368*bc36eafdSMike Gerdts ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Released hardware Global Lock\n")); 369*bc36eafdSMike Gerdts } 370*bc36eafdSMike Gerdts 371*bc36eafdSMike Gerdts AcpiGbl_GlobalLockAcquired = FALSE; 372*bc36eafdSMike Gerdts 373*bc36eafdSMike Gerdts /* Release the local GL mutex */ 374*bc36eafdSMike Gerdts 375*bc36eafdSMike Gerdts AcpiOsReleaseMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex); 376*bc36eafdSMike Gerdts return_ACPI_STATUS (Status); 377*bc36eafdSMike Gerdts } 378*bc36eafdSMike Gerdts 379*bc36eafdSMike Gerdts #endif /* !ACPI_REDUCED_HARDWARE */ 380