aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index c5c003291861..1e8bb6c94f14 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -146,6 +146,27 @@ void mce_intel_hcpu_update(unsigned long cpu)
146 per_cpu(cmci_storm_state, cpu) = CMCI_STORM_NONE; 146 per_cpu(cmci_storm_state, cpu) = CMCI_STORM_NONE;
147} 147}
148 148
149static void cmci_toggle_interrupt_mode(bool on)
150{
151 unsigned long flags, *owned;
152 int bank;
153 u64 val;
154
155 raw_spin_lock_irqsave(&cmci_discover_lock, flags);
156 owned = this_cpu_ptr(mce_banks_owned);
157 for_each_set_bit(bank, owned, MAX_NR_BANKS) {
158 rdmsrl(MSR_IA32_MCx_CTL2(bank), val);
159
160 if (on)
161 val |= MCI_CTL2_CMCI_EN;
162 else
163 val &= ~MCI_CTL2_CMCI_EN;
164
165 wrmsrl(MSR_IA32_MCx_CTL2(bank), val);
166 }
167 raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
168}
169
149unsigned long cmci_intel_adjust_timer(unsigned long interval) 170unsigned long cmci_intel_adjust_timer(unsigned long interval)
150{ 171{
151 if ((this_cpu_read(cmci_backoff_cnt) > 0) && 172 if ((this_cpu_read(cmci_backoff_cnt) > 0) &&
@@ -175,7 +196,7 @@ unsigned long cmci_intel_adjust_timer(unsigned long interval)
175 */ 196 */
176 if (!atomic_read(&cmci_storm_on_cpus)) { 197 if (!atomic_read(&cmci_storm_on_cpus)) {
177 __this_cpu_write(cmci_storm_state, CMCI_STORM_NONE); 198 __this_cpu_write(cmci_storm_state, CMCI_STORM_NONE);
178 cmci_reenable(); 199 cmci_toggle_interrupt_mode(true);
179 cmci_recheck(); 200 cmci_recheck();
180 } 201 }
181 return CMCI_POLL_INTERVAL; 202 return CMCI_POLL_INTERVAL;
@@ -186,22 +207,6 @@ unsigned long cmci_intel_adjust_timer(unsigned long interval)
186 } 207 }
187} 208}
188 209
189static void cmci_storm_disable_banks(void)
190{
191 unsigned long flags, *owned;
192 int bank;
193 u64 val;
194
195 raw_spin_lock_irqsave(&cmci_discover_lock, flags);
196 owned = this_cpu_ptr(mce_banks_owned);
197 for_each_set_bit(bank, owned, MAX_NR_BANKS) {
198 rdmsrl(MSR_IA32_MCx_CTL2(bank), val);
199 val &= ~MCI_CTL2_CMCI_EN;
200 wrmsrl(MSR_IA32_MCx_CTL2(bank), val);
201 }
202 raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
203}
204
205static bool cmci_storm_detect(void) 210static bool cmci_storm_detect(void)
206{ 211{
207 unsigned int cnt = __this_cpu_read(cmci_storm_cnt); 212 unsigned int cnt = __this_cpu_read(cmci_storm_cnt);
@@ -223,7 +228,7 @@ static bool cmci_storm_detect(void)
223 if (cnt <= CMCI_STORM_THRESHOLD) 228 if (cnt <= CMCI_STORM_THRESHOLD)
224 return false; 229 return false;
225 230
226 cmci_storm_disable_banks(); 231 cmci_toggle_interrupt_mode(false);
227 __this_cpu_write(cmci_storm_state, CMCI_STORM_ACTIVE); 232 __this_cpu_write(cmci_storm_state, CMCI_STORM_ACTIVE);
228 r = atomic_add_return(1, &cmci_storm_on_cpus); 233 r = atomic_add_return(1, &cmci_storm_on_cpus);
229 mce_timer_kick(CMCI_STORM_INTERVAL); 234 mce_timer_kick(CMCI_STORM_INTERVAL);