genirq: Distangle kernel/irq/handle.c
[pandora-kernel.git] / kernel / irq / irqdesc.c
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  */
22 struct lock_class_key irq_desc_lock_class;
23
24 #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_HARDIRQS)
25 static 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
31 static void __init init_irq_default_affinity(void)
32 {
33 }
34 #endif
35
36 int nr_irqs = NR_IRQS;
37 EXPORT_SYMBOL_GPL(nr_irqs);
38
39 #ifdef CONFIG_SPARSE_IRQ
40
41 static struct irq_desc irq_desc_init = {
42         .status         = IRQ_DISABLED,
43         .handle_irq     = handle_bad_irq,
44         .depth          = 1,
45         .lock           = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
46 };
47
48 void __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
65 static 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  */
91 DEFINE_RAW_SPINLOCK(sparse_irq_lock);
92
93 static RADIX_TREE(irq_desc_tree, GFP_ATOMIC);
94
95 static void set_irq_desc(unsigned int irq, struct irq_desc *desc)
96 {
97         radix_tree_insert(&irq_desc_tree, irq, desc);
98 }
99
100 struct irq_desc *irq_to_desc(unsigned int irq)
101 {
102         return radix_tree_lookup(&irq_desc_tree, irq);
103 }
104
105 void 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
114 static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = {
115         [0 ... NR_IRQS_LEGACY-1] = {
116                 .status         = IRQ_DISABLED,
117                 .handle_irq     = handle_bad_irq,
118                 .depth          = 1,
119                 .lock           = __RAW_SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
120         }
121 };
122
123 static unsigned int *kstat_irqs_legacy;
124
125 int __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
164 struct 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
197 out_unlock:
198         raw_spin_unlock_irqrestore(&sparse_irq_lock, flags);
199
200         return desc;
201 }
202
203 #else /* !CONFIG_SPARSE_IRQ */
204
205 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
206         [0 ... NR_IRQS-1] = {
207                 .status         = IRQ_DISABLED,
208                 .handle_irq     = handle_bad_irq,
209                 .depth          = 1,
210                 .lock           = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
211         }
212 };
213
214 static unsigned int kstat_irqs_all[NR_IRQS][NR_CPUS];
215 int __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];
234         }
235         return arch_early_irq_init();
236 }
237
238 struct irq_desc *irq_to_desc(unsigned int irq)
239 {
240         return (irq < NR_IRQS) ? irq_desc + irq : NULL;
241 }
242
243 struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
244 {
245         return irq_to_desc(irq);
246 }
247 #endif /* !CONFIG_SPARSE_IRQ */
248
249 void clear_kstat_irqs(struct irq_desc *desc)
250 {
251         memset(desc->kstat_irqs, 0, nr_cpu_ids * sizeof(*(desc->kstat_irqs)));
252 }
253
254 void early_init_irq_lock_class(void)
255 {
256         struct irq_desc *desc;
257         int i;
258
259         for_each_irq_desc(i, desc) {
260                 lockdep_set_class(&desc->lock, &irq_desc_lock_class);
261         }
262 }
263
264 unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
265 {
266         struct irq_desc *desc = irq_to_desc(irq);
267         return desc ? desc->kstat_irqs[cpu] : 0;
268 }
269 EXPORT_SYMBOL(kstat_irqs_cpu);