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/handle.c | |
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/handle.c')
-rw-r--r-- | kernel/irq/handle.c | 97 |
1 files changed, 70 insertions, 27 deletions
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 | |||