[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [LINUX] Fail gracefully if we run out of spare IRQs.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID ff5f976191a5a8c1964cd6528bb650caa4080ca6 # Parent ec9259920f85181265b6a13f243de592ff3b161e [LINUX] Fail gracefully if we run out of spare IRQs. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 26 ++++--- linux-2.6-xen-sparse/drivers/xen/core/evtchn.c | 38 ++++++++--- linux-2.6-xen-sparse/drivers/xen/core/smpboot.c | 72 +++++++++++++-------- linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 13 +-- 4 files changed, 96 insertions(+), 53 deletions(-) diff -r ec9259920f85 -r ff5f976191a5 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Thu Dec 07 16:09:04 2006 +0000 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Thu Dec 07 16:43:08 2006 +0000 @@ -1047,9 +1047,9 @@ void time_resume(void) #ifdef CONFIG_SMP static char timer_name[NR_CPUS][15]; -void local_setup_timer(unsigned int cpu) -{ - int seq; +int local_setup_timer(unsigned int cpu) +{ + int seq, irq; BUG_ON(cpu == 0); @@ -1062,15 +1062,17 @@ void local_setup_timer(unsigned int cpu) } while (read_seqretry(&xtime_lock, seq)); sprintf(timer_name[cpu], "timer%d", cpu); - per_cpu(timer_irq, cpu) = - bind_virq_to_irqhandler( - VIRQ_TIMER, - cpu, - timer_interrupt, - SA_INTERRUPT, - timer_name[cpu], - NULL); - BUG_ON(per_cpu(timer_irq, cpu) < 0); + irq = bind_virq_to_irqhandler(VIRQ_TIMER, + cpu, + timer_interrupt, + SA_INTERRUPT, + timer_name[cpu], + NULL); + if (irq < 0) + return irq; + per_cpu(timer_irq, cpu) = irq; + + return 0; } void local_teardown_timer(unsigned int cpu) diff -r ec9259920f85 -r ff5f976191a5 linux-2.6-xen-sparse/drivers/xen/core/evtchn.c --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Thu Dec 07 16:09:04 2006 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Thu Dec 07 16:43:08 2006 +0000 @@ -251,8 +251,15 @@ static int find_unbound_irq(void) if (irq_bindcount[irq] == 0) break; - if (irq == NR_IRQS) - panic("No available IRQ to bind to: increase NR_IRQS!\n"); + if (irq == NR_IRQS) { + static int warned; + if (!warned) { + warned = 1; + printk(KERN_WARNING "No available IRQ to bind to: " + "increase NR_IRQS!\n"); + } + return -ENOSPC; + } return irq; } @@ -264,15 +271,17 @@ static int bind_evtchn_to_irq(unsigned i spin_lock(&irq_mapping_update_lock); if ((irq = evtchn_to_irq[evtchn]) == -1) { - irq = find_unbound_irq(); + if ((irq = find_unbound_irq()) < 0) + goto out; + evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_EVTCHN, 0, evtchn); } irq_bindcount[irq]++; + out: spin_unlock(&irq_mapping_update_lock); - return irq; } @@ -284,6 +293,9 @@ static int bind_virq_to_irq(unsigned int spin_lock(&irq_mapping_update_lock); if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) { + if ((irq = find_unbound_irq()) < 0) + goto out; + bind_virq.virq = virq; bind_virq.vcpu = cpu; if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, @@ -291,7 +303,6 @@ static int bind_virq_to_irq(unsigned int BUG(); evtchn = bind_virq.port; - irq = find_unbound_irq(); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_VIRQ, virq, evtchn); @@ -302,8 +313,8 @@ static int bind_virq_to_irq(unsigned int irq_bindcount[irq]++; + out: spin_unlock(&irq_mapping_update_lock); - return irq; } @@ -315,13 +326,15 @@ static int bind_ipi_to_irq(unsigned int spin_lock(&irq_mapping_update_lock); if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) { + if ((irq = find_unbound_irq()) < 0) + goto out; + bind_ipi.vcpu = cpu; if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, &bind_ipi) != 0) BUG(); evtchn = bind_ipi.port; - irq = find_unbound_irq(); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_irq_info(IRQT_IPI, ipi, evtchn); @@ -332,8 +345,8 @@ static int bind_ipi_to_irq(unsigned int irq_bindcount[irq]++; + out: spin_unlock(&irq_mapping_update_lock); - return irq; } @@ -383,6 +396,9 @@ int bind_evtchn_to_irqhandler( int retval; irq = bind_evtchn_to_irq(evtchn); + if (irq < 0) + return irq; + retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) { unbind_from_irq(irq); @@ -405,6 +421,9 @@ int bind_virq_to_irqhandler( int retval; irq = bind_virq_to_irq(virq, cpu); + if (irq < 0) + return irq; + retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) { unbind_from_irq(irq); @@ -427,6 +446,9 @@ int bind_ipi_to_irqhandler( int retval; irq = bind_ipi_to_irq(ipi, cpu); + if (irq < 0) + return irq; + retval = request_irq(irq, handler, irqflags, devname, dev_id); if (retval != 0) { unbind_from_irq(irq); diff -r ec9259920f85 -r ff5f976191a5 linux-2.6-xen-sparse/drivers/xen/core/smpboot.c --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c Thu Dec 07 16:09:04 2006 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c Thu Dec 07 16:43:08 2006 +0000 @@ -33,7 +33,7 @@ extern irqreturn_t smp_reschedule_interr extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *); extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *); -extern void local_setup_timer(unsigned int cpu); +extern int local_setup_timer(unsigned int cpu); extern void local_teardown_timer(unsigned int cpu); extern void hypervisor_callback(void); @@ -110,32 +110,45 @@ set_cpu_sibling_map(int cpu) cpu_data[cpu].booted_cores = 1; } -static void xen_smp_intr_init(unsigned int cpu) -{ +static int xen_smp_intr_init(unsigned int cpu) +{ + int rc; + + per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = -1; + sprintf(resched_name[cpu], "resched%d", cpu); - per_cpu(resched_irq, cpu) = - bind_ipi_to_irqhandler( - RESCHEDULE_VECTOR, - cpu, - smp_reschedule_interrupt, - SA_INTERRUPT, - resched_name[cpu], - NULL); - BUG_ON(per_cpu(resched_irq, cpu) < 0); + rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, + cpu, + smp_reschedule_interrupt, + SA_INTERRUPT, + resched_name[cpu], + NULL); + if (rc < 0) + goto fail; + per_cpu(resched_irq, cpu) = rc; sprintf(callfunc_name[cpu], "callfunc%d", cpu); - per_cpu(callfunc_irq, cpu) = - bind_ipi_to_irqhandler( - CALL_FUNCTION_VECTOR, - cpu, - smp_call_function_interrupt, - SA_INTERRUPT, - callfunc_name[cpu], - NULL); - BUG_ON(per_cpu(callfunc_irq, cpu) < 0); - - if (cpu != 0) - local_setup_timer(cpu); + rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR, + cpu, + smp_call_function_interrupt, + SA_INTERRUPT, + callfunc_name[cpu], + NULL); + if (rc < 0) + goto fail; + per_cpu(callfunc_irq, cpu) = rc; + + if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0)) + goto fail; + + return 0; + + fail: + if (per_cpu(resched_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); + if (per_cpu(callfunc_irq, cpu) >= 0) + unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); + return rc; } #ifdef CONFIG_HOTPLUG_CPU @@ -253,7 +266,8 @@ void __init smp_prepare_cpus(unsigned in set_cpu_sibling_map(0); - xen_smp_intr_init(0); + if (xen_smp_intr_init(0)) + BUG(); /* Restrict the possible_map according to max_cpus. */ while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) { @@ -419,7 +433,13 @@ int __devinit __cpu_up(unsigned int cpu) set_cpu_sibling_map(cpu); wmb(); - xen_smp_intr_init(cpu); + + rc = xen_smp_intr_init(cpu); + if (rc) { + remove_siblinginfo(cpu); + return rc; + } + cpu_set(cpu, cpu_online_map); rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); diff -r ec9259920f85 -r ff5f976191a5 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Dec 07 16:09:04 2006 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Dec 07 16:43:08 2006 +0000 @@ -1506,13 +1506,12 @@ static int __init netback_init(void) netif_xenbus_init(); #ifdef NETBE_DEBUG_INTERRUPT - (void)bind_virq_to_irqhandler( - VIRQ_DEBUG, - 0, - netif_be_dbg, - SA_SHIRQ, - "net-be-dbg", - &netif_be_dbg); + (void)bind_virq_to_irqhandler(VIRQ_DEBUG, + 0, + netif_be_dbg, + SA_SHIRQ, + "net-be-dbg", + &netif_be_dbg); #endif return 0; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |