[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.