diff options
-rw-r--r-- | arch/Kconfig | 3 | ||||
-rw-r--r-- | arch/x86/Kconfig | 12 | ||||
-rw-r--r-- | arch/x86/kernel/io_apic.c | 71 | ||||
-rw-r--r-- | arch/x86/kernel/irq_32.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/irq_64.c | 2 |
5 files changed, 62 insertions, 28 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index b36762246265..c8a7c2eb6490 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -106,6 +106,3 @@ config HAVE_CLK | |||
106 | config HAVE_DYN_ARRAY | 106 | config HAVE_DYN_ARRAY |
107 | def_bool n | 107 | def_bool n |
108 | 108 | ||
109 | config HAVE_SPARSE_IRQ | ||
110 | def_bool n | ||
111 | |||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b157e94637bf..600584b7a497 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -34,7 +34,6 @@ config X86 | |||
34 | select HAVE_GENERIC_DMA_COHERENT if X86_32 | 34 | select HAVE_GENERIC_DMA_COHERENT if X86_32 |
35 | select HAVE_EFFICIENT_UNALIGNED_ACCESS | 35 | select HAVE_EFFICIENT_UNALIGNED_ACCESS |
36 | select HAVE_DYN_ARRAY | 36 | select HAVE_DYN_ARRAY |
37 | select HAVE_SPARSE_IRQ | ||
38 | 37 | ||
39 | config ARCH_DEFCONFIG | 38 | config ARCH_DEFCONFIG |
40 | string | 39 | string |
@@ -238,6 +237,17 @@ config SMP | |||
238 | 237 | ||
239 | If you don't know what to do here, say N. | 238 | If you don't know what to do here, say N. |
240 | 239 | ||
240 | config HAVE_SPARSE_IRQ | ||
241 | bool "Support sparse irq numbering" | ||
242 | depends on PCI_MSI || HT_IRQ | ||
243 | default y | ||
244 | help | ||
245 | This enables support for sparse irq, esp for msi/msi-x. the irq | ||
246 | number will be bus/dev/fn + 12bit. You may need if you have lots of | ||
247 | cards supports msi-x installed. | ||
248 | |||
249 | If you don't know what to do here, say Y. | ||
250 | |||
241 | config X86_FIND_SMP_CONFIG | 251 | config X86_FIND_SMP_CONFIG |
242 | def_bool y | 252 | def_bool y |
243 | depends on X86_MPPARSE || X86_VOYAGER | 253 | depends on X86_MPPARSE || X86_VOYAGER |
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, |
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index cc929f2f84f1..b2e1082cf5ad 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c | |||
@@ -269,7 +269,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
269 | struct irqaction * action; | 269 | struct irqaction * action; |
270 | unsigned long flags; | 270 | unsigned long flags; |
271 | unsigned int entries; | 271 | unsigned int entries; |
272 | struct irq_desc *desc; | 272 | struct irq_desc *desc = NULL; |
273 | int tail = 0; | 273 | int tail = 0; |
274 | 274 | ||
275 | #ifdef CONFIG_HAVE_SPARSE_IRQ | 275 | #ifdef CONFIG_HAVE_SPARSE_IRQ |
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index 348a11168c2b..c2fca89a3f7e 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c | |||
@@ -74,7 +74,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
74 | struct irqaction * action; | 74 | struct irqaction * action; |
75 | unsigned long flags; | 75 | unsigned long flags; |
76 | unsigned int entries; | 76 | unsigned int entries; |
77 | struct irq_desc *desc; | 77 | struct irq_desc *desc = NULL; |
78 | int tail = 0; | 78 | int tail = 0; |
79 | 79 | ||
80 | #ifdef CONFIG_HAVE_SPARSE_IRQ | 80 | #ifdef CONFIG_HAVE_SPARSE_IRQ |