diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-08-19 23:50:51 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-16 10:52:57 -0400 |
commit | 8f09cd20a24c5f13c571bc73ddcd47be0af3b70f (patch) | |
tree | 7b4188221e5ac41d6ec9f773b87a5f8413f530b4 /arch/x86/kernel/io_apic.c | |
parent | ffd5aae7817fba22c5c3e304a31c44fa0a4e9a97 (diff) |
x86: make HAVE_SPARSE_IRQ support selectable
Ingo said sparse_irq is some intrusive. need to make it selectable
to make it simple, remove irq_desc as parameter in some functions.
(ack, eoi, set_affinity).
may need to make member if irq_chip to take irq_desc, or struct irq later.
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/io_apic.c')
-rw-r--r-- | arch/x86/kernel/io_apic.c | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c index bf0e66d73030..f853b667fa5c 100644 --- a/arch/x86/kernel/io_apic.c +++ b/arch/x86/kernel/io_apic.c | |||
@@ -107,7 +107,9 @@ struct irq_cfg; | |||
107 | struct irq_pin_list; | 107 | struct irq_pin_list; |
108 | struct irq_cfg { | 108 | struct irq_cfg { |
109 | unsigned int irq; | 109 | unsigned int irq; |
110 | #ifdef CONFIG_HAVE_SPARSE_IRQ | ||
110 | struct irq_cfg *next; | 111 | struct irq_cfg *next; |
112 | #endif | ||
111 | struct irq_pin_list *irq_2_pin; | 113 | struct irq_pin_list *irq_2_pin; |
112 | cpumask_t domain; | 114 | cpumask_t domain; |
113 | cpumask_t old_domain; | 115 | cpumask_t old_domain; |
@@ -137,20 +139,6 @@ static struct irq_cfg irq_cfg_legacy[] __initdata = { | |||
137 | }; | 139 | }; |
138 | 140 | ||
139 | static struct irq_cfg irq_cfg_init = { .irq = -1U, }; | 141 | static struct irq_cfg irq_cfg_init = { .irq = -1U, }; |
140 | /* need to be biger than size of irq_cfg_legacy */ | ||
141 | static int nr_irq_cfg = 32; | ||
142 | |||
143 | static int __init parse_nr_irq_cfg(char *arg) | ||
144 | { | ||
145 | if (arg) { | ||
146 | nr_irq_cfg = simple_strtoul(arg, NULL, 0); | ||
147 | if (nr_irq_cfg < 32) | ||
148 | nr_irq_cfg = 32; | ||
149 | } | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | early_param("nr_irq_cfg", parse_nr_irq_cfg); | ||
154 | 142 | ||
155 | static void init_one_irq_cfg(struct irq_cfg *cfg) | 143 | static void init_one_irq_cfg(struct irq_cfg *cfg) |
156 | { | 144 | { |
@@ -158,7 +146,9 @@ static void init_one_irq_cfg(struct irq_cfg *cfg) | |||
158 | } | 146 | } |
159 | 147 | ||
160 | static struct irq_cfg *irq_cfgx; | 148 | static struct irq_cfg *irq_cfgx; |
149 | #ifdef CONFIG_HAVE_SPARSE_IRQ | ||
161 | static struct irq_cfg *irq_cfgx_free; | 150 | static struct irq_cfg *irq_cfgx_free; |
151 | #endif | ||
162 | static void __init init_work(void *data) | 152 | static void __init init_work(void *data) |
163 | { | 153 | { |
164 | struct dyn_array *da = data; | 154 | struct dyn_array *da = data; |
@@ -174,15 +164,34 @@ static void __init init_work(void *data) | |||
174 | for (i = legacy_count; i < *da->nr; i++) | 164 | for (i = legacy_count; i < *da->nr; i++) |
175 | init_one_irq_cfg(&cfg[i]); | 165 | init_one_irq_cfg(&cfg[i]); |
176 | 166 | ||
167 | #ifdef CONFIG_HAVE_SPARSE_IRQ | ||
177 | for (i = 1; i < *da->nr; i++) | 168 | for (i = 1; i < *da->nr; i++) |
178 | cfg[i-1].next = &cfg[i]; | 169 | cfg[i-1].next = &cfg[i]; |
179 | 170 | ||
180 | irq_cfgx_free = &irq_cfgx[legacy_count]; | 171 | irq_cfgx_free = &irq_cfgx[legacy_count]; |
181 | irq_cfgx[legacy_count - 1].next = NULL; | 172 | irq_cfgx[legacy_count - 1].next = NULL; |
173 | #endif | ||
174 | } | ||
175 | |||
176 | #ifdef CONFIG_HAVE_SPARSE_IRQ | ||
177 | /* need to be biger than size of irq_cfg_legacy */ | ||
178 | static int nr_irq_cfg = 32; | ||
179 | |||
180 | static int __init parse_nr_irq_cfg(char *arg) | ||
181 | { | ||
182 | if (arg) { | ||
183 | nr_irq_cfg = simple_strtoul(arg, NULL, 0); | ||
184 | if (nr_irq_cfg < 32) | ||
185 | nr_irq_cfg = 32; | ||
186 | } | ||
187 | return 0; | ||
182 | } | 188 | } |
183 | 189 | ||
184 | #define for_each_irq_cfg(cfg) \ | 190 | early_param("nr_irq_cfg", parse_nr_irq_cfg); |
185 | for (cfg = irq_cfgx; cfg; cfg = cfg->next) | 191 | |
192 | #define for_each_irq_cfg(irqX, cfg) \ | ||
193 | for (cfg = irq_cfgx, irqX = cfg->irq; cfg; cfg = cfg->next, irqX = cfg ? cfg->irq : -1U) | ||
194 | |||
186 | 195 | ||
187 | DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work); | 196 | DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irq_cfg, PAGE_SIZE, init_work); |
188 | 197 | ||
@@ -273,7 +282,26 @@ static struct irq_cfg *irq_cfg_alloc(unsigned int irq) | |||
273 | #endif | 282 | #endif |
274 | return cfg; | 283 | return cfg; |
275 | } | 284 | } |
285 | #else | ||
286 | |||
287 | #define for_each_irq_cfg(irq, cfg) \ | ||
288 | for (irq = 0, cfg = &irq_cfgx[irq]; irq < nr_irqs; irq++, cfg = &irq_cfgx[irq]) | ||
289 | |||
290 | DEFINE_DYN_ARRAY(irq_cfgx, sizeof(struct irq_cfg), nr_irqs, PAGE_SIZE, init_work); | ||
276 | 291 | ||
292 | struct irq_cfg *irq_cfg(unsigned int irq) | ||
293 | { | ||
294 | if (irq < nr_irqs) | ||
295 | return &irq_cfgx[irq]; | ||
296 | |||
297 | return NULL; | ||
298 | } | ||
299 | struct irq_cfg *irq_cfg_alloc(unsigned int irq) | ||
300 | { | ||
301 | return irq_cfg(irq); | ||
302 | } | ||
303 | |||
304 | #endif | ||
277 | /* | 305 | /* |
278 | * This is performance-critical, we want to do it O(1) | 306 | * This is performance-critical, we want to do it O(1) |
279 | * | 307 | * |
@@ -1282,11 +1310,10 @@ void __setup_vector_irq(int cpu) | |||
1282 | struct irq_cfg *cfg; | 1310 | struct irq_cfg *cfg; |
1283 | 1311 | ||
1284 | /* Mark the inuse vectors */ | 1312 | /* Mark the inuse vectors */ |
1285 | for_each_irq_cfg(cfg) { | 1313 | for_each_irq_cfg(irq, cfg) { |
1286 | if (!cpu_isset(cpu, cfg->domain)) | 1314 | if (!cpu_isset(cpu, cfg->domain)) |
1287 | continue; | 1315 | continue; |
1288 | vector = cfg->vector; | 1316 | vector = cfg->vector; |
1289 | irq = cfg->irq; | ||
1290 | per_cpu(vector_irq, cpu)[vector] = irq; | 1317 | per_cpu(vector_irq, cpu)[vector] = irq; |
1291 | } | 1318 | } |
1292 | /* Mark the free vectors */ | 1319 | /* Mark the free vectors */ |
@@ -1563,6 +1590,7 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
1563 | union IO_APIC_reg_03 reg_03; | 1590 | union IO_APIC_reg_03 reg_03; |
1564 | unsigned long flags; | 1591 | unsigned long flags; |
1565 | struct irq_cfg *cfg; | 1592 | struct irq_cfg *cfg; |
1593 | unsigned int irq; | ||
1566 | 1594 | ||
1567 | if (apic_verbosity == APIC_QUIET) | 1595 | if (apic_verbosity == APIC_QUIET) |
1568 | return; | 1596 | return; |
@@ -1651,11 +1679,11 @@ __apicdebuginit(void) print_IO_APIC(void) | |||
1651 | } | 1679 | } |
1652 | } | 1680 | } |
1653 | printk(KERN_DEBUG "IRQ to pin mappings:\n"); | 1681 | printk(KERN_DEBUG "IRQ to pin mappings:\n"); |
1654 | for_each_irq_cfg(cfg) { | 1682 | for_each_irq_cfg(irq, cfg) { |
1655 | struct irq_pin_list *entry = cfg->irq_2_pin; | 1683 | struct irq_pin_list *entry = cfg->irq_2_pin; |
1656 | if (!entry) | 1684 | if (!entry) |
1657 | continue; | 1685 | continue; |
1658 | printk(KERN_DEBUG "IRQ%d ", cfg->irq); | 1686 | printk(KERN_DEBUG "IRQ%d ", irq); |
1659 | for (;;) { | 1687 | for (;;) { |
1660 | printk("-> %d:%d", entry->apic, entry->pin); | 1688 | printk("-> %d:%d", entry->apic, entry->pin); |
1661 | if (!entry->next) | 1689 | if (!entry->next) |
@@ -2535,8 +2563,7 @@ static inline void init_IO_APIC_traps(void) | |||
2535 | * Also, we've got to be careful not to trash gate | 2563 | * Also, we've got to be careful not to trash gate |
2536 | * 0x80, because int 0x80 is hm, kind of importantish. ;) | 2564 | * 0x80, because int 0x80 is hm, kind of importantish. ;) |
2537 | */ | 2565 | */ |
2538 | for_each_irq_cfg(cfg) { | 2566 | for_each_irq_cfg(irq, cfg) { |
2539 | irq = cfg->irq; | ||
2540 | if (IO_APIC_IRQ(irq) && !cfg->vector) { | 2567 | if (IO_APIC_IRQ(irq) && !cfg->vector) { |
2541 | /* | 2568 | /* |
2542 | * Hmm.. We don't have an entry for this, | 2569 | * Hmm.. We don't have an entry for this, |