# 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
|