diff options
| -rw-r--r-- | arch/powerpc/include/asm/hw_irq.h | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/irq.c | 48 | ||||
| -rw-r--r-- | arch/powerpc/mm/numa.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/platforms/cell/pervasive.c | 11 | ||||
| -rw-r--r-- | arch/powerpc/platforms/pseries/processor_idle.c | 17 | ||||
| -rw-r--r-- | drivers/tty/hvc/hvc_opal.c | 2 |
6 files changed, 69 insertions, 17 deletions
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 6eb75b80488c..0554ab062bdc 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
| @@ -86,8 +86,8 @@ static inline bool arch_irqs_disabled(void) | |||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | #ifdef CONFIG_PPC_BOOK3E | 88 | #ifdef CONFIG_PPC_BOOK3E |
| 89 | #define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory"); | 89 | #define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory") |
| 90 | #define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory"); | 90 | #define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory") |
| 91 | #else | 91 | #else |
| 92 | #define __hard_irq_enable() __mtmsrd(local_paca->kernel_msr | MSR_EE, 1) | 92 | #define __hard_irq_enable() __mtmsrd(local_paca->kernel_msr | MSR_EE, 1) |
| 93 | #define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1) | 93 | #define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1) |
| @@ -125,6 +125,8 @@ static inline bool arch_irq_disabled_regs(struct pt_regs *regs) | |||
| 125 | return !regs->softe; | 125 | return !regs->softe; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | extern bool prep_irq_for_idle(void); | ||
| 129 | |||
| 128 | #else /* CONFIG_PPC64 */ | 130 | #else /* CONFIG_PPC64 */ |
| 129 | 131 | ||
| 130 | #define SET_MSR_EE(x) mtmsr(x) | 132 | #define SET_MSR_EE(x) mtmsr(x) |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 1b415027ec0e..1f017bb7a7ce 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
| @@ -229,7 +229,7 @@ notrace void arch_local_irq_restore(unsigned long en) | |||
| 229 | */ | 229 | */ |
| 230 | if (unlikely(irq_happened != PACA_IRQ_HARD_DIS)) | 230 | if (unlikely(irq_happened != PACA_IRQ_HARD_DIS)) |
| 231 | __hard_irq_disable(); | 231 | __hard_irq_disable(); |
| 232 | #ifdef CONFIG_TRACE_IRQFLAG | 232 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 233 | else { | 233 | else { |
| 234 | /* | 234 | /* |
| 235 | * We should already be hard disabled here. We had bugs | 235 | * We should already be hard disabled here. We had bugs |
| @@ -286,6 +286,52 @@ void notrace restore_interrupts(void) | |||
| 286 | __hard_irq_enable(); | 286 | __hard_irq_enable(); |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | /* | ||
| 290 | * This is a helper to use when about to go into idle low-power | ||
| 291 | * when the latter has the side effect of re-enabling interrupts | ||
| 292 | * (such as calling H_CEDE under pHyp). | ||
| 293 | * | ||
| 294 | * You call this function with interrupts soft-disabled (this is | ||
| 295 | * already the case when ppc_md.power_save is called). The function | ||
| 296 | * will return whether to enter power save or just return. | ||
| 297 | * | ||
| 298 | * In the former case, it will have notified lockdep of interrupts | ||
| 299 | * being re-enabled and generally sanitized the lazy irq state, | ||
| 300 | * and in the latter case it will leave with interrupts hard | ||
| 301 | * disabled and marked as such, so the local_irq_enable() call | ||
| 302 | * in cpu_idle() will properly re-enable everything. | ||
| 303 | */ | ||
| 304 | bool prep_irq_for_idle(void) | ||
| 305 | { | ||
| 306 | /* | ||
| 307 | * First we need to hard disable to ensure no interrupt | ||
| 308 | * occurs before we effectively enter the low power state | ||
| 309 | */ | ||
| 310 | hard_irq_disable(); | ||
| 311 | |||
| 312 | /* | ||
| 313 | * If anything happened while we were soft-disabled, | ||
| 314 | * we return now and do not enter the low power state. | ||
| 315 | */ | ||
| 316 | if (lazy_irq_pending()) | ||
| 317 | return false; | ||
| 318 | |||
| 319 | /* Tell lockdep we are about to re-enable */ | ||
| 320 | trace_hardirqs_on(); | ||
| 321 | |||
| 322 | /* | ||
| 323 | * Mark interrupts as soft-enabled and clear the | ||
| 324 | * PACA_IRQ_HARD_DIS from the pending mask since we | ||
| 325 | * are about to hard enable as well as a side effect | ||
| 326 | * of entering the low power state. | ||
| 327 | */ | ||
| 328 | local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS; | ||
| 329 | local_paca->soft_enabled = 1; | ||
| 330 | |||
| 331 | /* Tell the caller to enter the low power state */ | ||
| 332 | return true; | ||
| 333 | } | ||
| 334 | |||
| 289 | #endif /* CONFIG_PPC64 */ | 335 | #endif /* CONFIG_PPC64 */ |
| 290 | 336 | ||
| 291 | int arch_show_interrupts(struct seq_file *p, int prec) | 337 | int arch_show_interrupts(struct seq_file *p, int prec) |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 6e8f677f5646..1e95556dc692 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
| @@ -639,7 +639,7 @@ static void __init parse_drconf_memory(struct device_node *memory) | |||
| 639 | unsigned int n, rc, ranges, is_kexec_kdump = 0; | 639 | unsigned int n, rc, ranges, is_kexec_kdump = 0; |
| 640 | unsigned long lmb_size, base, size, sz; | 640 | unsigned long lmb_size, base, size, sz; |
| 641 | int nid; | 641 | int nid; |
| 642 | struct assoc_arrays aa; | 642 | struct assoc_arrays aa = { .arrays = NULL }; |
| 643 | 643 | ||
| 644 | n = of_get_drconf_memory(memory, &dm); | 644 | n = of_get_drconf_memory(memory, &dm); |
| 645 | if (!n) | 645 | if (!n) |
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index efdacc829576..d17e98bc0c10 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c | |||
| @@ -42,11 +42,9 @@ static void cbe_power_save(void) | |||
| 42 | { | 42 | { |
| 43 | unsigned long ctrl, thread_switch_control; | 43 | unsigned long ctrl, thread_switch_control; |
| 44 | 44 | ||
| 45 | /* | 45 | /* Ensure our interrupt state is properly tracked */ |
| 46 | * We need to hard disable interrupts, the local_irq_enable() done by | 46 | if (!prep_irq_for_idle()) |
| 47 | * our caller upon return will hard re-enable. | 47 | return; |
| 48 | */ | ||
| 49 | hard_irq_disable(); | ||
| 50 | 48 | ||
| 51 | ctrl = mfspr(SPRN_CTRLF); | 49 | ctrl = mfspr(SPRN_CTRLF); |
| 52 | 50 | ||
| @@ -81,6 +79,9 @@ static void cbe_power_save(void) | |||
| 81 | */ | 79 | */ |
| 82 | ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); | 80 | ctrl &= ~(CTRL_RUNLATCH | CTRL_TE); |
| 83 | mtspr(SPRN_CTRLT, ctrl); | 81 | mtspr(SPRN_CTRLT, ctrl); |
| 82 | |||
| 83 | /* Re-enable interrupts in MSR */ | ||
| 84 | __hard_irq_enable(); | ||
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | static int cbe_system_reset_exception(struct pt_regs *regs) | 87 | static int cbe_system_reset_exception(struct pt_regs *regs) |
diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c index e61483e8e960..c71be66bd5dc 100644 --- a/arch/powerpc/platforms/pseries/processor_idle.c +++ b/arch/powerpc/platforms/pseries/processor_idle.c | |||
| @@ -99,15 +99,18 @@ out: | |||
| 99 | static void check_and_cede_processor(void) | 99 | static void check_and_cede_processor(void) |
| 100 | { | 100 | { |
| 101 | /* | 101 | /* |
| 102 | * Interrupts are soft-disabled at this point, | 102 | * Ensure our interrupt state is properly tracked, |
| 103 | * but not hard disabled. So an interrupt might have | 103 | * also checks if no interrupt has occurred while we |
| 104 | * occurred before entering NAP, and would be potentially | 104 | * were soft-disabled |
| 105 | * lost (edge events, decrementer events, etc...) unless | ||
| 106 | * we first hard disable then check. | ||
| 107 | */ | 105 | */ |
| 108 | hard_irq_disable(); | 106 | if (prep_irq_for_idle()) { |
| 109 | if (!lazy_irq_pending()) | ||
| 110 | cede_processor(); | 107 | cede_processor(); |
| 108 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 109 | /* Ensure that H_CEDE returns with IRQs on */ | ||
| 110 | if (WARN_ON(!(mfmsr() & MSR_EE))) | ||
| 111 | __hard_irq_enable(); | ||
| 112 | #endif | ||
| 113 | } | ||
| 111 | } | 114 | } |
| 112 | 115 | ||
| 113 | static int dedicated_cede_loop(struct cpuidle_device *dev, | 116 | static int dedicated_cede_loop(struct cpuidle_device *dev, |
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c index ced26c8ccd57..0d2ea0c224c3 100644 --- a/drivers/tty/hvc/hvc_opal.c +++ b/drivers/tty/hvc/hvc_opal.c | |||
| @@ -401,7 +401,7 @@ out: | |||
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL_RAW | 403 | #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL_RAW |
| 404 | void __init udbg_init_debug_opal(void) | 404 | void __init udbg_init_debug_opal_raw(void) |
| 405 | { | 405 | { |
| 406 | u32 index = CONFIG_PPC_EARLY_DEBUG_OPAL_VTERMNO; | 406 | u32 index = CONFIG_PPC_EARLY_DEBUG_OPAL_VTERMNO; |
| 407 | hvc_opal_privs[index] = &hvc_opal_boot_priv; | 407 | hvc_opal_privs[index] = &hvc_opal_boot_priv; |
