mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	ACPI / PM: Hold acpi_scan_lock over system PM transitions
Bad things happen if ACPI hotplug events are handled during system PM transitions, especially if devices are removed as a result. To prevent those bad things from happening, acquire acpi_scan_lock when a PM transition is started and release it when that transition is complete or has been aborted. This fixes resume lockup on my test-bed Acer Aspire S5 that happens when Thunderbolt devices are disconnected from the machine while suspended. Also fixes the analogous problem for Mika Westerberg on an Intel DZ77RE-75K board. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Toshi Kani <toshi.kani@hp.com>
This commit is contained in:
		
							parent
							
								
									1aaac07112
								
							
						
					
					
						commit
						ad07277e82
					
				
					 1 changed files with 24 additions and 15 deletions
				
			
		| 
						 | 
				
			
			@ -420,10 +420,21 @@ static void acpi_pm_finish(void)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *	acpi_pm_end - Finish up suspend sequence.
 | 
			
		||||
 * acpi_pm_start - Start system PM transition.
 | 
			
		||||
 */
 | 
			
		||||
static void acpi_pm_start(u32 acpi_state)
 | 
			
		||||
{
 | 
			
		||||
	acpi_target_sleep_state = acpi_state;
 | 
			
		||||
	acpi_sleep_tts_switch(acpi_target_sleep_state);
 | 
			
		||||
	acpi_scan_lock_acquire();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * acpi_pm_end - Finish up system PM transition.
 | 
			
		||||
 */
 | 
			
		||||
static void acpi_pm_end(void)
 | 
			
		||||
{
 | 
			
		||||
	acpi_scan_lock_release();
 | 
			
		||||
	/*
 | 
			
		||||
	 * This is necessary in case acpi_pm_finish() is not called during a
 | 
			
		||||
	 * failing transition to a sleep state.
 | 
			
		||||
| 
						 | 
				
			
			@ -451,21 +462,19 @@ static u32 acpi_suspend_states[] = {
 | 
			
		|||
static int acpi_suspend_begin(suspend_state_t pm_state)
 | 
			
		||||
{
 | 
			
		||||
	u32 acpi_state = acpi_suspend_states[pm_state];
 | 
			
		||||
	int error = 0;
 | 
			
		||||
	int error;
 | 
			
		||||
 | 
			
		||||
	error = (nvs_nosave || nvs_nosave_s3) ? 0 : suspend_nvs_alloc();
 | 
			
		||||
	if (error)
 | 
			
		||||
		return error;
 | 
			
		||||
 | 
			
		||||
	if (sleep_states[acpi_state]) {
 | 
			
		||||
		acpi_target_sleep_state = acpi_state;
 | 
			
		||||
		acpi_sleep_tts_switch(acpi_target_sleep_state);
 | 
			
		||||
	} else {
 | 
			
		||||
		printk(KERN_ERR "ACPI does not support this state: %d\n",
 | 
			
		||||
			pm_state);
 | 
			
		||||
		error = -ENOSYS;
 | 
			
		||||
	if (!sleep_states[acpi_state]) {
 | 
			
		||||
		pr_err("ACPI does not support sleep state S%u\n", acpi_state);
 | 
			
		||||
		return -ENOSYS;
 | 
			
		||||
	}
 | 
			
		||||
	return error;
 | 
			
		||||
 | 
			
		||||
	acpi_pm_start(acpi_state);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -631,10 +640,8 @@ static int acpi_hibernation_begin(void)
 | 
			
		|||
	int error;
 | 
			
		||||
 | 
			
		||||
	error = nvs_nosave ? 0 : suspend_nvs_alloc();
 | 
			
		||||
	if (!error) {
 | 
			
		||||
		acpi_target_sleep_state = ACPI_STATE_S4;
 | 
			
		||||
		acpi_sleep_tts_switch(acpi_target_sleep_state);
 | 
			
		||||
	}
 | 
			
		||||
	if (!error)
 | 
			
		||||
		acpi_pm_start(ACPI_STATE_S4);
 | 
			
		||||
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -713,8 +720,10 @@ static int acpi_hibernation_begin_old(void)
 | 
			
		|||
	if (!error) {
 | 
			
		||||
		if (!nvs_nosave)
 | 
			
		||||
			error = suspend_nvs_alloc();
 | 
			
		||||
		if (!error)
 | 
			
		||||
		if (!error) {
 | 
			
		||||
			acpi_target_sleep_state = ACPI_STATE_S4;
 | 
			
		||||
			acpi_scan_lock_acquire();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue