]> bbs.cooldavid.org Git - net-next-2.6.git/blame - kernel/irq/irqdesc.c
genirq: Provide default irq init flags
[net-next-2.6.git] / kernel / irq / irqdesc.c
CommitLineData
3795de23
TG
1/*
2 * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
3 * Copyright (C) 2005-2006, Thomas Gleixner, Russell King
4 *
5 * This file contains the interrupt descriptor management code
6 *
7 * Detailed information is available in Documentation/DocBook/genericirq
8 *
9 */
10#include <linux/irq.h>
11#include <linux/slab.h>
12#include <linux/module.h>
13#include <linux/interrupt.h>
14#include <linux/kernel_stat.h>
15#include <linux/radix-tree.h>
16
17#include "internals.h"
18
19/*
20 * lockdep: we want to handle all irq_desc locks as a single lock-class:
21 */
22struct lock_class_key irq_desc_lock_class;
23
24#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
25static void __init init_irq_default_affinity(void)
26{
27 alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
28 cpumask_setall(irq_default_affinity);
29}
30#else
31static void __init init_irq_default_affinity(void)
32{
33}
34#endif
35
36int nr_irqs = NR_IRQS;
37EXPORT_SYMBOL_GPL(nr_irqs);
38
39#ifdef CONFIG_SPARSE_IRQ
40
41static struct irq_desc irq_desc_init = {
1318a481 42 .status = IRQ_DEFAULT_INIT_FLAGS,
3795de23
TG
43 .handle_irq = handle_bad_irq,
44 .depth = 1,
45 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
46};
47
48void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr)
49{
50 void *ptr;
51
52 ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs),
53 GFP_ATOMIC, node);
54
55 /*
56 * don't overwite if can not get new one
57 * init_copy_kstat_irqs() could still use old one
58 */
59 if (ptr) {
60 printk(KERN_DEBUG " alloc kstat_irqs on node %d\n", node);
61 desc->kstat_irqs = ptr;
62 }
63}
64
65static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
66{
67 memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
68
69 raw_spin_lock_init(&desc->lock);
70 desc->irq_data.irq = irq;
71#ifdef CONFIG_SMP
72 desc->irq_data.node = node;
73#endif
74 lockdep_set_class(&desc->lock, &irq_desc_lock_class);
75 init_kstat_irqs(desc, node, nr_cpu_ids);
76 if (!desc->kstat_irqs) {
77 printk(KERN_ERR "can not alloc kstat_irqs\n");
78 BUG_ON(1);
79 }
80 if (!alloc_desc_masks(desc, node, false)) {
81 printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
82 BUG_ON(1);
83 }
84 init_desc_masks(desc);
85 arch_init_chip_data(desc, node);
86}
87
88/*
89 * Protect the sparse_irqs:
90 */
91DEFINE_RAW_SPINLOCK(sparse_irq_lock);
92
93static RADIX_TREE(irq_desc_tree, GFP_ATOMIC);
94
95static void set_irq_desc(unsigned int irq, struct irq_desc *desc)
96{
97 radix_tree_insert(&irq_desc_tree, irq, desc);
98}
99
100struct irq_desc *irq_to_desc(unsigned int irq)
101{
102 return radix_tree_lookup(&irq_desc_tree, irq);
103}
104
105void replace_irq_desc(unsigned int irq, struct irq_desc *desc)
106{
107 void **ptr;
108
109 ptr = radix_tree_lookup_slot(&irq_desc_tree, irq);
110 if (ptr)
111 radix_tree_replace_slot(ptr, desc);
112}
113
114static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = {
115 [0 ... NR_IRQS_LEGACY-1] = {
1318a481 116 .status = IRQ_DEFAULT_INIT_FLAGS,
3795de23
TG
117 .handle_irq = handle_bad_irq,
118 .depth = 1,
119 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
120 }
121};
122
123static unsigned int *kstat_irqs_legacy;
124
125int __init early_irq_init(void)
126{
127 struct irq_desc *desc;
128 int legacy_count;
129 int node;
130 int i;
131
132 init_irq_default_affinity();
133
134 /* initialize nr_irqs based on nr_cpu_ids */
135 arch_probe_nr_irqs();
136 printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d\n", NR_IRQS, nr_irqs);
137
138 desc = irq_desc_legacy;
139 legacy_count = ARRAY_SIZE(irq_desc_legacy);
140 node = first_online_node;
141
142 /* allocate based on nr_cpu_ids */
143 kstat_irqs_legacy = kzalloc_node(NR_IRQS_LEGACY * nr_cpu_ids *
144 sizeof(int), GFP_NOWAIT, node);
145
146 irq_desc_init.irq_data.chip = &no_irq_chip;
147
148 for (i = 0; i < legacy_count; i++) {
149 desc[i].irq_data.irq = i;
150 desc[i].irq_data.chip = &no_irq_chip;
151#ifdef CONFIG_SMP
152 desc[i].irq_data.node = node;
153#endif
154 desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
155 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
156 alloc_desc_masks(&desc[i], node, true);
157 init_desc_masks(&desc[i]);
158 set_irq_desc(i, &desc[i]);
159 }
160
161 return arch_early_irq_init();
162}
163
164struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
165{
166 struct irq_desc *desc;
167 unsigned long flags;
168
169 if (irq >= nr_irqs) {
170 WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
171 irq, nr_irqs);
172 return NULL;
173 }
174
175 desc = irq_to_desc(irq);
176 if (desc)
177 return desc;
178
179 raw_spin_lock_irqsave(&sparse_irq_lock, flags);
180
181 /* We have to check it to avoid races with another CPU */
182 desc = irq_to_desc(irq);
183 if (desc)
184 goto out_unlock;
185
186 desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
187
188 printk(KERN_DEBUG " alloc irq_desc for %d on node %d\n", irq, node);
189 if (!desc) {
190 printk(KERN_ERR "can not alloc irq_desc\n");
191 BUG_ON(1);
192 }
193 init_one_irq_desc(irq, desc, node);
194
195 set_irq_desc(irq, desc);
196
197out_unlock:
198 raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
199
200 return desc;
201}
202
203#else /* !CONFIG_SPARSE_IRQ */
204
205struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
206 [0 ... NR_IRQS-1] = {
1318a481 207 .status = IRQ_DEFAULT_INIT_FLAGS,
3795de23
TG
208 .handle_irq = handle_bad_irq,
209 .depth = 1,
210 .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
211 }
212};
213
214static unsigned int kstat_irqs_all[NR_IRQS][NR_CPUS];
215int __init early_irq_init(void)
216{
217 struct irq_desc *desc;
218 int count;
219 int i;
220
221 init_irq_default_affinity();
222
223 printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);
224
225 desc = irq_desc;
226 count = ARRAY_SIZE(irq_desc);
227
228 for (i = 0; i < count; i++) {
229 desc[i].irq_data.irq = i;
230 desc[i].irq_data.chip = &no_irq_chip;
231 alloc_desc_masks(&desc[i], 0, true);
232 init_desc_masks(&desc[i]);
233 desc[i].kstat_irqs = kstat_irqs_all[i];
154cd387 234 lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
3795de23
TG
235 }
236 return arch_early_irq_init();
237}
238
239struct irq_desc *irq_to_desc(unsigned int irq)
240{
241 return (irq < NR_IRQS) ? irq_desc + irq : NULL;
242}
243
244struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
245{
246 return irq_to_desc(irq);
247}
248#endif /* !CONFIG_SPARSE_IRQ */
249
250void clear_kstat_irqs(struct irq_desc *desc)
251{
252 memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs)));
253}
254
3795de23
TG
255unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
256{
257 struct irq_desc *desc = irq_to_desc(irq);
258 return desc ? desc->kstat_irqs[cpu] : 0;
259}