diff options
Diffstat (limited to 'arch/x86/kernel/irq.c')
| -rw-r--r-- | arch/x86/kernel/irq.c | 102 |
1 files changed, 96 insertions, 6 deletions
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 04bbd5278568..fee6cc2b2079 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
| @@ -92,17 +92,17 @@ static int show_other_interrupts(struct seq_file *p, int prec) | |||
| 92 | seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); | 92 | seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count); |
| 93 | seq_printf(p, " TLB shootdowns\n"); | 93 | seq_printf(p, " TLB shootdowns\n"); |
| 94 | #endif | 94 | #endif |
| 95 | #ifdef CONFIG_X86_MCE | 95 | #ifdef CONFIG_X86_THERMAL_VECTOR |
| 96 | seq_printf(p, "%*s: ", prec, "TRM"); | 96 | seq_printf(p, "%*s: ", prec, "TRM"); |
| 97 | for_each_online_cpu(j) | 97 | for_each_online_cpu(j) |
| 98 | seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count); | 98 | seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count); |
| 99 | seq_printf(p, " Thermal event interrupts\n"); | 99 | seq_printf(p, " Thermal event interrupts\n"); |
| 100 | # ifdef CONFIG_X86_MCE_THRESHOLD | 100 | #endif |
| 101 | #ifdef CONFIG_X86_MCE_THRESHOLD | ||
| 101 | seq_printf(p, "%*s: ", prec, "THR"); | 102 | seq_printf(p, "%*s: ", prec, "THR"); |
| 102 | for_each_online_cpu(j) | 103 | for_each_online_cpu(j) |
| 103 | seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count); | 104 | seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count); |
| 104 | seq_printf(p, " Threshold APIC interrupts\n"); | 105 | seq_printf(p, " Threshold APIC interrupts\n"); |
| 105 | # endif | ||
| 106 | #endif | 106 | #endif |
| 107 | #ifdef CONFIG_X86_MCE | 107 | #ifdef CONFIG_X86_MCE |
| 108 | seq_printf(p, "%*s: ", prec, "MCE"); | 108 | seq_printf(p, "%*s: ", prec, "MCE"); |
| @@ -194,11 +194,11 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
| 194 | sum += irq_stats(cpu)->irq_call_count; | 194 | sum += irq_stats(cpu)->irq_call_count; |
| 195 | sum += irq_stats(cpu)->irq_tlb_count; | 195 | sum += irq_stats(cpu)->irq_tlb_count; |
| 196 | #endif | 196 | #endif |
| 197 | #ifdef CONFIG_X86_MCE | 197 | #ifdef CONFIG_X86_THERMAL_VECTOR |
| 198 | sum += irq_stats(cpu)->irq_thermal_count; | 198 | sum += irq_stats(cpu)->irq_thermal_count; |
| 199 | # ifdef CONFIG_X86_MCE_THRESHOLD | 199 | #endif |
| 200 | #ifdef CONFIG_X86_MCE_THRESHOLD | ||
| 200 | sum += irq_stats(cpu)->irq_threshold_count; | 201 | sum += irq_stats(cpu)->irq_threshold_count; |
| 201 | # endif | ||
| 202 | #endif | 202 | #endif |
| 203 | #ifdef CONFIG_X86_MCE | 203 | #ifdef CONFIG_X86_MCE |
| 204 | sum += per_cpu(mce_exception_count, cpu); | 204 | sum += per_cpu(mce_exception_count, cpu); |
| @@ -274,3 +274,93 @@ void smp_generic_interrupt(struct pt_regs *regs) | |||
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); | 276 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); |
| 277 | |||
| 278 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 279 | /* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ | ||
| 280 | void fixup_irqs(void) | ||
| 281 | { | ||
| 282 | unsigned int irq, vector; | ||
| 283 | static int warned; | ||
| 284 | struct irq_desc *desc; | ||
| 285 | |||
| 286 | for_each_irq_desc(irq, desc) { | ||
| 287 | int break_affinity = 0; | ||
| 288 | int set_affinity = 1; | ||
| 289 | const struct cpumask *affinity; | ||
| 290 | |||
| 291 | if (!desc) | ||
| 292 | continue; | ||
| 293 | if (irq == 2) | ||
| 294 | continue; | ||
| 295 | |||
| 296 | /* interrupt's are disabled at this point */ | ||
| 297 | spin_lock(&desc->lock); | ||
| 298 | |||
| 299 | affinity = desc->affinity; | ||
| 300 | if (!irq_has_action(irq) || | ||
| 301 | cpumask_equal(affinity, cpu_online_mask)) { | ||
| 302 | spin_unlock(&desc->lock); | ||
| 303 | continue; | ||
| 304 | } | ||
| 305 | |||
| 306 | /* | ||
| 307 | * Complete the irq move. This cpu is going down and for | ||
| 308 | * non intr-remapping case, we can't wait till this interrupt | ||
| 309 | * arrives at this cpu before completing the irq move. | ||
| 310 | */ | ||
| 311 | irq_force_complete_move(irq); | ||
| 312 | |||
| 313 | if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { | ||
| 314 | break_affinity = 1; | ||
| 315 | affinity = cpu_all_mask; | ||
| 316 | } | ||
| 317 | |||
| 318 | if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->mask) | ||
| 319 | desc->chip->mask(irq); | ||
| 320 | |||
| 321 | if (desc->chip->set_affinity) | ||
| 322 | desc->chip->set_affinity(irq, affinity); | ||
| 323 | else if (!(warned++)) | ||
| 324 | set_affinity = 0; | ||
| 325 | |||
| 326 | if (!(desc->status & IRQ_MOVE_PCNTXT) && desc->chip->unmask) | ||
| 327 | desc->chip->unmask(irq); | ||
| 328 | |||
| 329 | spin_unlock(&desc->lock); | ||
| 330 | |||
| 331 | if (break_affinity && set_affinity) | ||
| 332 | printk("Broke affinity for irq %i\n", irq); | ||
| 333 | else if (!set_affinity) | ||
| 334 | printk("Cannot set affinity for irq %i\n", irq); | ||
| 335 | } | ||
| 336 | |||
| 337 | /* | ||
| 338 | * We can remove mdelay() and then send spuriuous interrupts to | ||
| 339 | * new cpu targets for all the irqs that were handled previously by | ||
| 340 | * this cpu. While it works, I have seen spurious interrupt messages | ||
| 341 | * (nothing wrong but still...). | ||
| 342 | * | ||
| 343 | * So for now, retain mdelay(1) and check the IRR and then send those | ||
| 344 | * interrupts to new targets as this cpu is already offlined... | ||
| 345 | */ | ||
| 346 | mdelay(1); | ||
| 347 | |||
| 348 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { | ||
| 349 | unsigned int irr; | ||
| 350 | |||
| 351 | if (__get_cpu_var(vector_irq)[vector] < 0) | ||
| 352 | continue; | ||
| 353 | |||
| 354 | irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); | ||
| 355 | if (irr & (1 << (vector % 32))) { | ||
| 356 | irq = __get_cpu_var(vector_irq)[vector]; | ||
| 357 | |||
| 358 | desc = irq_to_desc(irq); | ||
| 359 | spin_lock(&desc->lock); | ||
| 360 | if (desc->chip->retrigger) | ||
| 361 | desc->chip->retrigger(irq); | ||
| 362 | spin_unlock(&desc->lock); | ||
| 363 | } | ||
| 364 | } | ||
| 365 | } | ||
| 366 | #endif | ||
