irq.c 11.6 KB
Newer Older
1 2 3 4 5 6
/*
 * Common interrupt code for 32 and 64 bit
 */
#include <linux/cpu.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
7
#include <linux/of.h>
8
#include <linux/seq_file.h>
9
#include <linux/smp.h>
J
Jeremy Fitzhardinge 已提交
10
#include <linux/ftrace.h>
11
#include <linux/delay.h>
12
#include <linux/export.h>
13

I
Ingo Molnar 已提交
14
#include <asm/apic.h>
15
#include <asm/io_apic.h>
16
#include <asm/irq.h>
J
Jeremy Fitzhardinge 已提交
17
#include <asm/idle.h>
18
#include <asm/mce.h>
19
#include <asm/hw_irq.h>
20 21

#define CREATE_TRACE_POINTS
22
#include <asm/trace/irq_vectors.h>
23 24 25

atomic_t irq_err_count;

26
/* Function pointer for generic interrupt vector handling */
27
void (*x86_platform_ipi_callback)(void) = NULL;
28

T
Thomas Gleixner 已提交
29 30 31 32 33 34
/*
 * 'what should we do if we get a hw irq event on an illegal vector'.
 * each architecture has to answer this themselves.
 */
void ack_bad_irq(unsigned int irq)
{
C
Cyrill Gorcunov 已提交
35 36
	if (printk_ratelimit())
		pr_err("unexpected IRQ trap at vector %02x\n", irq);
T
Thomas Gleixner 已提交
37 38 39 40 41 42 43 44 45 46

	/*
	 * Currently unexpected vectors happen only on SMP and APIC.
	 * We _must_ ack these because every local APIC has only N
	 * irq slots per priority level, and a 'hanging, unacked' IRQ
	 * holds up an irq slot - in excessive cases (when multiple
	 * unexpected vectors occur) that might lock up the APIC
	 * completely.
	 * But only ack when the APIC is enabled -AK
	 */
47
	ack_APIC_irq();
T
Thomas Gleixner 已提交
48 49
}

50
#define irq_stats(x)		(&per_cpu(irq_stat, x))
51
/*
52
 * /proc/interrupts printing for arch specific interrupts
53
 */
54
int arch_show_interrupts(struct seq_file *p, int prec)
55 56 57
{
	int j;

58
	seq_printf(p, "%*s: ", prec, "NMI");
59 60 61 62
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", irq_stats(j)->__nmi_count);
	seq_printf(p, "  Non-maskable interrupts\n");
#ifdef CONFIG_X86_LOCAL_APIC
63
	seq_printf(p, "%*s: ", prec, "LOC");
64 65 66
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
	seq_printf(p, "  Local timer interrupts\n");
67 68 69 70 71

	seq_printf(p, "%*s: ", prec, "SPU");
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
	seq_printf(p, "  Spurious interrupts\n");
72
	seq_printf(p, "%*s: ", prec, "PMI");
I
Ingo Molnar 已提交
73 74
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", irq_stats(j)->apic_perf_irqs);
75
	seq_printf(p, "  Performance monitoring interrupts\n");
76
	seq_printf(p, "%*s: ", prec, "IWI");
77
	for_each_online_cpu(j)
78 79
		seq_printf(p, "%10u ", irq_stats(j)->apic_irq_work_irqs);
	seq_printf(p, "  IRQ work interrupts\n");
80 81
	seq_printf(p, "%*s: ", prec, "RTR");
	for_each_online_cpu(j)
82
		seq_printf(p, "%10u ", irq_stats(j)->icr_read_retry_count);
83
	seq_printf(p, "  APIC ICR read retries\n");
84
#endif
85
	if (x86_platform_ipi_callback) {
86
		seq_printf(p, "%*s: ", prec, "PLT");
87
		for_each_online_cpu(j)
88
			seq_printf(p, "%10u ", irq_stats(j)->x86_platform_ipis);
89 90
		seq_printf(p, "  Platform interrupts\n");
	}
91
#ifdef CONFIG_SMP
92
	seq_printf(p, "%*s: ", prec, "RES");
93 94 95
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
	seq_printf(p, "  Rescheduling interrupts\n");
96
	seq_printf(p, "%*s: ", prec, "CAL");
97
	for_each_online_cpu(j)
98 99
		seq_printf(p, "%10u ", irq_stats(j)->irq_call_count -
					irq_stats(j)->irq_tlb_count);
100
	seq_printf(p, "  Function call interrupts\n");
101
	seq_printf(p, "%*s: ", prec, "TLB");
102 103 104 105
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
	seq_printf(p, "  TLB shootdowns\n");
#endif
106
#ifdef CONFIG_X86_THERMAL_VECTOR
107
	seq_printf(p, "%*s: ", prec, "TRM");
108 109 110
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
	seq_printf(p, "  Thermal event interrupts\n");
111 112
#endif
#ifdef CONFIG_X86_MCE_THRESHOLD
113
	seq_printf(p, "%*s: ", prec, "THR");
114 115 116
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
	seq_printf(p, "  Threshold APIC interrupts\n");
117
#endif
118
#ifdef CONFIG_X86_MCE
119 120 121 122
	seq_printf(p, "%*s: ", prec, "MCE");
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", per_cpu(mce_exception_count, j));
	seq_printf(p, "  Machine check exceptions\n");
123 124 125 126
	seq_printf(p, "%*s: ", prec, "MCP");
	for_each_online_cpu(j)
		seq_printf(p, "%10u ", per_cpu(mce_poll_count, j));
	seq_printf(p, "  Machine check polls\n");
127
#endif
128
	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
129
#if defined(CONFIG_X86_IO_APIC)
130
	seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count));
