diff options
Diffstat (limited to 'drivers/acpi/acpica/evmisc.c')
| -rw-r--r-- | drivers/acpi/acpica/evmisc.c | 94 | 
1 files changed, 55 insertions, 39 deletions
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index fcaed9fb44f..8e31bb5a973 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -284,41 +284,41 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)   * RETURN:      ACPI_INTERRUPT_HANDLED   *   * DESCRIPTION: Invoked directly from the SCI handler when a global lock - *              release interrupt occurs. Attempt to acquire the global lock, - *              if successful, signal the thread waiting for the lock. + *              release interrupt occurs.  If there's a thread waiting for + *              the global lock, signal it.   *   * NOTE: Assumes that the semaphore can be signaled from interrupt level. If   * this is not possible for some reason, a separate thread will have to be   * scheduled to do this.   *   ******************************************************************************/ +static u8 acpi_ev_global_lock_pending; +static spinlock_t _acpi_ev_global_lock_pending_lock; +#define acpi_ev_global_lock_pending_lock &_acpi_ev_global_lock_pending_lock  static u32 acpi_ev_global_lock_handler(void *context)  { -	u8 acquired = FALSE; +	acpi_status status; +	acpi_cpu_flags flags; -	/* -	 * Attempt to get the lock. -	 * -	 * If we don't get it now, it will be marked pending and we will -	 * take another interrupt when it becomes free. -	 */ -	ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); -	if (acquired) { +	flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock); -		/* Got the lock, now wake all threads waiting for it */ +	if (!acpi_ev_global_lock_pending) { +		goto out; +	} -		acpi_gbl_global_lock_acquired = TRUE; -		/* Send a unit to the semaphore */ +	/* Send a unit to the semaphore */ -		if (ACPI_FAILURE -		    (acpi_os_signal_semaphore -		     (acpi_gbl_global_lock_semaphore, 1))) { -			ACPI_ERROR((AE_INFO, -				    "Could not signal Global Lock semaphore")); -		} +	status = acpi_os_signal_semaphore(acpi_gbl_global_lock_semaphore, 1); +	if (ACPI_FAILURE(status)) { +		ACPI_ERROR((AE_INFO, "Could not signal Global Lock semaphore"));  	} +	acpi_ev_global_lock_pending = FALSE; + + out: +	acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags); +  	return (ACPI_INTERRUPT_HANDLED);  } @@ -415,6 +415,7 @@ static int acpi_ev_global_lock_acquired;  acpi_status acpi_ev_acquire_global_lock(u16 timeout)  { +	acpi_cpu_flags flags;  	acpi_status status = AE_OK;  	u8 acquired = FALSE; @@ -467,32 +468,47 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)  		return_ACPI_STATUS(AE_OK);  	} -	/* Attempt to acquire the actual hardware lock */ +	flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock); + +	do { + +		/* Attempt to acquire the actual hardware lock */ + +		ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); +		if (acquired) { +			acpi_gbl_global_lock_acquired = TRUE; + +			ACPI_DEBUG_PRINT((ACPI_DB_EXEC, +					  "Acquired hardware Global Lock\n")); +			break; +		} -	ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired); -	if (acquired) { +		acpi_ev_global_lock_pending = TRUE; -		/* We got the lock */ +		acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags); +		/* +		 * Did not get the lock. The pending bit was set above, and we +		 * must wait until we get the global lock released interrupt. +		 */  		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, -				  "Acquired hardware Global Lock\n")); +				  "Waiting for hardware Global Lock\n")); -		acpi_gbl_global_lock_acquired = TRUE; -		return_ACPI_STATUS(AE_OK); -	} +		/* +		 * Wait for handshake with the global lock interrupt handler. +		 * This interface releases the interpreter if we must wait. +		 */ +		status = acpi_ex_system_wait_semaphore( +						acpi_gbl_global_lock_semaphore, +						ACPI_WAIT_FOREVER); -	/* -	 * Did not get the lock. The pending bit was set above, and we must now -	 * wait until we get the global lock released interrupt. -	 */ -	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n")); +		flags = acpi_os_acquire_lock(acpi_ev_global_lock_pending_lock); -	/* -	 * Wait for handshake with the global lock interrupt handler. -	 * This interface releases the interpreter if we must wait. -	 */ -	status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore, -					       ACPI_WAIT_FOREVER); +	} while (ACPI_SUCCESS(status)); + +	acpi_ev_global_lock_pending = FALSE; + +	acpi_os_release_lock(acpi_ev_global_lock_pending_lock, flags);  	return_ACPI_STATUS(status);  }  |