diff options
| author | Mike Travis <travis@sgi.com> | 2008-12-16 20:34:04 -0500 |
|---|---|---|
| committer | Mike Travis <travis@sgi.com> | 2008-12-16 20:40:59 -0500 |
| commit | 4cd4601d592d07b26e4b7d2bb8fcd55bbfd6cf6e (patch) | |
| tree | e06f3a0b1e861a2b84c2cb44469020d7f1e4d49d | |
| parent | b2bb85549134c005e997e5a7ed303bda6a1ae738 (diff) | |
x86: use work_on_cpu in x86/kernel/cpu/mcheck/mce_amd_64.c
Impact: Remove cpumask_t's from stack.
Simple transition to work_on_cpu(), rather than cpumask games.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Mike Travis <travis@sgi.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Robert Richter <robert.richter@amd.com>
Cc: jacob.shin@amd.com
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/mce_amd_64.c | 108 |
1 files changed, 55 insertions, 53 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index 5eb390a4b2e9..a1de80f368f1 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c | |||
| @@ -83,34 +83,41 @@ static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */ | |||
| 83 | * CPU Initialization | 83 | * CPU Initialization |
| 84 | */ | 84 | */ |
| 85 | 85 | ||
| 86 | struct thresh_restart { | ||
| 87 | struct threshold_block *b; | ||
| 88 | int reset; | ||
| 89 | u16 old_limit; | ||
| 90 | }; | ||
| 91 | |||
| 86 | /* must be called with correct cpu affinity */ | 92 | /* must be called with correct cpu affinity */ |
| 87 | static void threshold_restart_bank(struct threshold_block *b, | 93 | static long threshold_restart_bank(void *_tr) |
| 88 | int reset, u16 old_limit) | ||
| 89 | { | 94 | { |
| 95 | struct thresh_restart *tr = _tr; | ||
| 90 | u32 mci_misc_hi, mci_misc_lo; | 96 | u32 mci_misc_hi, mci_misc_lo; |
| 91 | 97 | ||
| 92 | rdmsr(b->address, mci_misc_lo, mci_misc_hi); | 98 | rdmsr(tr->b->address, mci_misc_lo, mci_misc_hi); |
| 93 | 99 | ||
| 94 | if (b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX)) | 100 | if (tr->b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX)) |
| 95 | reset = 1; /* limit cannot be lower than err count */ | 101 | tr->reset = 1; /* limit cannot be lower than err count */ |
| 96 | 102 | ||
| 97 | if (reset) { /* reset err count and overflow bit */ | 103 | if (tr->reset) { /* reset err count and overflow bit */ |
| 98 | mci_misc_hi = | 104 | mci_misc_hi = |
| 99 | (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) | | 105 | (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) | |
| 100 | (THRESHOLD_MAX - b->threshold_limit); | 106 | (THRESHOLD_MAX - tr->b->threshold_limit); |
| 101 | } else if (old_limit) { /* change limit w/o reset */ | 107 | } else if (tr->old_limit) { /* change limit w/o reset */ |
| 102 | int new_count = (mci_misc_hi & THRESHOLD_MAX) + | 108 | int new_count = (mci_misc_hi & THRESHOLD_MAX) + |
| 103 | (old_limit - b->threshold_limit); | 109 | (tr->old_limit - tr->b->threshold_limit); |
| 104 | mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) | | 110 | mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) | |
| 105 | (new_count & THRESHOLD_MAX); | 111 | (new_count & THRESHOLD_MAX); |
| 106 | } | 112 | } |
| 107 | 113 | ||
| 108 | b->interrupt_enable ? | 114 | tr->b->interrupt_enable ? |
| 109 | (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) : | 115 | (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) : |
| 110 | (mci_misc_hi &= ~MASK_INT_TYPE_HI); | 116 | (mci_misc_hi &= ~MASK_INT_TYPE_HI); |
| 111 | 117 | ||
| 112 | mci_misc_hi |= MASK_COUNT_EN_HI; | 118 | mci_misc_hi |= MASK_COUNT_EN_HI; |
| 113 | wrmsr(b->address, mci_misc_lo, mci_misc_hi); | 119 | wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi); |
| 120 | return 0; | ||
| 114 | } | 121 | } |
| 115 | 122 | ||
| 116 | /* cpu init entry point, called from mce.c with preempt off */ | 123 | /* cpu init entry point, called from mce.c with preempt off */ |
| @@ -120,6 +127,7 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
| 120 | unsigned int cpu = smp_processor_id(); | 127 | unsigned int cpu = smp_processor_id(); |
| 121 | u8 lvt_off; | 128 | u8 lvt_off; |
| 122 | u32 low = 0, high = 0, address = 0; | 129 | u32 low = 0, high = 0, address = 0; |
| 130 | struct thresh_restart tr; | ||
| 123 | 131 | ||
| 124 | for (bank = 0; bank < NR_BANKS; ++bank) { | 132 | for (bank = 0; bank < NR_BANKS; ++bank) { |
| 125 | for (block = 0; block < NR_BLOCKS; ++block) { | 133 | for (block = 0; block < NR_BLOCKS; ++block) { |
| @@ -162,7 +170,10 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
| 162 | wrmsr(address, low, high); | 170 | wrmsr(address, low, high); |
| 163 | 171 | ||
| 164 | threshold_defaults.address = address; | 172 | threshold_defaults.address = address; |
| 165 | threshold_restart_bank(&threshold_defaults, 0, 0); | 173 | tr.b = &threshold_defaults; |
| 174 | tr.reset = 0; | ||
| 175 | tr.old_limit = 0; | ||
| 176 | threshold_restart_bank(&tr); | ||
| 166 | } | 177 | } |
| 167 | } | 178 | } |
| 168 | } | 179 | } |
| @@ -251,20 +262,6 @@ struct threshold_attr { | |||
| 251 | ssize_t(*store) (struct threshold_block *, const char *, size_t count); | 262 | ssize_t(*store) (struct threshold_block *, const char *, size_t count); |
| 252 | }; | 263 | }; |
| 253 | 264 | ||
| 254 | static void affinity_set(unsigned int cpu, cpumask_t *oldmask, | ||
| 255 | cpumask_t *newmask) | ||
| 256 | { | ||
| 257 | *oldmask = current->cpus_allowed; | ||
| 258 | cpus_clear(*newmask); | ||
| 259 | cpu_set(cpu, *newmask); | ||
| 260 | set_cpus_allowed_ptr(current, newmask); | ||
| 261 | } | ||
| 262 | |||
| 263 | static void affinity_restore(const cpumask_t *oldmask) | ||
| 264 | { | ||
| 265 | set_cpus_allowed_ptr(current, oldmask); | ||
| 266 | } | ||
| 267 | |||
| 268 | #define SHOW_FIELDS(name) \ | 265 | #define SHOW_FIELDS(name) \ |
| 269 | static ssize_t show_ ## name(struct threshold_block * b, char *buf) \ | 266 | static ssize_t show_ ## name(struct threshold_block * b, char *buf) \ |
| 270 | { \ | 267 | { \ |
| @@ -277,15 +274,16 @@ static ssize_t store_interrupt_enable(struct threshold_block *b, | |||
| 277 | const char *buf, size_t count) | 274 | const char *buf, size_t count) |
| 278 | { | 275 | { |
| 279 | char *end; | 276 | char *end; |
| 280 | cpumask_t oldmask, newmask; | 277 | struct thresh_restart tr; |
| 281 | unsigned long new = simple_strtoul(buf, &end, 0); | 278 | unsigned long new = simple_strtoul(buf, &end, 0); |
| 282 | if (end == buf) | 279 | if (end == buf) |
| 283 | return -EINVAL; | 280 | return -EINVAL; |
| 284 | b->interrupt_enable = !!new; | 281 | b->interrupt_enable = !!new; |
| 285 | 282 | ||
| 286 | affinity_set(b->cpu, &oldmask, &newmask); | 283 | tr.b = b; |
| 287 | threshold_restart_bank(b, 0, 0); | 284 | tr.reset = 0; |
| 288 | affinity_restore(&oldmask); | 285 | tr.old_limit = 0; |
| 286 | work_on_cpu(b->cpu, threshold_restart_bank, &tr); | ||
| 289 | 287 | ||
| 290 | return end - buf; | 288 | return end - buf; |
| 291 | } | 289 | } |
| @@ -294,8 +292,7 @@ static ssize_t store_threshold_limit(struct threshold_block *b, | |||
| 294 | const char *buf, size_t count) | 292 | const char *buf, size_t count) |
| 295 | { | 293 | { |
| 296 | char *end; | 294 | char *end; |
| 297 | cpumask_t oldmask, newmask; | 295 | struct thresh_restart tr; |
| 298 | u16 old; | ||
| 299 | unsigned long new = simple_strtoul(buf, &end, 0); | 296 | unsigned long new = simple_strtoul(buf, &end, 0); |
| 300 | if (end == buf) | 297 | if (end == buf) |
| 301 | return -EINVAL; | 298 | return -EINVAL; |
| @@ -303,34 +300,36 @@ static ssize_t store_threshold_limit(struct threshold_block *b, | |||
| 303 | new = THRESHOLD_MAX; | 300 | new = THRESHOLD_MAX; |
| 304 | if (new < 1) | 301 | if (new < 1) |
| 305 | new = 1; | 302 | new = 1; |
| 306 | old = b->threshold_limit; | 303 | tr.old_limit = b->threshold_limit; |
| 307 | b->threshold_limit = new; | 304 | b->threshold_limit = new; |
| 305 | tr.b = b; | ||
| 306 | tr.reset = 0; | ||
| 308 | 307 | ||
| 309 | affinity_set(b->cpu, &oldmask, &newmask); | 308 | work_on_cpu(b->cpu, threshold_restart_bank, &tr); |
| 310 | threshold_restart_bank(b, 0, old); | ||
| 311 | affinity_restore(&oldmask); | ||
| 312 | 309 | ||
| 313 | return end - buf; | 310 | return end - buf; |
| 314 | } | 311 | } |
| 315 | 312 | ||
| 316 | static ssize_t show_error_count(struct threshold_block *b, char *buf) | 313 | static long local_error_count(void *_b) |
| 317 | { | 314 | { |
| 318 | u32 high, low; | 315 | struct threshold_block *b = _b; |
| 319 | cpumask_t oldmask, newmask; | 316 | u32 low, high; |
| 320 | affinity_set(b->cpu, &oldmask, &newmask); | 317 | |
| 321 | rdmsr(b->address, low, high); | 318 | rdmsr(b->address, low, high); |
| 322 | affinity_restore(&oldmask); | 319 | return (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit); |
| 323 | return sprintf(buf, "%x\n", | 320 | } |
| 324 | (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit)); | 321 | |
| 322 | static ssize_t show_error_count(struct threshold_block *b, char *buf) | ||
| 323 | { | ||
| 324 | return sprintf(buf, "%lx\n", work_on_cpu(b->cpu, local_error_count, b)); | ||
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | static ssize_t store_error_count(struct threshold_block *b, | 327 | static ssize_t store_error_count(struct threshold_block *b, |
| 328 | const char *buf, size_t count) | 328 | const char *buf, size_t count) |
| 329 | { | 329 | { |
| 330 | cpumask_t oldmask, newmask; | 330 | struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 }; |
| 331 | affinity_set(b->cpu, &oldmask, &newmask); | 331 | |
| 332 | threshold_restart_bank(b, 1, 0); | 332 | work_on_cpu(b->cpu, threshold_restart_bank, &tr); |
| 333 | affinity_restore(&oldmask); | ||
| 334 | return 1; | 333 | return 1; |
| 335 | } | 334 | } |
| 336 | 335 | ||
| @@ -463,12 +462,19 @@ out_free: | |||
| 463 | return err; | 462 | return err; |
| 464 | } | 463 | } |
| 465 | 464 | ||
| 465 | static long local_allocate_threshold_blocks(void *_bank) | ||
| 466 | { | ||
| 467 | unsigned int *bank = _bank; | ||
| 468 | |||
| 469 | return allocate_threshold_blocks(smp_processor_id(), *bank, 0, | ||
| 470 | MSR_IA32_MC0_MISC + *bank * 4); | ||
| 471 | } | ||
| 472 | |||
| 466 | /* symlinks sibling shared banks to first core. first core owns dir/files. */ | 473 | /* symlinks sibling shared banks to first core. first core owns dir/files. */ |
| 467 | static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | 474 | static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) |
| 468 | { | 475 | { |
| 469 | int i, err = 0; | 476 | int i, err = 0; |
| 470 | struct threshold_bank *b = NULL; | 477 | struct threshold_bank *b = NULL; |
| 471 | cpumask_t oldmask, newmask; | ||
| 472 | char name[32]; | 478 | char name[32]; |
| 473 | 479 | ||
| 474 | sprintf(name, "threshold_bank%i", bank); | 480 | sprintf(name, "threshold_bank%i", bank); |
| @@ -519,11 +525,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) | |||
| 519 | 525 | ||
| 520 | per_cpu(threshold_banks, cpu)[bank] = b; | 526 | per_cpu(threshold_banks, cpu)[bank] = b; |
| 521 | 527 | ||
| 522 | affinity_set(cpu, &oldmask, &newmask); | 528 | err = work_on_cpu(cpu, local_allocate_threshold_blocks, &bank); |
| 523 | err = allocate_threshold_blocks(cpu, bank, 0, | ||
| 524 | MSR_IA32_MC0_MISC + bank * 4); | ||
| 525 | affinity_restore(&oldmask); | ||
| 526 | |||
| 527 | if (err) | 529 | if (err) |
| 528 | goto out_free; | 530 | goto out_free; |
| 529 | 531 | ||
