diff options
author | Robert Richter <robert.richter@amd.com> | 2010-10-25 10:03:37 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-10-25 12:59:43 -0400 |
commit | bbaff08dca3c34d0fb6b4c4051354184e33e3df8 (patch) | |
tree | 3b08ed3ec89d079b634664bf131a0fbaa7868bca /arch | |
parent | 7203a0494084541575bac6dfc4e153f9e28869b8 (diff) |
mce, amd: Add helper functions to setup APIC
This patch reworks and cleans up mce_amd_feature_init() by
introducing helper functions to setup and check the LVT offset.
It also fixes line endings in pr_err() calls.
Signed-off-by: Robert Richter <robert.richter@amd.com>
Acked-by: Borislav Petkov <borislav.petkov@amd.com>
LKML-Reference: <1288015419-29543-4-git-send-email-robert.richter@amd.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_amd.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index eb771b9fc0cb..e316684f9ed7 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <asm/mce.h> | 31 | #include <asm/mce.h> |
32 | #include <asm/msr.h> | 32 | #include <asm/msr.h> |
33 | 33 | ||
34 | #define PFX "mce_threshold: " | ||
35 | #define VERSION "version 1.1.1" | ||
36 | #define NR_BANKS 6 | 34 | #define NR_BANKS 6 |
37 | #define NR_BLOCKS 9 | 35 | #define NR_BLOCKS 9 |
38 | #define THRESHOLD_MAX 0xFFF | 36 | #define THRESHOLD_MAX 0xFFF |
@@ -88,6 +86,27 @@ struct thresh_restart { | |||
88 | u16 old_limit; | 86 | u16 old_limit; |
89 | }; | 87 | }; |
90 | 88 | ||
89 | static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi) | ||
90 | { | ||
91 | int msr = (hi & MASK_LVTOFF_HI) >> 20; | ||
92 | |||
93 | if (apic < 0) { | ||
94 | pr_err(FW_BUG "cpu %d, failed to setup threshold interrupt " | ||
95 | "for bank %d, block %d (MSR%08X=0x%x%08x)\n", b->cpu, | ||
96 | b->bank, b->block, b->address, hi, lo); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | if (apic != msr) { | ||
101 | pr_err(FW_BUG "cpu %d, invalid threshold interrupt offset %d " | ||
102 | "for bank %d, block %d (MSR%08X=0x%x%08x)\n", | ||
103 | b->cpu, apic, b->bank, b->block, b->address, hi, lo); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | return 1; | ||
108 | }; | ||
109 | |||
91 | /* must be called with correct cpu affinity */ | 110 | /* must be called with correct cpu affinity */ |
92 | /* Called via smp_call_function_single() */ | 111 | /* Called via smp_call_function_single() */ |
93 | static void threshold_restart_bank(void *_tr) | 112 | static void threshold_restart_bank(void *_tr) |
@@ -113,9 +132,11 @@ static void threshold_restart_bank(void *_tr) | |||
113 | } | 132 | } |
114 | 133 | ||
115 | if (tr->set_lvt_off) { | 134 | if (tr->set_lvt_off) { |
116 | /* set new lvt offset */ | 135 | if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) { |
117 | hi &= ~MASK_LVTOFF_HI; | 136 | /* set new lvt offset */ |
118 | hi |= tr->lvt_off << 20; | 137 | hi &= ~MASK_LVTOFF_HI; |
138 | hi |= tr->lvt_off << 20; | ||
139 | } | ||
119 | } | 140 | } |
120 | 141 | ||
121 | tr->b->interrupt_enable ? | 142 | tr->b->interrupt_enable ? |
@@ -138,6 +159,15 @@ static void mce_threshold_block_init(struct threshold_block *b, int offset) | |||
138 | threshold_restart_bank(&tr); | 159 | threshold_restart_bank(&tr); |
139 | }; | 160 | }; |
140 | 161 | ||
162 | static int setup_APIC_mce(int reserved, int new) | ||
163 | { | ||
164 | if (reserved < 0 && !setup_APIC_eilvt(new, THRESHOLD_APIC_VECTOR, | ||
165 | APIC_EILVT_MSG_FIX, 0)) | ||
166 | return new; | ||
167 | |||
168 | return reserved; | ||
169 | } | ||
170 | |||
141 | /* cpu init entry point, called from mce.c with preempt off */ | 171 | /* cpu init entry point, called from mce.c with preempt off */ |
142 | void mce_amd_feature_init(struct cpuinfo_x86 *c) | 172 | void mce_amd_feature_init(struct cpuinfo_x86 *c) |
143 | { | 173 | { |
@@ -145,8 +175,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
145 | unsigned int cpu = smp_processor_id(); | 175 | unsigned int cpu = smp_processor_id(); |
146 | u32 low = 0, high = 0, address = 0; | 176 | u32 low = 0, high = 0, address = 0; |
147 | unsigned int bank, block; | 177 | unsigned int bank, block; |
148 | int lvt_off = -1; | 178 | int offset = -1; |
149 | u8 offset; | ||
150 | 179 | ||
151 | for (bank = 0; bank < NR_BANKS; ++bank) { | 180 | for (bank = 0; bank < NR_BANKS; ++bank) { |
152 | for (block = 0; block < NR_BLOCKS; ++block) { | 181 | for (block = 0; block < NR_BLOCKS; ++block) { |
@@ -177,28 +206,8 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
177 | if (shared_bank[bank] && c->cpu_core_id) | 206 | if (shared_bank[bank] && c->cpu_core_id) |
178 | break; | 207 | break; |
179 | #endif | 208 | #endif |
180 | offset = (high & MASK_LVTOFF_HI) >> 20; | 209 | offset = setup_APIC_mce(offset, |
181 | if (lvt_off < 0) { | 210 | (high & MASK_LVTOFF_HI) >> 20); |
182 | if (setup_APIC_eilvt(offset, | ||
183 | THRESHOLD_APIC_VECTOR, | ||
184 | APIC_EILVT_MSG_FIX, 0)) { | ||
185 | pr_err(FW_BUG "cpu %d, failed to " | ||
186 | "setup threshold interrupt " | ||
187 | "for bank %d, block %d " | ||
188 | "(MSR%08X=0x%x%08x)", | ||
189 | smp_processor_id(), bank, block, | ||
190 | address, high, low); | ||
191 | continue; | ||
192 | } | ||
193 | lvt_off = offset; | ||
194 | } else if (lvt_off != offset) { | ||
195 | pr_err(FW_BUG "cpu %d, invalid threshold " | ||
196 | "interrupt offset %d for bank %d," | ||
197 | "block %d (MSR%08X=0x%x%08x)", | ||
198 | smp_processor_id(), lvt_off, bank, | ||
199 | block, address, high, low); | ||
200 | continue; | ||
201 | } | ||
202 | 211 | ||
203 | memset(&b, 0, sizeof(b)); | 212 | memset(&b, 0, sizeof(b)); |
204 | b.cpu = cpu; | 213 | b.cpu = cpu; |