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 | |
| 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>
| -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; |
