aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/chip.c5
-rw-r--r--kernel/irq/handle.c54
-rw-r--r--kernel/irq/internals.h7
-rw-r--r--kernel/irq/manage.c12
-rw-r--r--kernel/irq/migration.c12
-rw-r--r--kernel/irq/numa_migrate.c19
-rw-r--r--kernel/irq/proc.c4
7 files changed, 74 insertions, 39 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 03d0bed2b8d9..c687ba4363f2 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -46,7 +46,10 @@ void dynamic_irq_init(unsigned int irq)
46 desc->irq_count = 0; 46 desc->irq_count = 0;
47 desc->irqs_unhandled = 0; 47 desc->irqs_unhandled = 0;
48#ifdef CONFIG_SMP 48#ifdef CONFIG_SMP
49 cpumask_setall(&desc->affinity); 49 cpumask_setall(desc->affinity);
50#ifdef CONFIG_GENERIC_PENDING_IRQ
51 cpumask_clear(desc->pending_mask);
52#endif
50#endif 53#endif
51 spin_unlock_irqrestore(&desc->lock, flags); 54 spin_unlock_irqrestore(&desc->lock, flags);
52} 55}
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index f6cdda68e5c6..9ebf77968871 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -17,6 +17,7 @@
17#include <linux/kernel_stat.h> 17#include <linux/kernel_stat.h>
18#include <linux/rculist.h> 18#include <linux/rculist.h>
19#include <linux/hash.h> 19#include <linux/hash.h>
20#include <linux/bootmem.h>
20 21
21#include "internals.h" 22#include "internals.h"
22 23
@@ -69,6 +70,7 @@ int nr_irqs = NR_IRQS;
69EXPORT_SYMBOL_GPL(nr_irqs); 70EXPORT_SYMBOL_GPL(nr_irqs);
70 71
71#ifdef CONFIG_SPARSE_IRQ 72#ifdef CONFIG_SPARSE_IRQ
73
72static struct irq_desc irq_desc_init = { 74static struct irq_desc irq_desc_init = {
73 .irq = -1, 75 .irq = -1,
74 .status = IRQ_DISABLED, 76 .status = IRQ_DISABLED,
@@ -76,9 +78,6 @@ static struct irq_desc irq_desc_init = {
76 .handle_irq = handle_bad_irq, 78 .handle_irq = handle_bad_irq,
77 .depth = 1, 79 .depth = 1,
78 .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), 80 .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
79#ifdef CONFIG_SMP
80 .affinity = CPU_MASK_ALL
81#endif
82}; 81};
83 82
84void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr) 83void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr)
@@ -115,6 +114,10 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu)
115 printk(KERN_ERR "can not alloc kstat_irqs\n"); 114 printk(KERN_ERR "can not alloc kstat_irqs\n");
116 BUG_ON(1); 115 BUG_ON(1);
117 } 116 }
117 if (!init_alloc_desc_masks(desc, cpu, false)) {
118 printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
119 BUG_ON(1);
120 }
118 arch_init_chip_data(desc, cpu); 121 arch_init_chip_data(desc, cpu);
119} 122}
120 123
@@ -123,7 +126,7 @@ static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu)
123 */ 126 */
124DEFINE_SPINLOCK(sparse_irq_lock); 127DEFINE_SPINLOCK(sparse_irq_lock);
125 128
126struct irq_desc *irq_desc_ptrs[NR_IRQS] __read_mostly; 129struct irq_desc **irq_desc_ptrs __read_mostly;
127 130
128static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = { 131static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = {
129 [0 ... NR_IRQS_LEGACY-1] = { 132 [0 ... NR_IRQS_LEGACY-1] = {
@@ -133,14 +136,10 @@ static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_sm
133 .handle_irq = handle_bad_irq, 136 .handle_irq = handle_bad_irq,
134 .depth = 1, 137 .depth = 1,
135 .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock), 138 .lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
136#ifdef CONFIG_SMP
137 .affinity = CPU_MASK_ALL
138#endif
139 } 139 }
140}; 140};
141 141
142/* FIXME: use bootmem alloc ...*/ 142static unsigned int *kstat_irqs_legacy;
143static unsigned int kstat_irqs_legacy[NR_IRQS_LEGACY][NR_CPUS];
144 143
145int __init early_irq_init(void) 144int __init early_irq_init(void)
146{ 145{
@@ -150,18 +149,30 @@ int __init early_irq_init(void)
150 149
151 init_irq_default_affinity(); 150 init_irq_default_affinity();
152 151
152 /* initialize nr_irqs based on nr_cpu_ids */
153 arch_probe_nr_irqs();
154 printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d\n", NR_IRQS, nr_irqs);
155
153 desc = irq_desc_legacy; 156 desc = irq_desc_legacy;
154 legacy_count = ARRAY_SIZE(irq_desc_legacy); 157 legacy_count = ARRAY_SIZE(irq_desc_legacy);
155 158
159 /* allocate irq_desc_ptrs array based on nr_irqs */
160 irq_desc_ptrs = alloc_bootmem(nr_irqs * sizeof(void *));
161
162 /* allocate based on nr_cpu_ids */
163 /* FIXME: invert kstat_irgs, and it'd be a per_cpu_alloc'd thing */
164 kstat_irqs_legacy = alloc_bootmem(NR_IRQS_LEGACY * nr_cpu_ids *
165 sizeof(int));
166
156 for (i = 0; i < legacy_count; i++) { 167 for (i = 0; i < legacy_count; i++) {
157 desc[i].irq = i; 168 desc[i].irq = i;
158 desc[i].kstat_irqs = kstat_irqs_legacy[i]; 169 desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
159 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); 170 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
160 171 init_alloc_desc_masks(&desc[i], 0, true);
161 irq_desc_ptrs[i] = desc + i; 172 irq_desc_ptrs[i] = desc + i;
162 } 173 }
163 174
164 for (i = legacy_count; i < NR_IRQS; i++) 175 for (i = legacy_count; i < nr_irqs; i++)
165 irq_desc_ptrs[i] = NULL; 176 irq_desc_ptrs[i] = NULL;
166 177
167 return arch_early_irq_init(); 178 return arch_early_irq_init();
@@ -169,7 +180,10 @@ int __init early_irq_init(void)
169 180
170struct irq_desc *irq_to_desc(unsigned int irq) 181struct irq_desc *irq_to_desc(unsigned int irq)
171{ 182{
172 return (irq < NR_IRQS) ? irq_desc_ptrs[irq] : NULL; 183 if (irq_desc_ptrs && irq < nr_irqs)
184 return irq_desc_ptrs[irq];
185
186 return NULL;
173} 187}
174 188
175struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu) 189struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
@@ -178,10 +192,9 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
178 unsigned long flags; 192 unsigned long flags;
179 int node; 193 int node;
180 194
181 if (irq >= NR_IRQS) { 195 if (irq >= nr_irqs) {
182 printk(KERN_WARNING "irq >= NR_IRQS in irq_to_desc_alloc: %d %d\n", 196 WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
183 irq, NR_IRQS); 197 irq, nr_irqs);
184 WARN_ON(1);
185 return NULL; 198 return NULL;
186 } 199 }
187 200
@@ -223,9 +236,6 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
223 .handle_irq = handle_bad_irq, 236 .handle_irq = handle_bad_irq,
224 .depth = 1, 237 .depth = 1,
225 .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), 238 .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
226#ifdef CONFIG_SMP
227 .affinity = CPU_MASK_ALL
228#endif
229 } 239 }
230}; 240};
231 241
@@ -238,14 +248,16 @@ int __init early_irq_init(void)
238 248
239 init_irq_default_affinity(); 249 init_irq_default_affinity();
240 250
251 printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
252
241 desc = irq_desc; 253 desc = irq_desc;
242 count = ARRAY_SIZE(irq_desc); 254 count = ARRAY_SIZE(irq_desc);
243 255
244 for (i = 0; i < count; i++) { 256 for (i = 0; i < count; i++) {
245 desc[i].irq = i; 257 desc[i].irq = i;
258 init_alloc_desc_masks(&desc[i], 0, true);
246 desc[i].kstat_irqs = kstat_irqs_all[i]; 259 desc[i].kstat_irqs = kstat_irqs_all[i];
247 } 260 }
248
249 return arch_early_irq_init(); 261 return arch_early_irq_init();
250} 262}
251 263
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index b60950bf5a16..ee1aa9f8e8b9 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -17,7 +17,14 @@ extern struct lock_class_key irq_desc_lock_class;
17extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr); 17extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr);
18extern void clear_kstat_irqs(struct irq_desc *desc); 18extern void clear_kstat_irqs(struct irq_desc *desc);
19extern spinlock_t sparse_irq_lock; 19extern spinlock_t sparse_irq_lock;
20
21#ifdef CONFIG_SPARSE_IRQ
22/* irq_desc_ptrs allocated at boot time */
23extern struct irq_desc **irq_desc_ptrs;
24#else
25/* irq_desc_ptrs is a fixed size array */
20extern struct irq_desc *irq_desc_ptrs[NR_IRQS]; 26extern struct irq_desc *irq_desc_ptrs[NR_IRQS];
27#endif
21 28
22#ifdef CONFIG_PROC_FS 29#ifdef CONFIG_PROC_FS
23extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); 30extern void register_irq_proc(unsigned int irq, struct irq_desc *desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index ea119effe096..6458e99984c0 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -90,14 +90,14 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
90 90
91#ifdef CONFIG_GENERIC_PENDING_IRQ 91#ifdef CONFIG_GENERIC_PENDING_IRQ
92 if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) { 92 if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) {
93 cpumask_copy(&desc->affinity, cpumask); 93 cpumask_copy(desc->affinity, cpumask);
94 desc->chip->set_affinity(irq, cpumask); 94 desc->chip->set_affinity(irq, cpumask);
95 } else { 95 } else {
96 desc->status |= IRQ_MOVE_PENDING; 96 desc->status |= IRQ_MOVE_PENDING;
97 cpumask_copy(&desc->pending_mask, cpumask); 97 cpumask_copy(desc->pending_mask, cpumask);
98 } 98 }
99#else 99#else
100 cpumask_copy(&desc->affinity, cpumask); 100 cpumask_copy(desc->affinity, cpumask);
101 desc->chip->set_affinity(irq, cpumask); 101 desc->chip->set_affinity(irq, cpumask);
102#endif 102#endif
103 desc->status |= IRQ_AFFINITY_SET; 103 desc->status |= IRQ_AFFINITY_SET;
@@ -119,16 +119,16 @@ static int setup_affinity(unsigned int irq, struct irq_desc *desc)
119 * one of the targets is online. 119 * one of the targets is online.
120 */ 120 */
121 if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) { 121 if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) {
122 if (cpumask_any_and(&desc->affinity, cpu_online_mask) 122 if (cpumask_any_and(desc->affinity, cpu_online_mask)
123 < nr_cpu_ids) 123 < nr_cpu_ids)
124 goto set_affinity; 124 goto set_affinity;
125 else 125 else
126 desc->status &= ~IRQ_AFFINITY_SET; 126 desc->status &= ~IRQ_AFFINITY_SET;
127 } 127 }
128 128
129 cpumask_and(&desc->affinity, cpu_online_mask, irq_default_affinity); 129 cpumask_and(desc->affinity, cpu_online_mask, irq_default_affinity);
130set_affinity: 130set_affinity:
131 desc->chip->set_affinity(irq, &desc->affinity); 131 desc->chip->set_affinity(irq, desc->affinity);
132 132
133 return 0; 133 return 0;
134} 134}
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index bd72329e630c..e05ad9be43b7 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -18,7 +18,7 @@ void move_masked_irq(int irq)
18 18
19 desc->status &= ~IRQ_MOVE_PENDING; 19 desc->status &= ~IRQ_MOVE_PENDING;
20 20
21 if (unlikely(cpumask_empty(&desc->pending_mask))) 21 if (unlikely(cpumask_empty(desc->pending_mask)))
22 return; 22 return;
23 23
24 if (!desc->chip->set_affinity) 24 if (!desc->chip->set_affinity)
@@ -38,13 +38,13 @@ void move_masked_irq(int irq)
38 * For correct operation this depends on the caller 38 * For correct operation this depends on the caller
39 * masking the irqs. 39 * masking the irqs.
40 */ 40 */
41 if (likely(cpumask_any_and(&desc->pending_mask, cpu_online_mask) 41 if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
42 < nr_cpu_ids)) { 42 < nr_cpu_ids)) {
43 cpumask_and(&desc->affinity, 43 cpumask_and(desc->affinity,
44 &desc->pending_mask, cpu_online_mask); 44 desc->pending_mask, cpu_online_mask);
45 desc->chip->set_affinity(irq, &desc->affinity); 45 desc->chip->set_affinity(irq, desc->affinity);
46 } 46 }
47 cpumask_clear(&desc->pending_mask); 47 cpumask_clear(desc->pending_mask);
48} 48}
49 49
50void move_native_irq(int irq) 50void move_native_irq(int irq)
diff --git a/kernel/irq/numa_migrate.c b/kernel/irq/numa_migrate.c
index aef18ab6b75b..243d6121e50e 100644
--- a/kernel/irq/numa_migrate.c
+++ b/kernel/irq/numa_migrate.c
@@ -33,15 +33,22 @@ static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc)
33 old_desc->kstat_irqs = NULL; 33 old_desc->kstat_irqs = NULL;
34} 34}
35 35
36static void init_copy_one_irq_desc(int irq, struct irq_desc *old_desc, 36static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc,
37 struct irq_desc *desc, int cpu) 37 struct irq_desc *desc, int cpu)
38{ 38{
39 memcpy(desc, old_desc, sizeof(struct irq_desc)); 39 memcpy(desc, old_desc, sizeof(struct irq_desc));
40 if (!init_alloc_desc_masks(desc, cpu, false)) {
41 printk(KERN_ERR "irq %d: can not get new irq_desc cpumask "
42 "for migration.\n", irq);
43 return false;
44 }
40 spin_lock_init(&desc->lock); 45 spin_lock_init(&desc->lock);
41 desc->cpu = cpu; 46 desc->cpu = cpu;
42 lockdep_set_class(&desc->lock, &irq_desc_lock_class); 47 lockdep_set_class(&desc->lock, &irq_desc_lock_class);
43 init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids); 48 init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids);
49 init_copy_desc_masks(old_desc, desc);
44 arch_init_copy_chip_data(old_desc, desc, cpu); 50 arch_init_copy_chip_data(old_desc, desc, cpu);
51 return true;
45} 52}
46 53
47static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc) 54static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc)
@@ -71,12 +78,18 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
71 node = cpu_to_node(cpu); 78 node = cpu_to_node(cpu);
72 desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); 79 desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
73 if (!desc) { 80 if (!desc) {
74 printk(KERN_ERR "irq %d: can not get new irq_desc for migration.\n", irq); 81 printk(KERN_ERR "irq %d: can not get new irq_desc "
82 "for migration.\n", irq);
83 /* still use old one */
84 desc = old_desc;
85 goto out_unlock;
86 }
87 if (!init_copy_one_irq_desc(irq, old_desc, desc, cpu)) {
75 /* still use old one */ 88 /* still use old one */
89 kfree(desc);
76 desc = old_desc; 90 desc = old_desc;
77 goto out_unlock; 91 goto out_unlock;
78 } 92 }
79 init_copy_one_irq_desc(irq, old_desc, desc, cpu);
80 93
81 irq_desc_ptrs[irq] = desc; 94 irq_desc_ptrs[irq] = desc;
82 spin_unlock_irqrestore(&sparse_irq_lock, flags); 95 spin_unlock_irqrestore(&sparse_irq_lock, flags);
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index aae3f742bcec..692363dd591f 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -20,11 +20,11 @@ static struct proc_dir_entry *root_irq_dir;
20static int irq_affinity_proc_show(struct seq_file *m, void *v) 20static int irq_affinity_proc_show(struct seq_file *m, void *v)
21{ 21{
22 struct irq_desc *desc = irq_to_desc((long)m->private); 22 struct irq_desc *desc = irq_to_desc((long)m->private);
23 const struct cpumask *mask = &desc->affinity; 23 const struct cpumask *mask = desc->affinity;
24 24
25#ifdef CONFIG_GENERIC_PENDING_IRQ 25#ifdef CONFIG_GENERIC_PENDING_IRQ
26 if (desc->status & IRQ_MOVE_PENDING) 26 if (desc->status & IRQ_MOVE_PENDING)
27 mask = &desc->pending_mask; 27 mask = desc->pending_mask;
28#endif 28#endif
29 seq_cpumask(m, mask); 29 seq_cpumask(m, mask);
30 seq_putc(m, '\n'); 30 seq_putc(m, '\n');