diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2015-10-09 11:47:34 -0400 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2015-10-09 11:47:34 -0400 |
commit | a78afccbbaa6d2df49768cabad8af28a0a84181d (patch) | |
tree | a14d9ddea49c27df575fd6c029baad80b8b03a75 | |
parent | 348a65cdcbbf243073ee39d1f7d4413081ad7eab (diff) | |
parent | f1e0bb0ad473a32d1b7e6d285ae9f7e47710bb5e (diff) |
Merge branch 'irq/for-arm' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'irq/for-arm' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
genirq: Introduce generic irq migration for cpu hotunplug
-rw-r--r-- | include/linux/irq.h | 2 | ||||
-rw-r--r-- | kernel/irq/Kconfig | 4 | ||||
-rw-r--r-- | kernel/irq/Makefile | 1 | ||||
-rw-r--r-- | kernel/irq/cpuhotplug.c | 82 |
4 files changed, 89 insertions, 0 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 11bf09288ddb..45cc7299bb61 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -452,6 +452,8 @@ extern int irq_set_affinity_locked(struct irq_data *data, | |||
452 | const struct cpumask *cpumask, bool force); | 452 | const struct cpumask *cpumask, bool force); |
453 | extern int irq_set_vcpu_affinity(unsigned int irq, void *vcpu_info); | 453 | extern int irq_set_vcpu_affinity(unsigned int irq, void *vcpu_info); |
454 | 454 | ||
455 | extern void irq_migrate_all_off_this_cpu(void); | ||
456 | |||
455 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) | 457 | #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) |
456 | void irq_move_irq(struct irq_data *data); | 458 | void irq_move_irq(struct irq_data *data); |
457 | void irq_move_masked_irq(struct irq_data *data); | 459 | void irq_move_masked_irq(struct irq_data *data); |
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index 9a76e3beda54..3b48dab80164 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig | |||
@@ -30,6 +30,10 @@ config GENERIC_IRQ_LEGACY_ALLOC_HWIRQ | |||
30 | config GENERIC_PENDING_IRQ | 30 | config GENERIC_PENDING_IRQ |
31 | bool | 31 | bool |
32 | 32 | ||
33 | # Support for generic irq migrating off cpu before the cpu is offline. | ||
34 | config GENERIC_IRQ_MIGRATION | ||
35 | bool | ||
36 | |||
33 | # Alpha specific irq affinity mechanism | 37 | # Alpha specific irq affinity mechanism |
34 | config AUTO_IRQ_AFFINITY | 38 | config AUTO_IRQ_AFFINITY |
35 | bool | 39 | bool |
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile index d12123526e2b..2fc9cbdf35b6 100644 --- a/kernel/irq/Makefile +++ b/kernel/irq/Makefile | |||
@@ -5,5 +5,6 @@ obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o | |||
5 | obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o | 5 | obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o |
6 | obj-$(CONFIG_PROC_FS) += proc.o | 6 | obj-$(CONFIG_PROC_FS) += proc.o |
7 | obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o | 7 | obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o |
8 | obj-$(CONFIG_GENERIC_IRQ_MIGRATION) += cpuhotplug.o | ||
8 | obj-$(CONFIG_PM_SLEEP) += pm.o | 9 | obj-$(CONFIG_PM_SLEEP) += pm.o |
9 | obj-$(CONFIG_GENERIC_MSI_IRQ) += msi.o | 10 | obj-$(CONFIG_GENERIC_MSI_IRQ) += msi.o |
diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c new file mode 100644 index 000000000000..80f4f4e56fed --- /dev/null +++ b/kernel/irq/cpuhotplug.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * Generic cpu hotunplug interrupt migration code copied from the | ||
3 | * arch/arm implementation | ||
4 | * | ||
5 | * Copyright (C) Russell King | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/ratelimit.h> | ||
13 | #include <linux/irq.h> | ||
14 | |||
15 | #include "internals.h" | ||
16 | |||
17 | static bool migrate_one_irq(struct irq_desc *desc) | ||
18 | { | ||
19 | struct irq_data *d = irq_desc_get_irq_data(desc); | ||
20 | const struct cpumask *affinity = d->common->affinity; | ||
21 | struct irq_chip *c; | ||
22 | bool ret = false; | ||
23 | |||
24 | /* | ||
25 | * If this is a per-CPU interrupt, or the affinity does not | ||
26 | * include this CPU, then we have nothing to do. | ||
27 | */ | ||
28 | if (irqd_is_per_cpu(d) || | ||
29 | !cpumask_test_cpu(smp_processor_id(), affinity)) | ||
30 | return false; | ||
31 | |||
32 | if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { | ||
33 | affinity = cpu_online_mask; | ||
34 | ret = true; | ||
35 | } | ||
36 | |||
37 | c = irq_data_get_irq_chip(d); | ||
38 | if (!c->irq_set_affinity) { | ||
39 | pr_warn_ratelimited("IRQ%u: unable to set affinity\n", d->irq); | ||
40 | } else { | ||
41 | int r = irq_do_set_affinity(d, affinity, false); | ||
42 | if (r) | ||
43 | pr_warn_ratelimited("IRQ%u: set affinity failed(%d).\n", | ||
44 | d->irq, r); | ||
45 | } | ||
46 | |||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * irq_migrate_all_off_this_cpu - Migrate irqs away from offline cpu | ||
52 | * | ||
53 | * The current CPU has been marked offline. Migrate IRQs off this CPU. | ||
54 | * If the affinity settings do not allow other CPUs, force them onto any | ||
55 | * available CPU. | ||
56 | * | ||
57 | * Note: we must iterate over all IRQs, whether they have an attached | ||
58 | * action structure or not, as we need to get chained interrupts too. | ||
59 | */ | ||
60 | void irq_migrate_all_off_this_cpu(void) | ||
61 | { | ||
62 | unsigned int irq; | ||
63 | struct irq_desc *desc; | ||
64 | unsigned long flags; | ||
65 | |||
66 | local_irq_save(flags); | ||
67 | |||
68 | for_each_active_irq(irq) { | ||
69 | bool affinity_broken; | ||
70 | |||
71 | desc = irq_to_desc(irq); | ||
72 | raw_spin_lock(&desc->lock); | ||
73 | affinity_broken = migrate_one_irq(desc); | ||
74 | raw_spin_unlock(&desc->lock); | ||
75 | |||
76 | if (affinity_broken) | ||
77 | pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n", | ||
78 | irq, smp_processor_id()); | ||
79 | } | ||
80 | |||
81 | local_irq_restore(flags); | ||
82 | } | ||