131 132 133 134 135 136 137 138 139 140 141 142 143
#endif
	return 0;
}

/*
 * /proc/stat helpers
 */
u64 arch_irq_stat_cpu(unsigned int cpu)
{
	u64 sum = irq_stats(cpu)->__nmi_count;

#ifdef CONFIG_X86_LOCAL_APIC
	sum += irq_stats(cpu)->apic_timer_irqs;
144
	sum += irq_stats(cpu)->irq_spurious_count;
I
Ingo Molnar 已提交
145
	sum += irq_stats(cpu)->apic_perf_irqs;
146
	sum += irq_stats(cpu)->apic_irq_work_irqs;
147
	sum += irq_stats(cpu)->icr_read_retry_count;
148
#endif
149 150
	if (x86_platform_ipi_callback)
		sum += irq_stats(cpu)->x86_platform_ipis;
151 152 153 154
#ifdef CONFIG_SMP
	sum += irq_stats(cpu)->irq_resched_count;
	sum += irq_stats(cpu)->irq_call_count;
#endif
155
#ifdef CONFIG_X86_THERMAL_VECTOR
156
	sum += irq_stats(cpu)->irq_thermal_count;
157 158
#endif
#ifdef CONFIG_X86_MCE_THRESHOLD
159
	sum += irq_stats(cpu)->irq_threshold_count;
H
Hidetoshi Seto 已提交
160
#endif
161
#ifdef CONFIG_X86_MCE
H
Hidetoshi Seto 已提交
162 163
	sum += per_cpu(mce_exception_count, cpu);
	sum += per_cpu(mce_poll_count, cpu);
164 165 166 167 168 169 170 171 172
#endif
	return sum;
}

u64 arch_irq_stat(void)
{
	u64 sum = atomic_read(&irq_err_count);
	return sum;
}
173

J
Jeremy Fitzhardinge 已提交
174 175 176 177 178 179

/*
 * do_IRQ handles all normal device IRQ's (the special
 * SMP cross-CPU interrupts have their own specific
 * handlers).
 */
180
__visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
J
Jeremy Fitzhardinge 已提交
181 182 183 184 185 186 187 188
{
	struct pt_regs *old_regs = set_irq_regs(regs);

	/* high bit used in ret_from_ code  */
	unsigned vector = ~regs->orig_ax;
	unsigned irq;

	irq_enter();
189
	exit_idle();
J
Jeremy Fitzhardinge 已提交
190

T
Tejun Heo 已提交
191
	irq = __this_cpu_read(vector_irq[vector]);
J
Jeremy Fitzhardinge 已提交
192 193

	if (!handle_irq(irq, regs)) {
194
		ack_APIC_irq();
J
Jeremy Fitzhardinge 已提交
195

196 197 198 199 200 201 202
		if (irq != VECTOR_RETRIGGERED) {
			pr_emerg_ratelimited("%s: %d.%d No irq handler for vector (irq %d)\n",
					     __func__, smp_processor_id(),
					     vector, irq);
		} else {
			__this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
		}
J
Jeremy Fitzhardinge 已提交
203 204 205 206 207 208 209 210
	}

	irq_exit();

	set_irq_regs(old_regs);
	return 1;
}

