diff options
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/pseries/processor_idle.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c index 085fd3f45ad..a12e95af693 100644 --- a/arch/powerpc/platforms/pseries/processor_idle.c +++ b/arch/powerpc/platforms/pseries/processor_idle.c | |||
@@ -96,6 +96,20 @@ out: | |||
96 | return index; | 96 | return index; |
97 | } | 97 | } |
98 | 98 | ||
99 | static void check_and_cede_processor(void) | ||
100 | { | ||
101 | /* | ||
102 | * Interrupts are soft-disabled at this point, | ||
103 | * but not hard disabled. So an interrupt might have | ||
104 | * occurred before entering NAP, and would be potentially | ||
105 | * lost (edge events, decrementer events, etc...) unless | ||
106 | * we first hard disable then check. | ||
107 | */ | ||
108 | hard_irq_disable(); | ||
109 | if (get_paca()->irq_happened == 0) | ||
110 | cede_processor(); | ||
111 | } | ||
112 | |||
99 | static int dedicated_cede_loop(struct cpuidle_device *dev, | 113 | static int dedicated_cede_loop(struct cpuidle_device *dev, |
100 | struct cpuidle_driver *drv, | 114 | struct cpuidle_driver *drv, |
101 | int index) | 115 | int index) |
@@ -108,7 +122,7 @@ static int dedicated_cede_loop(struct cpuidle_device *dev, | |||
108 | 122 | ||
109 | ppc64_runlatch_off(); | 123 | ppc64_runlatch_off(); |
110 | HMT_medium(); | 124 | HMT_medium(); |
111 | cede_processor(); | 125 | check_and_cede_processor(); |
112 | 126 | ||
113 | get_lppaca()->donate_dedicated_cpu = 0; | 127 | get_lppaca()->donate_dedicated_cpu = 0; |
114 | dev->last_residency = | 128 | dev->last_residency = |
@@ -132,7 +146,7 @@ static int shared_cede_loop(struct cpuidle_device *dev, | |||
132 | * processor. When returning here, external interrupts | 146 | * processor. When returning here, external interrupts |
133 | * are enabled. | 147 | * are enabled. |
134 | */ | 148 | */ |
135 | cede_processor(); | 149 | check_and_cede_processor(); |
136 | 150 | ||
137 | dev->last_residency = | 151 | dev->last_residency = |
138 | (int)idle_loop_epilog(in_purr, kt_before); | 152 | (int)idle_loop_epilog(in_purr, kt_before); |