aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 80c482382d5c..f438318ee800 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -59,12 +59,6 @@ struct threshold_block {
59 struct list_head miscj; 59 struct list_head miscj;
60}; 60};
61 61
62/* defaults used early on boot */
63static struct threshold_block threshold_defaults = {
64 .interrupt_enable = 0,
65 .threshold_limit = THRESHOLD_MAX,
66};
67
68struct threshold_bank { 62struct threshold_bank {
69 struct kobject *kobj; 63 struct kobject *kobj;
70 struct threshold_block *blocks; 64 struct threshold_block *blocks;
@@ -89,6 +83,8 @@ static void amd_threshold_interrupt(void);
89struct thresh_restart { 83struct thresh_restart {
90 struct threshold_block *b; 84 struct threshold_block *b;
91 int reset; 85 int reset;
86 int set_lvt_off;
87 int lvt_off;
92 u16 old_limit; 88 u16 old_limit;
93}; 89};
94 90
@@ -116,6 +112,12 @@ static void threshold_restart_bank(void *_tr)
116 (new_count & THRESHOLD_MAX); 112 (new_count & THRESHOLD_MAX);
117 } 113 }
118 114
115 if (tr->set_lvt_off) {
116 /* set new lvt offset */
117 mci_misc_hi &= ~MASK_LVTOFF_HI;
118 mci_misc_hi |= tr->lvt_off << 20;
119 }
120
119 tr->b->interrupt_enable ? 121 tr->b->interrupt_enable ?
120 (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) : 122 (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
121 (mci_misc_hi &= ~MASK_INT_TYPE_HI); 123 (mci_misc_hi &= ~MASK_INT_TYPE_HI);
@@ -124,13 +126,25 @@ static void threshold_restart_bank(void *_tr)
124 wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi); 126 wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
125} 127}
126 128
129static void mce_threshold_block_init(struct threshold_block *b, int offset)
130{
131 struct thresh_restart tr = {
132 .b = b,
133 .set_lvt_off = 1,
134 .lvt_off = offset,
135 };
136
137 b->threshold_limit = THRESHOLD_MAX;
138 threshold_restart_bank(&tr);
139};
140
127/* cpu init entry point, called from mce.c with preempt off */ 141/* cpu init entry point, called from mce.c with preempt off */
128void mce_amd_feature_init(struct cpuinfo_x86 *c) 142void mce_amd_feature_init(struct cpuinfo_x86 *c)
129{ 143{
144 struct threshold_block b;
130 unsigned int cpu = smp_processor_id(); 145 unsigned int cpu = smp_processor_id();
131 u32 low = 0, high = 0, address = 0; 146 u32 low = 0, high = 0, address = 0;
132 unsigned int bank, block; 147 unsigned int bank, block;
133 struct thresh_restart tr;
134 int lvt_off = -1; 148 int lvt_off = -1;
135 u8 offset; 149 u8 offset;
136 150
@@ -186,16 +200,13 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
186 continue; 200 continue;
187 } 201 }
188 202
189 high &= ~MASK_LVTOFF_HI; 203 memset(&b, 0, sizeof(b));
190 high |= lvt_off << 20; 204 b.cpu = cpu;
191 wrmsr(address, low, high); 205 b.bank = bank;
192 206 b.block = block;
193 threshold_defaults.address = address; 207 b.address = address;
194 tr.b = &threshold_defaults;
195 tr.reset = 0;
196 tr.old_limit = 0;
197 threshold_restart_bank(&tr);
198 208
209 mce_threshold_block_init(&b, offset);
199 mce_threshold_vector = amd_threshold_interrupt; 210 mce_threshold_vector = amd_threshold_interrupt;
200 } 211 }
201 } 212 }
@@ -298,9 +309,8 @@ store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size)
298 309
299 b->interrupt_enable = !!new; 310 b->interrupt_enable = !!new;
300 311
312 memset(&tr, 0, sizeof(tr));
301 tr.b = b; 313 tr.b = b;
302 tr.reset = 0;
303 tr.old_limit = 0;
304 314
305 smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); 315 smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
306 316
@@ -321,10 +331,10 @@ store_threshold_limit(struct threshold_block *b, const char *buf, size_t size)
321 if (new < 1) 331 if (new < 1)
322 new = 1; 332 new = 1;
323 333
334 memset(&tr, 0, sizeof(tr));
324 tr.old_limit = b->threshold_limit; 335 tr.old_limit = b->threshold_limit;
325 b->threshold_limit = new; 336 b->threshold_limit = new;
326 tr.b = b; 337 tr.b = b;
327 tr.reset = 0;
328 338
329 smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); 339 smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
330 340