mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	xen: improve error handling in do_suspend.
The existing error handling has a few issues: - If freeze_processes() fails it exits with shutting_down = SHUTDOWN_SUSPEND. - If dpm_suspend_noirq() fails it exits without resuming xenbus. - If stop_machine() fails it exits without resuming xenbus or calling dpm_resume_end(). - xs_suspend()/xs_resume() and dpm_suspend_noirq()/dpm_resume_noirq() were not nested in the obvious way. Fix by ensuring each failure case goto's the correct label. Treat a failure of stop_machine() as a cancelled suspend in order to follow the correct resume path. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Cc: Stable Kernel <stable@kernel.org>
This commit is contained in:
		
							parent
							
								
									fed5ea87e0
								
							
						
					
					
						commit
						65f63384b3
					
				
					 1 changed files with 11 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -86,32 +86,32 @@ static void do_suspend(void)
 | 
			
		|||
	err = freeze_processes();
 | 
			
		||||
	if (err) {
 | 
			
		||||
		printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
 | 
			
		||||
		return;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	err = dpm_suspend_start(PMSG_SUSPEND);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
 | 
			
		||||
		goto out;
 | 
			
		||||
		goto out_thaw;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printk(KERN_DEBUG "suspending xenstore...\n");
 | 
			
		||||
	xs_suspend();
 | 
			
		||||
 | 
			
		||||
	err = dpm_suspend_noirq(PMSG_SUSPEND);
 | 
			
		||||
	if (err) {
 | 
			
		||||
		printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
 | 
			
		||||
		goto resume_devices;
 | 
			
		||||
		goto out_resume;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	printk(KERN_DEBUG "suspending xenstore...\n");
 | 
			
		||||
	xs_suspend();
 | 
			
		||||
 | 
			
		||||
	err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
 | 
			
		||||
 | 
			
		||||
	dpm_resume_noirq(PMSG_RESUME);
 | 
			
		||||
 | 
			
		||||
	if (err) {
 | 
			
		||||
		printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
 | 
			
		||||
		goto out;
 | 
			
		||||
		cancelled = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!cancelled) {
 | 
			
		||||
| 
						 | 
				
			
			@ -120,15 +120,17 @@ static void do_suspend(void)
 | 
			
		|||
	} else
 | 
			
		||||
		xs_suspend_cancel();
 | 
			
		||||
 | 
			
		||||
resume_devices:
 | 
			
		||||
out_resume:
 | 
			
		||||
	dpm_resume_end(PMSG_RESUME);
 | 
			
		||||
 | 
			
		||||
	/* Make sure timer events get retriggered on all CPUs */
 | 
			
		||||
	clock_was_set();
 | 
			
		||||
out:
 | 
			
		||||
 | 
			
		||||
out_thaw:
 | 
			
		||||
#ifdef CONFIG_PREEMPT
 | 
			
		||||
	thaw_processes();
 | 
			
		||||
#endif
 | 
			
		||||
out:
 | 
			
		||||
	shutting_down = SHUTDOWN_INVALID;
 | 
			
		||||
}
 | 
			
		||||
#endif	/* CONFIG_PM_SLEEP */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue