diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2010-09-28 14:34:53 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-10-12 10:53:40 -0400 |
commit | fbc6bff04a095e049be290ff6f6ac68839166bd6 (patch) | |
tree | 056af820123082b624e757da3d909c1e75d93db2 /arch/x86/kernel/apic | |
parent | fe6dab4e79e82ec35879bfe1a8968b7d15ac0d91 (diff) |
x86: ioapic: Cleanup sparse irq code
Switch over to the new allocator and remove all the magic which was
caused by the unability to destroy irq descriptors. Get rid of the
create_irq_nr() loop for sparse and non sparse irq.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/apic')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 107 |
1 files changed, 48 insertions, 59 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 5aae718a713..ed340297571 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -157,6 +157,9 @@ int __init arch_early_irq_init(void) | |||
157 | count = ARRAY_SIZE(irq_cfgx); | 157 | count = ARRAY_SIZE(irq_cfgx); |
158 | node = cpu_to_node(0); | 158 | node = cpu_to_node(0); |
159 | 159 | ||
160 | /* Make sure the legacy interrupts are marked in the bitmap */ | ||
161 | irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs); | ||
162 | |||
160 | for (i = 0; i < count; i++) { | 163 | for (i = 0; i < count; i++) { |
161 | set_irq_chip_data(i, &cfg[i]); | 164 | set_irq_chip_data(i, &cfg[i]); |
162 | zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node); | 165 | zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node); |
@@ -201,11 +204,15 @@ out_cfg: | |||
201 | 204 | ||
202 | static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) | 205 | static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg) |
203 | { | 206 | { |
207 | if (!cfg) | ||
208 | return; | ||
209 | set_irq_chip_data(at, NULL); | ||
204 | free_cpumask_var(cfg->domain); | 210 | free_cpumask_var(cfg->domain); |
205 | free_cpumask_var(cfg->old_domain); | 211 | free_cpumask_var(cfg->old_domain); |
206 | kfree(cfg); | 212 | kfree(cfg); |
207 | } | 213 | } |
208 | 214 | ||
215 | #if 0 | ||
209 | int arch_init_chip_data(struct irq_desc *desc, int node) | 216 | int arch_init_chip_data(struct irq_desc *desc, int node) |
210 | { | 217 | { |
211 | struct irq_cfg *cfg; | 218 | struct irq_cfg *cfg; |
@@ -323,6 +330,7 @@ void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc) | |||
323 | } | 330 | } |
324 | } | 331 | } |
325 | /* end for move_irq_desc */ | 332 | /* end for move_irq_desc */ |
333 | #endif | ||
326 | 334 | ||
327 | #else | 335 | #else |
328 | 336 | ||
@@ -1479,11 +1487,9 @@ static struct { | |||
1479 | 1487 | ||
1480 | static void __init setup_IO_APIC_irqs(void) | 1488 | static void __init setup_IO_APIC_irqs(void) |
1481 | { | 1489 | { |
1482 | int apic_id, pin, idx, irq; | 1490 | int apic_id, pin, idx, irq, notcon = 0; |
1483 | int notcon = 0; | ||
1484 | struct irq_desc *desc; | ||
1485 | struct irq_cfg *cfg; | ||
1486 | int node = cpu_to_node(0); | 1491 | int node = cpu_to_node(0); |
1492 | struct irq_cfg *cfg; | ||
1487 | 1493 | ||
1488 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); | 1494 | apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); |
1489 | 1495 | ||
@@ -1520,12 +1526,10 @@ static void __init setup_IO_APIC_irqs(void) | |||
1520 | apic->multi_timer_check(apic_id, irq)) | 1526 | apic->multi_timer_check(apic_id, irq)) |
1521 | continue; | 1527 | continue; |
1522 | 1528 | ||
1523 | desc = irq_to_desc_alloc_node(irq, node); | 1529 | cfg = alloc_irq_and_cfg_at(irq, node); |
1524 | if (!desc) { | 1530 | if (!cfg) |
1525 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | ||
1526 | continue; | 1531 | continue; |
1527 | } | 1532 | |
1528 | cfg = get_irq_desc_chip_data(desc); | ||
1529 | add_pin_to_irq_node(cfg, node, apic_id, pin); | 1533 | add_pin_to_irq_node(cfg, node, apic_id, pin); |
1530 | /* | 1534 | /* |
1531 | * don't mark it in pin_programmed, so later acpi could | 1535 | * don't mark it in pin_programmed, so later acpi could |
@@ -1547,9 +1551,7 @@ static void __init setup_IO_APIC_irqs(void) | |||
1547 | */ | 1551 | */ |
1548 | void setup_IO_APIC_irq_extra(u32 gsi) | 1552 | void setup_IO_APIC_irq_extra(u32 gsi) |
1549 | { | 1553 | { |
1550 | int apic_id = 0, pin, idx, irq; | 1554 | int apic_id = 0, pin, idx, irq, node = cpu_to_node(0); |
1551 | int node = cpu_to_node(0); | ||
1552 | struct irq_desc *desc; | ||
1553 | struct irq_cfg *cfg; | 1555 | struct irq_cfg *cfg; |
1554 | 1556 | ||
1555 | /* | 1557 | /* |
@@ -1570,13 +1572,10 @@ void setup_IO_APIC_irq_extra(u32 gsi) | |||
1570 | if (apic_id == 0 || irq < NR_IRQS_LEGACY) | 1572 | if (apic_id == 0 || irq < NR_IRQS_LEGACY) |
1571 | return; | 1573 | return; |
1572 | 1574 | ||
1573 | desc = irq_to_desc_alloc_node(irq, node); | 1575 | cfg = alloc_irq_and_cfg_at(irq, node); |
1574 | if (!desc) { | 1576 | if (!cfg) |
1575 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | ||
1576 | return; | 1577 | return; |
1577 | } | ||
1578 | 1578 | ||
1579 | cfg = get_irq_desc_chip_data(desc); | ||
1580 | add_pin_to_irq_node(cfg, node, apic_id, pin); | 1579 | add_pin_to_irq_node(cfg, node, apic_id, pin); |
1581 | 1580 | ||
1582 | if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) { | 1581 | if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) { |
@@ -3177,44 +3176,37 @@ device_initcall(ioapic_init_sysfs); | |||
3177 | /* | 3176 | /* |
3178 | * Dynamic irq allocate and deallocation | 3177 | * Dynamic irq allocate and deallocation |
3179 | */ | 3178 | */ |
3180 | unsigned int create_irq_nr(unsigned int irq_want, int node) | 3179 | unsigned int create_irq_nr(unsigned int from, int node) |
3181 | { | 3180 | { |
3182 | /* Allocate an unused irq */ | 3181 | struct irq_cfg *cfg; |
3183 | unsigned int irq; | ||
3184 | unsigned int new; | ||
3185 | unsigned long flags; | 3182 | unsigned long flags; |
3186 | struct irq_cfg *cfg_new = NULL; | 3183 | unsigned int ret = 0; |
3187 | struct irq_desc *desc_new = NULL; | 3184 | int irq; |
3188 | |||
3189 | irq = 0; | ||
3190 | if (irq_want < nr_irqs_gsi) | ||
3191 | irq_want = nr_irqs_gsi; | ||
3192 | |||
3193 | raw_spin_lock_irqsave(&vector_lock, flags); | ||
3194 | for (new = irq_want; new < nr_irqs; new++) { | ||
3195 | desc_new = irq_to_desc_alloc_node(new, node); | ||
3196 | if (!desc_new) { | ||
3197 | printk(KERN_INFO "can not get irq_desc for %d\n", new); | ||
3198 | continue; | ||
3199 | } | ||
3200 | cfg_new = get_irq_desc_chip_data(desc_new); | ||
3201 | |||
3202 | if (cfg_new->vector != 0) | ||
3203 | continue; | ||
3204 | 3185 | ||
3205 | desc_new = move_irq_desc(desc_new, node); | 3186 | if (from < nr_irqs_gsi) |
3206 | cfg_new = get_irq_desc_chip_data(desc_new); | 3187 | from = nr_irqs_gsi; |
3207 | 3188 | ||
3208 | if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0) | 3189 | irq = alloc_irq_from(from, node); |
3209 | irq = new; | 3190 | if (irq < 0) |
3210 | break; | 3191 | return 0; |
3192 | cfg = alloc_irq_cfg(irq, node); | ||
3193 | if (!cfg) { | ||
3194 | free_irq_at(irq, NULL); | ||
3195 | return 0; | ||
3211 | } | 3196 | } |
3212 | raw_spin_unlock_irqrestore(&vector_lock, flags); | ||
3213 | 3197 | ||
3214 | if (irq > 0) | 3198 | raw_spin_lock_irqsave(&vector_lock, flags); |
3215 | dynamic_irq_init_keep_chip_data(irq); | 3199 | if (!__assign_irq_vector(irq, cfg, apic->target_cpus())) |
3200 | ret = irq; | ||
3201 | raw_spin_unlock_irqrestore(&vector_lock, flags); | ||
3216 | 3202 | ||
3217 | return irq; | 3203 | if (ret) { |
3204 | set_irq_chip_data(irq, cfg); | ||
3205 | irq_clear_status_flags(irq, IRQ_NOREQUEST); | ||
3206 | } else { | ||
3207 | free_irq_at(irq, cfg); | ||
3208 | } | ||
3209 | return ret; | ||
3218 | } | 3210 | } |
3219 | 3211 | ||
3220 | int create_irq(void) | 3212 | int create_irq(void) |
@@ -3234,14 +3226,16 @@ int create_irq(void) | |||
3234 | 3226 | ||
3235 | void destroy_irq(unsigned int irq) | 3227 | void destroy_irq(unsigned int irq) |
3236 | { | 3228 | { |
3229 | struct irq_cfg *cfg = get_irq_chip_data(irq); | ||
3237 | unsigned long flags; | 3230 | unsigned long flags; |
3238 | 3231 | ||
3239 | dynamic_irq_cleanup_keep_chip_data(irq); | 3232 | irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE); |
3240 | 3233 | ||
3241 | free_irte(irq); | 3234 | free_irte(irq); |
3242 | raw_spin_lock_irqsave(&vector_lock, flags); | 3235 | raw_spin_lock_irqsave(&vector_lock, flags); |
3243 | __clear_irq_vector(irq, get_irq_chip_data(irq)); | 3236 | __clear_irq_vector(irq, cfg); |
3244 | raw_spin_unlock_irqrestore(&vector_lock, flags); | 3237 | raw_spin_unlock_irqrestore(&vector_lock, flags); |
3238 | free_irq_at(irq, cfg); | ||
3245 | } | 3239 | } |
3246 | 3240 | ||
3247 | /* | 3241 | /* |
@@ -3802,7 +3796,6 @@ int __init arch_probe_nr_irqs(void) | |||
3802 | static int __io_apic_set_pci_routing(struct device *dev, int irq, | 3796 | static int __io_apic_set_pci_routing(struct device *dev, int irq, |
3803 | struct io_apic_irq_attr *irq_attr) | 3797 | struct io_apic_irq_attr *irq_attr) |
3804 | { | 3798 | { |
3805 | struct irq_desc *desc; | ||
3806 | struct irq_cfg *cfg; | 3799 | struct irq_cfg *cfg; |
3807 | int node; | 3800 | int node; |
3808 | int ioapic, pin; | 3801 | int ioapic, pin; |
@@ -3820,18 +3813,14 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq, | |||
3820 | else | 3813 | else |
3821 | node = cpu_to_node(0); | 3814 | node = cpu_to_node(0); |
3822 | 3815 | ||
3823 | desc = irq_to_desc_alloc_node(irq, node); | 3816 | cfg = alloc_irq_and_cfg_at(irq, node); |
3824 | if (!desc) { | 3817 | if (!cfg) |
3825 | printk(KERN_INFO "can not get irq_desc %d\n", irq); | ||
3826 | return 0; | 3818 | return 0; |
3827 | } | ||
3828 | 3819 | ||
3829 | pin = irq_attr->ioapic_pin; | 3820 | pin = irq_attr->ioapic_pin; |
3830 | trigger = irq_attr->trigger; | 3821 | trigger = irq_attr->trigger; |
3831 | polarity = irq_attr->polarity; | 3822 | polarity = irq_attr->polarity; |
3832 | 3823 | ||
3833 | cfg = get_irq_desc_chip_data(desc); | ||
3834 | |||
3835 | /* | 3824 | /* |
3836 | * IRQs < 16 are already in the irq_2_pin[] map | 3825 | * IRQs < 16 are already in the irq_2_pin[] map |
3837 | */ | 3826 | */ |
@@ -4232,11 +4221,11 @@ void __init pre_init_apic_IRQ0(void) | |||
4232 | #ifndef CONFIG_SMP | 4221 | #ifndef CONFIG_SMP |
4233 | phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); | 4222 | phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); |
4234 | #endif | 4223 | #endif |
4235 | irq_to_desc_alloc_node(0, 0); | 4224 | /* Make sure the irq descriptor is set up */ |
4225 | cfg = alloc_irq_and_cfg_at(0, 0); | ||
4236 | 4226 | ||
4237 | setup_local_APIC(); | 4227 | setup_local_APIC(); |
4238 | 4228 | ||
4239 | cfg = irq_cfg(0); | ||
4240 | add_pin_to_irq_node(cfg, 0, 0, 0); | 4229 | add_pin_to_irq_node(cfg, 0, 0, 0); |
4241 | set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); | 4230 | set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); |
4242 | 4231 | ||