211
/*
212
 * Handler for X86_PLATFORM_IPI_VECTOR.
213
 */
214
void __smp_x86_platform_ipi(void)
215
{
216
	inc_irq_stat(x86_platform_ipis);
217

218 219
	if (x86_platform_ipi_callback)
		x86_platform_ipi_callback();
220
}
221

222
__visible void smp_x86_platform_ipi(struct pt_regs *regs)
223 224
{
	struct pt_regs *old_regs = set_irq_regs(regs);
225

226 227 228
	entering_ack_irq();
	__smp_x86_platform_ipi();
	exiting_irq();
229 230 231
	set_irq_regs(old_regs);
}

232 233 234 235
#ifdef CONFIG_HAVE_KVM
/*
 * Handler for POSTED_INTERRUPT_VECTOR.
 */
236
__visible void smp_kvm_posted_intr_ipi(struct pt_regs *regs)
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
{
	struct pt_regs *old_regs = set_irq_regs(regs);

	ack_APIC_irq();

	irq_enter();

	exit_idle();

	inc_irq_stat(kvm_posted_intr_ipis);

	irq_exit();

	set_irq_regs(old_regs);
}
#endif

254
__visible void smp_trace_x86_platform_ipi(struct pt_regs *regs)
255 256 257 258 259 260 261 262 263 264 265
{
	struct pt_regs *old_regs = set_irq_regs(regs);

	entering_ack_irq();
	trace_x86_platform_ipi_entry(X86_PLATFORM_IPI_VECTOR);
	__smp_x86_platform_ipi();
	trace_x86_platform_ipi_exit(X86_PLATFORM_IPI_VECTOR);
	exiting_irq();
	set_irq_regs(old_regs);
}

266
EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
267 268

#ifdef CONFIG_HOTPLUG_CPU
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
/*
 * This cpu is going to be removed and its vectors migrated to the remaining
 * online cpus.  Check to see if there are enough vectors in the remaining cpus.
 * This function is protected by stop_machine().
 */
int check_irq_vectors_for_cpu_disable(void)
{
	int irq, cpu;
	unsigned int this_cpu, vector, this_count, count;
	struct irq_desc *desc;
	struct irq_data *data;
	struct cpumask affinity_new, online_new;

	this_cpu = smp_processor_id();
	cpumask_copy(&online_new, cpu_online_mask);
	cpu_clear(this_cpu, online_new);

	this_count = 0;
	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
		irq = __this_cpu_read(vector_irq[vector]);
		if (irq >= 0) {
			desc = irq_to_desc(irq);
			data = irq_desc_get_irq_data(desc);
			cpumask_copy(&affinity_new, data->affinity);
			cpu_clear(this_cpu, affinity_new);

			/* Do not count inactive or per-cpu irqs. */
			if (!irq_has_action(irq) || irqd_is_per_cpu(data))
				continue;

			/*
			 * A single irq may be mapped to multiple
			 * cpu's vector_irq[] (for example IOAPIC cluster
			 * mode).  In this case we have two
			 * possibilities:
			 *
			 * 1) the resulting affinity mask is empty; that is
			 * this the down'd cpu is the last cpu in the irq's
			 * affinity mask, or
			 *
			 * 2) the resulting affinity mask is no longer
			 * a subset of the online cpus but the affinity
			 * mask is not zero; that is the down'd cpu is the
			 * last online cpu in a user set affinity mask.
			 */
			if (cpumask_empty(&affinity_new) ||
			    !cpumask_subset(&affinity_new, &online_new))
				this_count++;
		}
	}

	count = 0;
	for_each_online_cpu(cpu) {
		if (cpu == this_cpu)
			continue;
		for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
		     vector++) {
			if (per_cpu(vector_irq, cpu)[vector] < 0)
				count++;
		}
	}

	if (count < this_count) {
		pr_warn("CPU %d disable failed: CPU has %u vectors assigned and there are only %u available.\n",
			this_cpu, this_count, count);
		return -ERANGE;
	}
	return 0;
}

339 340 341
/* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */
void fixup_irqs(void)
{
342
	unsigned int irq, vector;
343 344
	static int warned;
	struct irq_desc *desc;
345
	struct irq_data *data;
346
	struct irq_chip *chip;
347 348 349 350 351 352 353 354 355 356 357 358

	for_each_irq_desc(irq, desc) {
		int break_affinity = 0;
		int set_affinity = 1;
		const struct cpumask *affinity;

		if (!desc)
			continue;
		if (irq == 2)
			continue;

		/* interrupt's are disabled at this point */
359
		raw_spin_lock(&desc->lock);
360

361
		data = irq_desc_get_irq_data(desc);
362
		affinity = data->affinity;
363
		if (!irq_has_action(irq) || irqd_is_per_cpu(data) ||
364
		    cpumask_subset(affinity, cpu_online_mask)) {
365
			raw_spin_unlock(&desc->lock);
366 367 368
			continue;
		}

369 370 371 372 373 374 375
		/*
		 * Complete the irq move. This cpu is going down and for
		 * non intr-remapping case, we can't wait till this interrupt
		 * arrives at this cpu before completing the irq move.
		 */
		irq_force_complete_move(irq);

376 377
		if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
			break_affinity = 1;
378
			affinity = cpu_online_mask;
379 380
		}

381 382 383
		chip = irq_data_get_irq_chip(data);
		if (!irqd_can_move_in_process_context(data) && chip->irq_mask)
			chip->irq_mask(data);
384

385 386
		if (chip->irq_set_affinity)
			chip->irq_set_affinity(data, affinity, true);
387 388 389
		else if (!(warned++))
			set_affinity = 0;

390 391 392 393 394
		/*
		 * We unmask if the irq was not marked masked by the
		 * core code. That respects the lazy irq disable
		 * behaviour.
		 */
395
		if (!irqd_can_move_in_process_context(data) &&
396
		    !irqd_irq_masked(data) && chip->irq_unmask)
397
			chip->irq_unmask(data);
398

399
		raw_spin_unlock(&desc->lock);
400 401

		if (break_affinity && set_affinity)
402
			pr_notice("Broke affinity for irq %i\n", irq);
403
		else if (!set_affinity)
404
			pr_notice("Cannot set affinity for irq %i\n", irq);
405 406
	}

407 408 409 410 411 412 413 414 415
	/*
	 * We can remove mdelay() and then send spuriuous interrupts to
	 * new cpu targets for all the irqs that were handled previously by
	 * this cpu. While it works, I have seen spurious interrupt messages
	 * (nothing wrong but still...).
	 *
	 * So for now, retain mdelay(1) and check the IRR and then send those
	 * interrupts to new targets as this cpu is already offlined...
	 */
416
	mdelay(1);
417 418 419 420

	for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
		unsigned int irr;

421
		if (__this_cpu_read(vector_irq[vector]) <= VECTOR_UNDEFINED)
422 423 424 425
			continue;

		irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
		if (irr  & (1 << (vector % 32))) {
T
Tejun Heo 已提交
426
			irq = __this_cpu_read(vector_irq[vector]);
427

428
			desc = irq_to_desc(irq);
429 430
			data = irq_desc_get_irq_data(desc);
			chip = irq_data_get_irq_chip(data);
431
			raw_spin_lock(&desc->lock);
432
			if (chip->irq_retrigger) {
433
				chip->irq_retrigger(data);
434 435
				__this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED);
			}
436
			raw_spin_unlock(&desc->lock);
437
		}
438 439
		if (__this_cpu_read(vector_irq[vector]) != VECTOR_RETRIGGERED)
			__this_cpu_write(vector_irq[vector], VECTOR_UNDEFINED);
440
	}
441 442
}
#endif