diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-08-19 23:50:09 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-16 10:52:32 -0400 |
commit | 7f95ec9e4c12fd067febfd57532da1166d75d858 (patch) | |
tree | b395b6776485f60e3f5d9d820ad665161ef76771 /kernel/irq | |
parent | 3060d6fe28570640c2d7d66d38b9eaa848c3b9e3 (diff) |
x86: move kstat_irqs from kstat to irq_desc
based on Eric's patch ...
together mold it with dyn_array for irq_desc, will allcate kstat_irqs for
nr_irq_desc alltogether if needed. -- at that point nr_cpus is known already.
v2: make sure system without generic_hardirqs works they don't have irq_desc
v3: fix merging
v4: [mingo@elte.hu] fix typo
[ mingo@elte.hu ] irq: build fix
fix:
arch/x86/xen/spinlock.c: In function 'xen_spin_lock_slow':
arch/x86/xen/spinlock.c:90: error: 'struct kernel_stat' has no member named 'irqs'
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/irq')
-rw-r--r-- | kernel/irq/chip.c | 15 | ||||
-rw-r--r-- | kernel/irq/handle.c | 97 |
2 files changed, 75 insertions, 37 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 76c225cf4b26..2aa3d4b2fce8 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -312,14 +312,13 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) | |||
312 | { | 312 | { |
313 | struct irqaction *action; | 313 | struct irqaction *action; |
314 | irqreturn_t action_ret; | 314 | irqreturn_t action_ret; |
315 | const unsigned int cpu = smp_processor_id(); | ||
316 | 315 | ||
317 | spin_lock(&desc->lock); | 316 | spin_lock(&desc->lock); |
318 | 317 | ||
319 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 318 | if (unlikely(desc->status & IRQ_INPROGRESS)) |
320 | goto out_unlock; | 319 | goto out_unlock; |
321 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 320 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
322 | kstat_cpu(cpu).irqs[irq]++; | 321 | kstat_irqs_this_cpu(desc)++; |
323 | 322 | ||
324 | action = desc->action; | 323 | action = desc->action; |
325 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) | 324 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) |
@@ -351,7 +350,6 @@ out_unlock: | |||
351 | void | 350 | void |
352 | handle_level_irq(unsigned int irq, struct irq_desc *desc) | 351 | handle_level_irq(unsigned int irq, struct irq_desc *desc) |
353 | { | 352 | { |
354 | unsigned int cpu = smp_processor_id(); | ||
355 | struct irqaction *action; | 353 | struct irqaction *action; |
356 | irqreturn_t action_ret; | 354 | irqreturn_t action_ret; |
357 | 355 | ||
@@ -361,7 +359,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
361 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 359 | if (unlikely(desc->status & IRQ_INPROGRESS)) |
362 | goto out_unlock; | 360 | goto out_unlock; |
363 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 361 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
364 | kstat_cpu(cpu).irqs[irq]++; | 362 | kstat_irqs_this_cpu(desc)++; |
365 | 363 | ||
366 | /* | 364 | /* |
367 | * If its disabled or no action available | 365 | * If its disabled or no action available |
@@ -399,7 +397,6 @@ out_unlock: | |||
399 | void | 397 | void |
400 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | 398 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) |
401 | { | 399 | { |
402 | unsigned int cpu = smp_processor_id(); | ||
403 | struct irqaction *action; | 400 | struct irqaction *action; |
404 | irqreturn_t action_ret; | 401 | irqreturn_t action_ret; |
405 | 402 | ||
@@ -409,7 +406,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
409 | goto out; | 406 | goto out; |
410 | 407 | ||
411 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 408 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
412 | kstat_cpu(cpu).irqs[irq]++; | 409 | kstat_irqs_this_cpu(desc)++; |
413 | 410 | ||
414 | /* | 411 | /* |
415 | * If its disabled or no action available | 412 | * If its disabled or no action available |
@@ -458,8 +455,6 @@ out: | |||
458 | void | 455 | void |
459 | handle_edge_irq(unsigned int irq, struct irq_desc *desc) | 456 | handle_edge_irq(unsigned int irq, struct irq_desc *desc) |
460 | { | 457 | { |
461 | const unsigned int cpu = smp_processor_id(); | ||
462 | |||
463 | spin_lock(&desc->lock); | 458 | spin_lock(&desc->lock); |
464 | 459 | ||
465 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); | 460 | desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); |
@@ -476,7 +471,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
476 | goto out_unlock; | 471 | goto out_unlock; |
477 | } | 472 | } |
478 | 473 | ||
479 | kstat_cpu(cpu).irqs[irq]++; | 474 | kstat_irqs_this_cpu(desc)++; |
480 | 475 | ||
481 | /* Start handling the irq */ | 476 | /* Start handling the irq */ |
482 | desc->chip->ack(irq); | 477 | desc->chip->ack(irq); |
@@ -531,7 +526,7 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc) | |||
531 | { | 526 | { |
532 | irqreturn_t action_ret; | 527 | irqreturn_t action_ret; |
533 | 528 | ||
534 | kstat_this_cpu.irqs[irq]++; | 529 | kstat_irqs_this_cpu(desc)++; |
535 | 530 | ||
536 | if (desc->chip->ack) | 531 | if (desc->chip->ack) |
537 | desc->chip->ack(irq); | 532 | desc->chip->ack(irq); |
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 9fc33b3378e6..1f346990f3f8 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -37,7 +37,7 @@ void | |||
37 | handle_bad_irq(unsigned int irq, struct irq_desc *desc) | 37 | handle_bad_irq(unsigned int irq, struct irq_desc *desc) |
38 | { | 38 | { |
39 | print_irq_desc(irq, desc); | 39 | print_irq_desc(irq, desc); |
40 | kstat_this_cpu.irqs[irq]++; | 40 | kstat_irqs_this_cpu(desc)++; |
41 | ack_bad_irq(irq); | 41 | ack_bad_irq(irq); |
42 | } | 42 | } |
43 | 43 | ||
@@ -80,17 +80,38 @@ static void init_one_irq_desc(struct irq_desc *desc) | |||
80 | #endif | 80 | #endif |
81 | } | 81 | } |
82 | 82 | ||
83 | #ifdef CONFIG_HAVE_SPARSE_IRQ | 83 | extern int after_bootmem; |
84 | static int nr_irq_desc = 32; | 84 | extern void *__alloc_bootmem_nopanic(unsigned long size, |
85 | unsigned long align, | ||
86 | unsigned long goal); | ||
85 | 87 | ||
86 | static int __init parse_nr_irq_desc(char *arg) | 88 | static void init_kstat_irqs(struct irq_desc *desc, int nr_desc, int nr) |
87 | { | 89 | { |
88 | if (arg) | 90 | unsigned long bytes, total_bytes; |
89 | nr_irq_desc = simple_strtoul(arg, NULL, 0); | 91 | char *ptr; |
90 | return 0; | 92 | int i; |
93 | unsigned long phys; | ||
94 | |||
95 | /* Compute how many bytes we need per irq and allocate them */ | ||
96 | bytes = nr * sizeof(unsigned int); | ||
97 | total_bytes = bytes * nr_desc; | ||
98 | if (after_bootmem) | ||
99 | ptr = kzalloc(total_bytes, GFP_ATOMIC); | ||
100 | else | ||
101 | ptr = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0); | ||
102 | |||
103 | if (!ptr) | ||
104 | panic(" can not allocate kstat_irqs\n"); | ||
105 | |||
106 | phys = __pa(ptr); | ||
107 | printk(KERN_DEBUG "kstat_irqs ==> [%#lx - %#lx]\n", phys, phys + total_bytes); | ||
108 | |||
109 | for (i = 0; i < nr_desc; i++) { | ||
110 | desc[i].kstat_irqs = (unsigned int *)ptr; | ||
111 | ptr += bytes; | ||
112 | } | ||
91 | } | 113 | } |
92 | 114 | ||
93 | early_param("nr_irq_desc", parse_nr_irq_desc); | ||
94 | 115 | ||
95 | static void __init init_work(void *data) | 116 | static void __init init_work(void *data) |
96 | { | 117 | { |
@@ -100,25 +121,44 @@ static void __init init_work(void *data) | |||
100 | 121 | ||
101 | desc = *da->name; | 122 | desc = *da->name; |
102 | 123 | ||
103 | for (i = 0; i < *da->nr; i++) | 124 | for (i = 0; i < *da->nr; i++) { |
104 | init_one_irq_desc(&desc[i]); | 125 | init_one_irq_desc(&desc[i]); |
126 | #ifndef CONFIG_HAVE_SPARSE_IRQ | ||
127 | desc[i].irq = i; | ||
128 | #endif | ||
129 | } | ||
105 | 130 | ||
131 | #ifdef CONFIG_HAVE_SPARSE_IRQ | ||
106 | for (i = 1; i < *da->nr; i++) | 132 | for (i = 1; i < *da->nr; i++) |
107 | desc[i-1].next = &desc[i]; | 133 | desc[i-1].next = &desc[i]; |
134 | #endif | ||
135 | |||
136 | /* init kstat_irqs, nr_cpu_ids is ready already */ | ||
137 | init_kstat_irqs(desc, *da->nr, nr_cpu_ids); | ||
108 | } | 138 | } |
109 | 139 | ||
140 | #ifdef CONFIG_HAVE_SPARSE_IRQ | ||
141 | static int nr_irq_desc = 32; | ||
142 | |||
143 | static int __init parse_nr_irq_desc(char *arg) | ||
144 | { | ||
145 | if (arg) | ||
146 | nr_irq_desc = simple_strtoul(arg, NULL, 0); | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | early_param("nr_irq_desc", parse_nr_irq_desc); | ||
151 | |||
110 | static struct irq_desc *sparse_irqs; | 152 | static struct irq_desc *sparse_irqs; |
111 | DEFINE_DYN_ARRAY(sparse_irqs, sizeof(struct irq_desc), nr_irq_desc, PAGE_SIZE, init_work); | 153 | DEFINE_DYN_ARRAY(sparse_irqs, sizeof(struct irq_desc), nr_irq_desc, PAGE_SIZE, init_work); |
112 | 154 | ||
113 | extern int after_bootmem; | ||
114 | extern void *__alloc_bootmem_nopanic(unsigned long size, | ||
115 | unsigned long align, | ||
116 | unsigned long goal); | ||
117 | struct irq_desc *irq_to_desc(unsigned int irq) | 155 | struct irq_desc *irq_to_desc(unsigned int irq) |
118 | { | 156 | { |
119 | struct irq_desc *desc, *desc_pri; | 157 | struct irq_desc *desc, *desc_pri; |
120 | int i; | 158 | int i; |
121 | int count = 0; | 159 | int count = 0; |
160 | unsigned long phys; | ||
161 | unsigned long total_bytes; | ||
122 | 162 | ||
123 | BUG_ON(irq == -1U); | 163 | BUG_ON(irq == -1U); |
124 | 164 | ||
@@ -141,38 +181,34 @@ struct irq_desc *irq_to_desc(unsigned int irq) | |||
141 | */ | 181 | */ |
142 | printk(KERN_DEBUG "try to get more irq_desc %d\n", nr_irq_desc); | 182 | printk(KERN_DEBUG "try to get more irq_desc %d\n", nr_irq_desc); |
143 | 183 | ||
184 | total_bytes = sizeof(struct irq_desc) * nr_irq_desc; | ||
144 | if (after_bootmem) | 185 | if (after_bootmem) |
145 | desc = kzalloc(sizeof(struct irq_desc)*nr_irq_desc, GFP_ATOMIC); | 186 | desc = kzalloc(total_bytes, GFP_ATOMIC); |
146 | else | 187 | else |
147 | desc = __alloc_bootmem_nopanic(sizeof(struct irq_desc)*nr_irq_desc, PAGE_SIZE, 0); | 188 | desc = __alloc_bootmem_nopanic(total_bytes, PAGE_SIZE, 0); |
148 | 189 | ||
149 | if (!desc) | 190 | if (!desc) |
150 | panic("please boot with nr_irq_desc= %d\n", count * 2); | 191 | panic("please boot with nr_irq_desc= %d\n", count * 2); |
151 | 192 | ||
193 | phys = __pa(desc); | ||
194 | printk(KERN_DEBUG "irq_desc ==> [%#lx - %#lx]\n", phys, phys + total_bytes); | ||
195 | |||
152 | for (i = 0; i < nr_irq_desc; i++) | 196 | for (i = 0; i < nr_irq_desc; i++) |
153 | init_one_irq_desc(&desc[i]); | 197 | init_one_irq_desc(&desc[i]); |
154 | 198 | ||
155 | for (i = 1; i < nr_irq_desc; i++) | 199 | for (i = 1; i < nr_irq_desc; i++) |
156 | desc[i-1].next = &desc[i]; | 200 | desc[i-1].next = &desc[i]; |
157 | 201 | ||
202 | /* init kstat_irqs, nr_cpu_ids is ready already */ | ||
203 | init_kstat_irqs(desc, nr_irq_desc, nr_cpu_ids); | ||
204 | |||
158 | desc->irq = irq; | 205 | desc->irq = irq; |
159 | desc_pri->next = desc; | 206 | desc_pri->next = desc; |
160 | 207 | ||
161 | return desc; | 208 | return desc; |
162 | } | 209 | } |
163 | #else | 210 | #else |
164 | static void __init init_work(void *data) | ||
165 | { | ||
166 | struct dyn_array *da = data; | ||
167 | int i; | ||
168 | struct irq_desc *desc; | ||
169 | |||
170 | desc = *da->name; | ||
171 | 211 | ||
172 | for (i = 0; i < *da->nr; i++) | ||
173 | init_one_irq_desc(&desc[i]); | ||
174 | |||
175 | } | ||
176 | static struct irq_desc *irq_desc; | 212 | static struct irq_desc *irq_desc; |
177 | DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work); | 213 | DEFINE_DYN_ARRAY(irq_desc, sizeof(struct irq_desc), nr_irqs, PAGE_SIZE, init_work); |
178 | 214 | ||
@@ -315,7 +351,7 @@ unsigned int __do_IRQ(unsigned int irq) | |||
315 | struct irqaction *action; | 351 | struct irqaction *action; |
316 | unsigned int status; | 352 | unsigned int status; |
317 | 353 | ||
318 | kstat_this_cpu.irqs[irq]++; | 354 | kstat_irqs_this_cpu(desc)++; |
319 | if (CHECK_IRQ_PER_CPU(desc->status)) { | 355 | if (CHECK_IRQ_PER_CPU(desc->status)) { |
320 | irqreturn_t action_ret; | 356 | irqreturn_t action_ret; |
321 | 357 | ||
@@ -415,3 +451,10 @@ void early_init_irq_lock_class(void) | |||
415 | } | 451 | } |
416 | #endif | 452 | #endif |
417 | 453 | ||
454 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) | ||
455 | { | ||
456 | struct irq_desc *desc = irq_to_desc(irq); | ||
457 | return desc->kstat_irqs[cpu]; | ||
458 | } | ||
459 | EXPORT_SYMBOL(kstat_irqs_cpu); | ||
460 | |||