forked from Minki/linux
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>
This commit is contained in:
parent
fe6dab4e79
commit
fbc6bff04a
@ -61,7 +61,6 @@ config X86
|
|||||||
select HAVE_USER_RETURN_NOTIFIER
|
select HAVE_USER_RETURN_NOTIFIER
|
||||||
select HAVE_GENERIC_HARDIRQS
|
select HAVE_GENERIC_HARDIRQS
|
||||||
select HAVE_SPARSE_IRQ
|
select HAVE_SPARSE_IRQ
|
||||||
select NUMA_IRQ_DESC if (SPARSE_IRQ && NUMA)
|
|
||||||
select GENERIC_IRQ_PROBE
|
select GENERIC_IRQ_PROBE
|
||||||
select GENERIC_PENDING_IRQ if SMP
|
select GENERIC_PENDING_IRQ if SMP
|
||||||
|
|
||||||
|
@ -157,6 +157,9 @@ int __init arch_early_irq_init(void)
|
|||||||
count = ARRAY_SIZE(irq_cfgx);
|
count = ARRAY_SIZE(irq_cfgx);
|
||||||
node = cpu_to_node(0);
|
node = cpu_to_node(0);
|
||||||
|
|
||||||
|
/* Make sure the legacy interrupts are marked in the bitmap */
|
||||||
|
irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs);
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
set_irq_chip_data(i, &cfg[i]);
|
set_irq_chip_data(i, &cfg[i]);
|
||||||
zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
|
zalloc_cpumask_var_node(&cfg[i].domain, GFP_NOWAIT, node);
|
||||||
@ -201,11 +204,15 @@ out_cfg:
|
|||||||
|
|
||||||
static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg)
|
static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg)
|
||||||
{
|
{
|
||||||
|
if (!cfg)
|
||||||
|
return;
|
||||||
|
set_irq_chip_data(at, NULL);
|
||||||
free_cpumask_var(cfg->domain);
|
free_cpumask_var(cfg->domain);
|
||||||
free_cpumask_var(cfg->old_domain);
|
free_cpumask_var(cfg->old_domain);
|
||||||
kfree(cfg);
|
kfree(cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
int arch_init_chip_data(struct irq_desc *desc, int node)
|
int arch_init_chip_data(struct irq_desc *desc, int node)
|
||||||
{
|
{
|
||||||
struct irq_cfg *cfg;
|
struct irq_cfg *cfg;
|
||||||
@ -323,6 +330,7 @@ void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* end for move_irq_desc */
|
/* end for move_irq_desc */
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -1479,11 +1487,9 @@ static struct {
|
|||||||
|
|
||||||
static void __init setup_IO_APIC_irqs(void)
|
static void __init setup_IO_APIC_irqs(void)
|
||||||
{
|
{
|
||||||
int apic_id, pin, idx, irq;
|
int apic_id, pin, idx, irq, notcon = 0;
|
||||||
int notcon = 0;
|
|
||||||
struct irq_desc *desc;
|
|
||||||
struct irq_cfg *cfg;
|
|
||||||
int node = cpu_to_node(0);
|
int node = cpu_to_node(0);
|
||||||
|
struct irq_cfg *cfg;
|
||||||
|
|
||||||
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
|
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
|
||||||
|
|
||||||
@ -1520,12 +1526,10 @@ static void __init setup_IO_APIC_irqs(void)
|
|||||||
apic->multi_timer_check(apic_id, irq))
|
apic->multi_timer_check(apic_id, irq))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
desc = irq_to_desc_alloc_node(irq, node);
|
cfg = alloc_irq_and_cfg_at(irq, node);
|
||||||
if (!desc) {
|
if (!cfg)
|
||||||
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
cfg = get_irq_desc_chip_data(desc);
|
|
||||||
add_pin_to_irq_node(cfg, node, apic_id, pin);
|
add_pin_to_irq_node(cfg, node, apic_id, pin);
|
||||||
/*
|
/*
|
||||||
* don't mark it in pin_programmed, so later acpi could
|
* don't mark it in pin_programmed, so later acpi could
|
||||||
@ -1547,9 +1551,7 @@ static void __init setup_IO_APIC_irqs(void)
|
|||||||
*/
|
*/
|
||||||
void setup_IO_APIC_irq_extra(u32 gsi)
|
void setup_IO_APIC_irq_extra(u32 gsi)
|
||||||
{
|
{
|
||||||
int apic_id = 0, pin, idx, irq;
|
int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
|
||||||
int node = cpu_to_node(0);
|
|
||||||
struct irq_desc *desc;
|
|
||||||
struct irq_cfg *cfg;
|
struct irq_cfg *cfg;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1570,13 +1572,10 @@ void setup_IO_APIC_irq_extra(u32 gsi)
|
|||||||
if (apic_id == 0 || irq < NR_IRQS_LEGACY)
|
if (apic_id == 0 || irq < NR_IRQS_LEGACY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
desc = irq_to_desc_alloc_node(irq, node);
|
cfg = alloc_irq_and_cfg_at(irq, node);
|
||||||
if (!desc) {
|
if (!cfg)
|
||||||
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
cfg = get_irq_desc_chip_data(desc);
|
|
||||||
add_pin_to_irq_node(cfg, node, apic_id, pin);
|
add_pin_to_irq_node(cfg, node, apic_id, pin);
|
||||||
|
|
||||||
if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
|
if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
|
||||||
@ -3177,44 +3176,37 @@ device_initcall(ioapic_init_sysfs);
|
|||||||
/*
|
/*
|
||||||
* Dynamic irq allocate and deallocation
|
* Dynamic irq allocate and deallocation
|
||||||
*/
|
*/
|
||||||
unsigned int create_irq_nr(unsigned int irq_want, int node)
|
unsigned int create_irq_nr(unsigned int from, int node)
|
||||||
{
|
{
|
||||||
/* Allocate an unused irq */
|
struct irq_cfg *cfg;
|
||||||
unsigned int irq;
|
|
||||||
unsigned int new;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct irq_cfg *cfg_new = NULL;
|
unsigned int ret = 0;
|
||||||
struct irq_desc *desc_new = NULL;
|
int irq;
|
||||||
|
|
||||||
irq = 0;
|
if (from < nr_irqs_gsi)
|
||||||
if (irq_want < nr_irqs_gsi)
|
from = nr_irqs_gsi;
|
||||||
irq_want = nr_irqs_gsi;
|
|
||||||
|
irq = alloc_irq_from(from, node);
|
||||||
|
if (irq < 0)
|
||||||
|
return 0;
|
||||||
|
cfg = alloc_irq_cfg(irq, node);
|
||||||
|
if (!cfg) {
|
||||||
|
free_irq_at(irq, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&vector_lock, flags);
|
raw_spin_lock_irqsave(&vector_lock, flags);
|
||||||
for (new = irq_want; new < nr_irqs; new++) {
|
if (!__assign_irq_vector(irq, cfg, apic->target_cpus()))
|
||||||
desc_new = irq_to_desc_alloc_node(new, node);
|
ret = irq;
|
||||||
if (!desc_new) {
|
|
||||||
printk(KERN_INFO "can not get irq_desc for %d\n", new);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cfg_new = get_irq_desc_chip_data(desc_new);
|
|
||||||
|
|
||||||
if (cfg_new->vector != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
desc_new = move_irq_desc(desc_new, node);
|
|
||||||
cfg_new = get_irq_desc_chip_data(desc_new);
|
|
||||||
|
|
||||||
if (__assign_irq_vector(new, cfg_new, apic->target_cpus()) == 0)
|
|
||||||
irq = new;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
raw_spin_unlock_irqrestore(&vector_lock, flags);
|
raw_spin_unlock_irqrestore(&vector_lock, flags);
|
||||||
|
|
||||||
if (irq > 0)
|
if (ret) {
|
||||||
dynamic_irq_init_keep_chip_data(irq);
|
set_irq_chip_data(irq, cfg);
|
||||||
|
irq_clear_status_flags(irq, IRQ_NOREQUEST);
|
||||||
return irq;
|
} else {
|
||||||
|
free_irq_at(irq, cfg);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int create_irq(void)
|
int create_irq(void)
|
||||||
@ -3234,14 +3226,16 @@ int create_irq(void)
|
|||||||
|
|
||||||
void destroy_irq(unsigned int irq)
|
void destroy_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
|
struct irq_cfg *cfg = get_irq_chip_data(irq);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
dynamic_irq_cleanup_keep_chip_data(irq);
|
irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
|
||||||
|
|
||||||
free_irte(irq);
|
free_irte(irq);
|
||||||
raw_spin_lock_irqsave(&vector_lock, flags);
|
raw_spin_lock_irqsave(&vector_lock, flags);
|
||||||
__clear_irq_vector(irq, get_irq_chip_data(irq));
|
__clear_irq_vector(irq, cfg);
|
||||||
raw_spin_unlock_irqrestore(&vector_lock, flags);
|
raw_spin_unlock_irqrestore(&vector_lock, flags);
|
||||||
|
free_irq_at(irq, cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3802,7 +3796,6 @@ int __init arch_probe_nr_irqs(void)
|
|||||||
static int __io_apic_set_pci_routing(struct device *dev, int irq,
|
static int __io_apic_set_pci_routing(struct device *dev, int irq,
|
||||||
struct io_apic_irq_attr *irq_attr)
|
struct io_apic_irq_attr *irq_attr)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc;
|
|
||||||
struct irq_cfg *cfg;
|
struct irq_cfg *cfg;
|
||||||
int node;
|
int node;
|
||||||
int ioapic, pin;
|
int ioapic, pin;
|
||||||
@ -3820,18 +3813,14 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq,
|
|||||||
else
|
else
|
||||||
node = cpu_to_node(0);
|
node = cpu_to_node(0);
|
||||||
|
|
||||||
desc = irq_to_desc_alloc_node(irq, node);
|
cfg = alloc_irq_and_cfg_at(irq, node);
|
||||||
if (!desc) {
|
if (!cfg)
|
||||||
printk(KERN_INFO "can not get irq_desc %d\n", irq);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
pin = irq_attr->ioapic_pin;
|
pin = irq_attr->ioapic_pin;
|
||||||
trigger = irq_attr->trigger;
|
trigger = irq_attr->trigger;
|
||||||
polarity = irq_attr->polarity;
|
polarity = irq_attr->polarity;
|
||||||
|
|
||||||
cfg = get_irq_desc_chip_data(desc);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IRQs < 16 are already in the irq_2_pin[] map
|
* IRQs < 16 are already in the irq_2_pin[] map
|
||||||
*/
|
*/
|
||||||
@ -4232,11 +4221,11 @@ void __init pre_init_apic_IRQ0(void)
|
|||||||
#ifndef CONFIG_SMP
|
#ifndef CONFIG_SMP
|
||||||
phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
|
phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
|
||||||
#endif
|
#endif
|
||||||
irq_to_desc_alloc_node(0, 0);
|
/* Make sure the irq descriptor is set up */
|
||||||
|
cfg = alloc_irq_and_cfg_at(0, 0);
|
||||||
|
|
||||||
setup_local_APIC();
|
setup_local_APIC();
|
||||||
|
|
||||||
cfg = irq_cfg(0);
|
|
||||||
add_pin_to_irq_node(cfg, 0, 0, 0);
|
add_pin_to_irq_node(cfg, 0, 0, 0);
|
||||||
set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
|
set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user