aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/io_apic.c130
-rw-r--r--arch/x86/kernel/irq_32.c8
-rw-r--r--arch/x86/kernel/irq_64.c8
-rw-r--r--drivers/char/random.c31
-rw-r--r--drivers/pci/htirq.c19
-rw-r--r--drivers/pci/intr_remapping.c75
-rw-r--r--fs/proc/proc_misc.c43
-rw-r--r--include/linux/irq.h20
-rw-r--r--kernel/irq/handle.c114
9 files changed, 10 insertions, 438 deletions
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
index f959acbc0db2..683610517d2a 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/io_apic.c
@@ -111,9 +111,6 @@ struct irq_cfg;
111struct irq_pin_list; 111struct irq_pin_list;
112struct irq_cfg { 112struct irq_cfg {
113 unsigned int irq; 113 unsigned int irq;
114#ifdef CONFIG_HAVE_SPARSE_IRQ
115 struct irq_cfg *next;
116#endif
117 struct irq_pin_list *irq_2_pin; 114 struct irq_pin_list *irq_2_pin;
118 cpumask_t domain; 115 cpumask_t domain;
119 cpumask_t old_domain; 116 cpumask_t old_domain;
@@ -151,15 +148,6 @@ static void init_one_irq_cfg(struct irq_cfg *cfg)
151 148
152static struct irq_cfg *irq_cfgx; 149static struct irq_cfg *irq_cfgx;
153 150
154#ifdef CONFIG_HAVE_SPARSE_IRQ
155/*
156 * Protect the irq_cfgx_free freelist:
157 */
158static DEFINE_SPINLOCK(irq_cfg_lock);
159
160static struct irq_cfg *irq_cfgx_free;
161#endif
162
163static void __init init_work(void *data) 151static void __init init_work(void *data)
164{ 152{
165 struct dyn_array *da = data; 153 struct dyn_array *da = data;
@@ -174,114 +162,7 @@ static void __init init_work(void *data)
174 legacy_count = ARRAY_SIZE(irq_cfg_legacy); 162 legacy_count = ARRAY_SIZE(irq_cfg_legacy);
175 for (i = legacy_count; i < *da->nr; i++) 163 for (i = legacy_count; i < *da->nr; i++)
176 init_one_irq_cfg(&cfg[i]); 164 init_one_irq_cfg(&cfg[i]);
177
178#ifdef CONFIG_HAVE_SPARSE_IRQ
179 for (i = 1; i < *da->nr; i++)
180 cfg[i-1].next = &cfg[i];
181
182 irq_cfgx_free = &irq_cfgx[legacy_count];
183 irq_cfgx[legacy_count - 1].next = NULL;
184#endif
185}
186
187#ifdef CONFIG_HAVE_SPARSE_IRQ
188/* need to be biger than size of irq_cfg_legacy */
189static int nr_irq_cfg = 32;
190
191static int __init parse_nr_irq_cfg(char *arg)
192{
193 if (arg) {
194 nr_irq_cfg = simple_strtoul(arg, NULL, 0);
195 if (nr_irq_cfg < 32)
196 nr_irq_cfg = 32;
197 }
198 return 0;
199}
200
201early_param("nr_irq_cfg", parse_nr_irq_cfg);
202
203#define for_each_irq_cfg(irqX, cfg) \
204 for (cfg = irq_cfgx, irqX = cfg->irq; cfg; cfg = cfg->next, irqX = cfg ? cfg->irq : -1U)
205
206
207DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work);
208
209static struct irq_cfg *irq_cfg(unsigned int irq)
210{
211 struct irq_cfg *cfg;
212
213 cfg = irq_cfgx;
214 while (cfg) {
215 if (cfg->irq == irq)
216 return cfg;
217
218 cfg = cfg->next;
219 }
220
221 return NULL;
222}
223
224static struct irq_cfg *irq_cfg_alloc(unsigned int irq)
225{
226 struct irq_cfg *cfg, *cfg_pri;
227 unsigned long flags;
228 int count = 0;
229 int i;
230
231 cfg_pri = cfg = irq_cfgx;
232 while (cfg) {
233 if (cfg->irq == irq)
234 return cfg;
235
236 cfg_pri = cfg;
237 cfg = cfg->next;
238 count++;
239 }
240
241 spin_lock_irqsave(&irq_cfg_lock, flags);
242 if (!irq_cfgx_free) {
243 unsigned long phys;
244 unsigned long total_bytes;
245 /*
246 * we run out of pre-allocate ones, allocate more
247 */
248 printk(KERN_DEBUG "try to get more irq_cfg %d\n", nr_irq_cfg);
249
250 total_bytes = sizeof(struct irq_cfg) * nr_irq_cfg;
251 if (after_bootmem)
252 cfg = kzalloc(total_bytes, GFP_ATOMIC);
253 else
254 cfg = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0);
255
256 if (!cfg)
257 panic("please boot with nr_irq_cfg= %d\n", count * 2);
258
259 phys = __pa(cfg);
260 printk(KERN_DEBUG "irq_cfg ==> [%#lx - %#lx]\n", phys, phys + total_bytes);
261
262 for (i = 0; i < nr_irq_cfg; i++)
263 init_one_irq_cfg(&cfg[i]);
264
265 for (i = 1; i < nr_irq_cfg; i++)
266 cfg[i-1].next = &cfg[i];
267
268 irq_cfgx_free = cfg;
269 }
270
271 cfg = irq_cfgx_free;
272 irq_cfgx_free = irq_cfgx_free->next;
273 cfg->next = NULL;
274 if (cfg_pri)
275 cfg_pri->next = cfg;
276 else
277 irq_cfgx = cfg;
278 cfg->irq = irq;
279
280 spin_unlock_irqrestore(&irq_cfg_lock, flags);
281
282 return cfg;
283} 165}
284#else
285 166
286#define for_each_irq_cfg(irq, cfg) \ 167#define for_each_irq_cfg(irq, cfg) \
287 for (irq = 0, cfg = &irq_cfgx[irq]; irq < nr_irqs; irq++, cfg = &irq_cfgx[irq]) 168 for (irq = 0, cfg = &irq_cfgx[irq]; irq < nr_irqs; irq++, cfg = &irq_cfgx[irq])
@@ -290,17 +171,16 @@ DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irqs, PAGE_SIZE, init_work
290 171
291struct irq_cfg *irq_cfg(unsigned int irq) 172struct irq_cfg *irq_cfg(unsigned int irq)
292{ 173{
293 if (irq < nr_irqs) 174 if (irq < nr_irqs)
294 return &irq_cfgx[irq]; 175 return &irq_cfgx[irq];
295 176
296 return NULL; 177 return NULL;
297} 178}
298struct irq_cfg *irq_cfg_alloc(unsigned int irq) 179struct irq_cfg *irq_cfg_alloc(unsigned int irq)
299{ 180{
300 return irq_cfg(irq); 181 return irq_cfg(irq);
301} 182}
302 183
303#endif
304/* 184/*
305 * This is performance-critical, we want to do it O(1) 185 * This is performance-critical, we want to do it O(1)
306 * 186 *
@@ -3068,9 +2948,7 @@ unsigned int create_irq_nr(unsigned int irq_want)
3068 unsigned long flags; 2948 unsigned long flags;
3069 struct irq_cfg *cfg_new; 2949 struct irq_cfg *cfg_new;
3070 2950
3071#ifndef CONFIG_HAVE_SPARSE_IRQ
3072 irq_want = nr_irqs - 1; 2951 irq_want = nr_irqs - 1;
3073#endif
3074 2952
3075 irq = 0; 2953 irq = 0;
3076 spin_lock_irqsave(&vector_lock, flags); 2954 spin_lock_irqsave(&vector_lock, flags);
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 001772ffc918..ccf6c1bf7120 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -272,20 +272,12 @@ int show_interrupts(struct seq_file *p, void *v)
272 struct irq_desc *desc = NULL; 272 struct irq_desc *desc = NULL;
273 int tail = 0; 273 int tail = 0;
274 274
275#ifdef CONFIG_HAVE_SPARSE_IRQ
276 desc = (struct irq_desc *)v;
277 entries = -1U;
278 i = desc->irq;
279 if (!desc->next)
280 tail = 1;
281#else
282 entries = nr_irqs - 1; 275 entries = nr_irqs - 1;
283 i = *(loff_t *) v; 276 i = *(loff_t *) v;
284 if (i == nr_irqs) 277 if (i == nr_irqs)
285 tail = 1; 278 tail = 1;
286 else 279 else
287 desc = irq_to_desc(i); 280 desc = irq_to_desc(i);
288#endif
289 281
290 if (i == 0) { 282 if (i == 0) {
291 seq_printf(p, " "); 283 seq_printf(p, " ");
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index ec2661091283..21f53b911113 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -77,20 +77,12 @@ int show_interrupts(struct seq_file *p, void *v)
77 struct irq_desc *desc = NULL; 77 struct irq_desc *desc = NULL;
78 int tail = 0; 78 int tail = 0;
79 79
80#ifdef CONFIG_HAVE_SPARSE_IRQ
81 desc = (struct irq_desc *)v;
82 entries = -1U;
83 i = desc->irq;
84 if (!desc->next)
85 tail = 1;
86#else
87 entries = nr_irqs - 1; 80 entries = nr_irqs - 1;
88 i = *(loff_t *) v; 81 i = *(loff_t *) v;
89 if (i == nr_irqs) 82 if (i == nr_irqs)
90 tail = 1; 83 tail = 1;
91 else 84 else
92 desc = irq_to_desc(i); 85 desc = irq_to_desc(i);
93#endif
94 86
95 if (i == 0) { 87 if (i == 0) {
96 seq_printf(p, " "); 88 seq_printf(p, " ");
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 60c9c7ee6b2c..9ce80213007b 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -558,8 +558,6 @@ struct timer_rand_state {
558 unsigned dont_count_entropy:1; 558 unsigned dont_count_entropy:1;
559}; 559};
560 560
561#ifndef CONFIG_HAVE_SPARSE_IRQ
562
563#ifdef CONFIG_HAVE_DYN_ARRAY 561#ifdef CONFIG_HAVE_DYN_ARRAY
564static struct timer_rand_state **irq_timer_state; 562static struct timer_rand_state **irq_timer_state;
565DEFINE_DYN_ARRAY(irq_timer_state, sizeof(struct timer_rand_state *), nr_irqs, PAGE_SIZE, NULL); 563DEFINE_DYN_ARRAY(irq_timer_state, sizeof(struct timer_rand_state *), nr_irqs, PAGE_SIZE, NULL);
@@ -583,33 +581,6 @@ static void set_timer_rand_state(unsigned int irq, struct timer_rand_state *stat
583 irq_timer_state[irq] = state; 581 irq_timer_state[irq] = state;
584} 582}
585 583
586#else
587
588static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
589{
590 struct irq_desc *desc;
591
592 desc = irq_to_desc(irq);
593
594 if (!desc)
595 return NULL;
596
597 return desc->timer_rand_state;
598}
599
600static void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
601{
602 struct irq_desc *desc;
603
604 desc = irq_to_desc(irq);
605
606 if (!desc)
607 return;
608
609 desc->timer_rand_state = state;
610}
611#endif
612
613static struct timer_rand_state input_timer_state; 584static struct timer_rand_state input_timer_state;
614 585
615/* 586/*
@@ -967,10 +938,8 @@ void rand_initialize_irq(int irq)
967{ 938{
968 struct timer_rand_state *state; 939 struct timer_rand_state *state;
969 940
970#ifndef CONFIG_HAVE_SPARSE_IRQ
971 if (irq >= nr_irqs) 941 if (irq >= nr_irqs)
972 return; 942 return;
973#endif
974 943
975 state = get_timer_rand_state(irq); 944 state = get_timer_rand_state(irq);
976 945
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index 9e4929a00832..bf7d6ce9bbb3 100644
--- a/drivers/pci/htirq.c
+++ b/drivers/pci/htirq.c
@@ -82,18 +82,6 @@ void unmask_ht_irq(unsigned int irq)
82 write_ht_irq_msg(irq, &msg); 82 write_ht_irq_msg(irq, &msg);
83} 83}
84 84
85static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
86{
87 unsigned int irq;
88
89 irq = dev->bus->number;
90 irq <<= 8;
91 irq |= dev->devfn;
92 irq <<= 12;
93
94 return irq;
95}
96
97/** 85/**
98 * __ht_create_irq - create an irq and attach it to a device. 86 * __ht_create_irq - create an irq and attach it to a device.
99 * @dev: The hypertransport device to find the irq capability on. 87 * @dev: The hypertransport device to find the irq capability on.
@@ -110,7 +98,6 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
110 int max_irq; 98 int max_irq;
111 int pos; 99 int pos;
112 int irq; 100 int irq;
113 unsigned int irq_want;
114 101
115 pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ); 102 pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);
116 if (!pos) 103 if (!pos)
@@ -138,12 +125,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
138 cfg->msg.address_lo = 0xffffffff; 125 cfg->msg.address_lo = 0xffffffff;
139 cfg->msg.address_hi = 0xffffffff; 126 cfg->msg.address_hi = 0xffffffff;
140 127
141 irq_want= build_irq_for_pci_dev(dev);
142#ifdef CONFIG_HAVE_SPARSE_IRQ
143 irq = create_irq_nr(irq_want + idx);
144#else
145 irq = create_irq(); 128 irq = create_irq();
146#endif 129
147 if (irq <= 0) { 130 if (irq <= 0) {
148 kfree(cfg); 131 kfree(cfg);
149 return -EBUSY; 132 return -EBUSY;
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 2dcf973890c4..0f43b265eee6 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -19,78 +19,6 @@ struct irq_2_iommu {
19 u8 irte_mask; 19 u8 irte_mask;
20}; 20};
21 21
22#ifdef CONFIG_HAVE_SPARSE_IRQ
23static struct irq_2_iommu *irq_2_iommuX;
24/* fill one page ? */
25static int nr_irq_2_iommu = 0x100;
26static int irq_2_iommu_index;
27DEFINE_DYN_ARRAY(irq_2_iommuX, sizeof(struct irq_2_iommu), nr_irq_2_iommu, PAGE_SIZE, NULL);
28
29extern void *__alloc_bootmem_nopanic(unsigned long size,
30 unsigned long align,
31 unsigned long goal);
32
33static struct irq_2_iommu *get_one_free_irq_2_iommu(int not_used)
34{
35 struct irq_2_iommu *iommu;
36 unsigned long total_bytes;
37
38 if (irq_2_iommu_index >= nr_irq_2_iommu) {
39 /*
40 * we run out of pre-allocate ones, allocate more
41 */
42 printk(KERN_DEBUG "try to get more irq_2_iommu %d\n", nr_irq_2_iommu);
43
44 total_bytes = sizeof(struct irq_2_iommu)*nr_irq_2_iommu;
45
46 if (after_bootmem)
47 iommu = kzalloc(total_bytes, GFP_ATOMIC);
48 else
49 iommu = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0);
50
51 if (!iommu)
52 panic("can not get more irq_2_iommu\n");
53
54 irq_2_iommuX = iommu;
55 irq_2_iommu_index = 0;
56 }
57
58 iommu = &irq_2_iommuX[irq_2_iommu_index];
59 irq_2_iommu_index++;
60 return iommu;
61}
62
63static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
64{
65 struct irq_desc *desc;
66
67 desc = irq_to_desc(irq);
68
69 BUG_ON(!desc);
70
71 return desc->irq_2_iommu;
72}
73
74static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
75{
76 struct irq_desc *desc;
77 struct irq_2_iommu *irq_iommu;
78
79 /*
80 * alloc irq desc if not allocated already.
81 */
82 desc = irq_to_desc_alloc(irq);
83
84 irq_iommu = desc->irq_2_iommu;
85
86 if (!irq_iommu)
87 desc->irq_2_iommu = get_one_free_irq_2_iommu(irq);
88
89 return desc->irq_2_iommu;
90}
91
92#else /* !CONFIG_HAVE_SPARSE_IRQ */
93
94#ifdef CONFIG_HAVE_DYN_ARRAY 22#ifdef CONFIG_HAVE_DYN_ARRAY
95static struct irq_2_iommu *irq_2_iommuX; 23static struct irq_2_iommu *irq_2_iommuX;
96DEFINE_DYN_ARRAY(irq_2_iommuX, sizeof(struct irq_2_iommu), nr_irqs, PAGE_SIZE, NULL); 24DEFINE_DYN_ARRAY(irq_2_iommuX, sizeof(struct irq_2_iommu), nr_irqs, PAGE_SIZE, NULL);
@@ -109,7 +37,6 @@ static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
109{ 37{
110 return irq_2_iommu(irq); 38 return irq_2_iommu(irq);
111} 39}
112#endif
113 40
114static DEFINE_SPINLOCK(irq_2_ir_lock); 41static DEFINE_SPINLOCK(irq_2_ir_lock);
115 42
@@ -166,11 +93,9 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
166 if (!count) 93 if (!count)
167 return -1; 94 return -1;
168 95
169#ifndef CONFIG_HAVE_SPARSE_IRQ
170 /* protect irq_2_iommu_alloc later */ 96 /* protect irq_2_iommu_alloc later */
171 if (irq >= nr_irqs) 97 if (irq >= nr_irqs)
172 return -1; 98 return -1;
173#endif
174 99
175 /* 100 /*
176 * start the IRTE search from index 0. 101 * start the IRTE search from index 0.
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index d68c3592fe4a..3f5c7b9d1a70 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -529,13 +529,10 @@ static int show_stat(struct seq_file *p, void *v)
529 softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq); 529 softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
530 steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal); 530 steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
531 guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest); 531 guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
532
532 for_each_irq_desc(j, desc) 533 for_each_irq_desc(j, desc)
533 { 534 sum += kstat_irqs_cpu(j, i);
534 unsigned int temp;
535 535
536 temp = kstat_irqs_cpu(j, i);
537 sum += temp;
538 }
539 sum += arch_irq_stat_cpu(i); 536 sum += arch_irq_stat_cpu(i);
540 } 537 }
541 sum += arch_irq_stat(); 538 sum += arch_irq_stat();
@@ -578,21 +575,13 @@ static int show_stat(struct seq_file *p, void *v)
578 seq_printf(p, "intr %llu", (unsigned long long)sum); 575 seq_printf(p, "intr %llu", (unsigned long long)sum);
579 576
580 /* sum again ? it could be updated? */ 577 /* sum again ? it could be updated? */
581 for_each_irq_desc(j, desc) 578 for_each_irq_desc(j, desc) {
582 {
583 per_irq_sum = 0; 579 per_irq_sum = 0;
584 for_each_possible_cpu(i) {
585 unsigned int temp;
586 580
587 temp = kstat_irqs_cpu(j, i); 581 for_each_possible_cpu(i)
588 per_irq_sum += temp; 582 per_irq_sum += kstat_irqs_cpu(j, i);
589 }
590 583
591#ifdef CONFIG_HAVE_SPARSE_IRQ
592 seq_printf(p, " %#x:%u", j, per_irq_sum);
593#else
594 seq_printf(p, " %u", per_irq_sum); 584 seq_printf(p, " %u", per_irq_sum);
595#endif
596 } 585 }
597 586
598 seq_printf(p, 587 seq_printf(p,
@@ -645,36 +634,14 @@ static const struct file_operations proc_stat_operations = {
645 */ 634 */
646static void *int_seq_start(struct seq_file *f, loff_t *pos) 635static void *int_seq_start(struct seq_file *f, loff_t *pos)
647{ 636{
648#ifdef CONFIG_HAVE_SPARSE_IRQ
649 struct irq_desc *desc;
650 int irq;
651 int count = *pos;
652
653 for_each_irq_desc(irq, desc) {
654 if (count-- == 0)
655 return desc;
656 }
657
658 return NULL;
659#else
660 return (*pos <= nr_irqs) ? pos : NULL; 637 return (*pos <= nr_irqs) ? pos : NULL;
661#endif
662} 638}
663 639
664 640
665static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos) 641static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
666{ 642{
667#ifdef CONFIG_HAVE_SPARSE_IRQ
668 struct irq_desc *desc;
669
670 desc = ((struct irq_desc *)v)->next;
671 (*pos)++;
672
673 return desc;
674#else
675 (*pos)++; 643 (*pos)++;
676 return (*pos <= nr_irqs) ? pos : NULL; 644 return (*pos <= nr_irqs) ? pos : NULL;
677#endif
678} 645}
679 646
680static void int_seq_stop(struct seq_file *f, void *v) 647static void int_seq_stop(struct seq_file *f, void *v)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 7d1adacaadb4..68e0f3f9df30 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -167,16 +167,9 @@ struct irq_2_iommu;
167 */ 167 */
168struct irq_desc { 168struct irq_desc {
169 unsigned int irq; 169 unsigned int irq;
170#ifdef CONFIG_HAVE_SPARSE_IRQ
171 struct irq_desc *next;
172 struct timer_rand_state *timer_rand_state;
173#endif
174#ifdef CONFIG_HAVE_DYN_ARRAY 170#ifdef CONFIG_HAVE_DYN_ARRAY
175 unsigned int *kstat_irqs; 171 unsigned int *kstat_irqs;
176#endif 172#endif
177#if defined(CONFIG_INTR_REMAP) && defined(CONFIG_HAVE_SPARSE_IRQ)
178 struct irq_2_iommu *irq_2_iommu;
179#endif
180 irq_flow_handler_t handle_irq; 173 irq_flow_handler_t handle_irq;
181 struct irq_chip *chip; 174 struct irq_chip *chip;
182 struct msi_desc *msi_desc; 175 struct msi_desc *msi_desc;
@@ -205,8 +198,6 @@ struct irq_desc {
205} ____cacheline_internodealigned_in_smp; 198} ____cacheline_internodealigned_in_smp;
206 199
207 200
208#ifndef CONFIG_HAVE_SPARSE_IRQ
209
210#ifndef CONFIG_HAVE_DYN_ARRAY 201#ifndef CONFIG_HAVE_DYN_ARRAY
211/* could be removed if we get rid of all irq_desc reference */ 202/* could be removed if we get rid of all irq_desc reference */
212extern struct irq_desc irq_desc[NR_IRQS]; 203extern struct irq_desc irq_desc[NR_IRQS];
@@ -224,17 +215,6 @@ static inline struct irq_desc *irq_to_desc_alloc(unsigned int irq)
224 return irq_to_desc(irq); 215 return irq_to_desc(irq);
225} 216}
226 217
227#else
228
229extern struct irq_desc *irq_to_desc(unsigned int irq);
230extern struct irq_desc *irq_to_desc_alloc(unsigned int irq);
231
232extern struct irq_desc *sparse_irqs;
233#define for_each_irq_desc(irqX, desc) \
234 for (desc = sparse_irqs, irqX = desc->irq; desc; desc = desc->next, irqX = desc ? desc->irq : -1U)
235
236#endif
237
238#ifdef CONFIG_HAVE_DYN_ARRAY 218#ifdef CONFIG_HAVE_DYN_ARRAY
239#define kstat_irqs_this_cpu(DESC) \ 219#define kstat_irqs_this_cpu(DESC) \
240 ((DESC)->kstat_irqs[smp_processor_id()]) 220 ((DESC)->kstat_irqs[smp_processor_id()])
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index c19896f895f9..f837133cdfbe 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -111,15 +111,6 @@ static void init_kstat_irqs(struct irq_desc *desc, int nr_desc, int nr)
111 } 111 }
112} 112}
113 113
114#ifdef CONFIG_HAVE_SPARSE_IRQ
115/*
116 * Protect the sparse_irqs_free freelist:
117 */
118static DEFINE_SPINLOCK(sparse_irq_lock);
119static struct irq_desc *sparse_irqs_free;
120struct irq_desc *sparse_irqs;
121#endif
122
123static void __init init_work(void *data) 114static void __init init_work(void *data)
124{ 115{
125 struct dyn_array *da = data; 116 struct dyn_array *da = data;
@@ -130,121 +121,16 @@ static void __init init_work(void *data)
130 121
131 for (i = 0; i < *da->nr; i++) { 122 for (i = 0; i < *da->nr; i++) {
132 init_one_irq_desc(&desc[i]); 123 init_one_irq_desc(&desc[i]);
133#ifndef CONFIG_HAVE_SPARSE_IRQ
134 desc[i].irq = i; 124 desc[i].irq = i;
135#endif
136 } 125 }
137 126
138 /* init kstat_irqs, nr_cpu_ids is ready already */ 127 /* init kstat_irqs, nr_cpu_ids is ready already */
139 init_kstat_irqs(desc, *da->nr, nr_cpu_ids); 128 init_kstat_irqs(desc, *da->nr, nr_cpu_ids);
140
141#ifdef CONFIG_HAVE_SPARSE_IRQ
142 for (i = 1; i < *da->nr; i++)
143 desc[i-1].next = &desc[i];
144
145 sparse_irqs_free = sparse_irqs;
146 sparse_irqs = NULL;
147#endif
148}
149
150#ifdef CONFIG_HAVE_SPARSE_IRQ
151static int nr_irq_desc = 32;
152
153static int __init parse_nr_irq_desc(char *arg)
154{
155 if (arg)
156 nr_irq_desc = simple_strtoul(arg, NULL, 0);
157 return 0;
158}
159
160early_param("nr_irq_desc", parse_nr_irq_desc);
161
162DEFINE_DYN_ARRAY(sparse_irqs, sizeof(struct irq_desc), nr_irq_desc, PAGE_SIZE, init_work);
163
164struct irq_desc *irq_to_desc(unsigned int irq)
165{
166 struct irq_desc *desc;
167
168 desc = sparse_irqs;
169 while (desc) {
170 if (desc->irq == irq)
171 return desc;
172
173 desc = desc->next;
174 }
175 return NULL;
176} 129}
177 130
178struct irq_desc *irq_to_desc_alloc(unsigned int irq)
179{
180 struct irq_desc *desc, *desc_pri;
181 unsigned long flags;
182 int count = 0;
183 int i;
184
185 desc_pri = desc = sparse_irqs;
186 while (desc) {
187 if (desc->irq == irq)
188 return desc;
189
190 desc_pri = desc;
191 desc = desc->next;
192 count++;
193 }
194
195 spin_lock_irqsave(&sparse_irq_lock, flags);
196 /*
197 * we run out of pre-allocate ones, allocate more
198 */
199 if (!sparse_irqs_free) {
200 unsigned long phys;
201 unsigned long total_bytes;
202
203 printk(KERN_DEBUG "try to get more irq_desc %d\n", nr_irq_desc);
204
205 total_bytes = sizeof(struct irq_desc) * nr_irq_desc;
206 if (after_bootmem)
207 desc = kzalloc(total_bytes, GFP_ATOMIC);
208 else
209 desc = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0);
210
211 if (!desc)
212 panic("please boot with nr_irq_desc= %d\n", count * 2);
213
214 phys = __pa(desc);
215 printk(KERN_DEBUG "irq_desc ==> [%#lx - %#lx]\n", phys, phys + total_bytes);
216
217 for (i = 0; i < nr_irq_desc; i++)
218 init_one_irq_desc(&desc[i]);
219
220 for (i = 1; i < nr_irq_desc; i++)
221 desc[i-1].next = &desc[i];
222
223 /* init kstat_irqs, nr_cpu_ids is ready already */
224 init_kstat_irqs(desc, nr_irq_desc, nr_cpu_ids);
225
226 sparse_irqs_free = desc;
227 }
228
229 desc = sparse_irqs_free;
230 sparse_irqs_free = sparse_irqs_free->next;
231 desc->next = NULL;
232 if (desc_pri)
233 desc_pri->next = desc;
234 else
235 sparse_irqs = desc;
236 desc->irq = irq;
237
238 spin_unlock_irqrestore(&sparse_irq_lock, flags);
239
240 return desc;
241}
242#else
243struct irq_desc *irq_desc; 131struct irq_desc *irq_desc;
244DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work); 132DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work);
245 133
246#endif
247
248#else 134#else
249 135
250struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { 136struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {