| 
									
										
										
										
											2007-02-08 18:33:55 +11:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  Copyright 2006 Michael Ellerman, IBM Corporation | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version | 
					
						
							|  |  |  |  * 2 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-04 13:46:58 +10:00
										 |  |  | #include <linux/kernel.h>
 | 
					
						
							|  |  |  | #include <linux/interrupt.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-02-08 18:33:55 +11:00
										 |  |  | #include <asm/machdep.h>
 | 
					
						
							|  |  |  | #include <asm/page.h>
 | 
					
						
							|  |  |  | #include <asm/firmware.h>
 | 
					
						
							|  |  |  | #include <asm/kexec.h>
 | 
					
						
							|  |  |  | #include <asm/mpic.h>
 | 
					
						
							| 
									
										
										
										
											2011-04-04 13:46:58 +10:00
										 |  |  | #include <asm/xics.h>
 | 
					
						
							| 
									
										
										
										
											2007-05-10 22:17:18 +10:00
										 |  |  | #include <asm/smp.h>
 | 
					
						
							| 
									
										
										
										
											2007-02-08 18:33:55 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "pseries.h"
 | 
					
						
							|  |  |  | #include "plpar_wrappers.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Don't risk a hypervisor call if we're crashing */ | 
					
						
							|  |  |  | 	if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) { | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:32 +00:00
										 |  |  | 		int ret; | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:34 +00:00
										 |  |  | 		int cpu = smp_processor_id(); | 
					
						
							|  |  |  | 		int hwcpu = hard_smp_processor_id(); | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (get_lppaca()->dtl_enable_mask) { | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:34 +00:00
										 |  |  | 			ret = unregister_dtl(hwcpu); | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:32 +00:00
										 |  |  | 			if (ret) { | 
					
						
							|  |  |  | 				pr_err("WARNING: DTL deregistration for cpu " | 
					
						
							|  |  |  | 				       "%d (hw %d) failed with %d\n", | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:34 +00:00
										 |  |  | 				       cpu, hwcpu, ret); | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:32 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-02-08 18:33:55 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:34 +00:00
										 |  |  | 		ret = unregister_slb_shadow(hwcpu); | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:33 +00:00
										 |  |  | 		if (ret) { | 
					
						
							|  |  |  | 			pr_err("WARNING: SLB shadow buffer deregistration " | 
					
						
							|  |  |  | 			       "for cpu %d (hw %d) failed with %d\n", | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:34 +00:00
										 |  |  | 			       cpu, hwcpu, ret); | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:33 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-02-08 18:33:55 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:34 +00:00
										 |  |  | 		ret = unregister_vpa(hwcpu); | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:33 +00:00
										 |  |  | 		if (ret) { | 
					
						
							|  |  |  | 			pr_err("WARNING: VPA deregistration for cpu %d " | 
					
						
							| 
									
										
										
										
											2011-07-25 01:46:34 +00:00
										 |  |  | 			       "(hw %d) failed with %d\n", cpu, hwcpu, ret); | 
					
						
							| 
									
										
										
										
											2007-02-08 18:33:55 +11:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void pseries_kexec_cpu_down_mpic(int crash_shutdown, int secondary) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	pseries_kexec_cpu_down(crash_shutdown, secondary); | 
					
						
							|  |  |  | 	mpic_teardown_this_cpu(secondary); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void __init setup_kexec_cpu_down_mpic(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_mpic; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void pseries_kexec_cpu_down_xics(int crash_shutdown, int secondary) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	pseries_kexec_cpu_down(crash_shutdown, secondary); | 
					
						
							| 
									
										
										
										
											2008-02-07 07:37:31 +11:00
										 |  |  | 	xics_kexec_teardown_cpu(secondary); | 
					
						
							| 
									
										
										
										
											2007-02-08 18:33:55 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void __init setup_kexec_cpu_down_xics(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ppc_md.kexec_cpu_down = pseries_kexec_cpu_down_xics; | 
					
						
							|  |  |  | } |