# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID d9442abaa9809f251e402286a87a8eef8135e4fe
# Parent f294acb258585f9f42e292cf37a3d3ddff578217
Virtual device drivers use new bind_evtchn_to_irqhandler() call
instead of directly interfacing with Linux IRQ subsystem. This
allows them to be used in situations where the IRQ subsystem is
not paravirtualised.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Wed Aug 3
09:35:38 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Wed Aug 3
12:51:35 2005
@@ -62,6 +62,8 @@
#include <mach_wakecpu.h>
#include <smpboot_hooks.h>
+#include <asm-xen/evtchn.h>
+
/* Set if we find a B stepping CPU */
static int __initdata smp_b_stepping;
@@ -1534,13 +1536,13 @@
int cpu = smp_processor_id();
per_cpu(resched_irq, cpu) =
- bind_ipi_on_cpu_to_irq(RESCHEDULE_VECTOR);
+ bind_ipi_to_irq(RESCHEDULE_VECTOR);
sprintf(resched_name[cpu], "resched%d", cpu);
BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
SA_INTERRUPT, resched_name[cpu], NULL));
per_cpu(callfunc_irq, cpu) =
- bind_ipi_on_cpu_to_irq(CALL_FUNCTION_VECTOR);
+ bind_ipi_to_irq(CALL_FUNCTION_VECTOR);
sprintf(callfunc_name[cpu], "callfunc%d", cpu);
BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
smp_call_function_interrupt,
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Wed Aug 3 09:35:38 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Wed Aug 3 12:51:35 2005
@@ -70,6 +70,8 @@
#include "io_ports.h"
+#include <asm-xen/evtchn.h>
+
extern spinlock_t i8259A_lock;
int pit_latch_buggy; /* extern */
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Wed Aug 3 09:35:38 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Wed Aug 3 12:51:35 2005
@@ -229,12 +229,13 @@
if ( HYPERVISOR_event_channel_op(&op) != 0 )
panic("Failed to unbind virtual IRQ %d\n", virq);
- /* This is a slight hack. Interdomain ports can be allocated
- directly by userspace, and at that point they get bound by
- Xen to vcpu 0. We therefore need to make sure that if we
- get an event on an event channel we don't know about vcpu 0
- handles it. Binding channels to vcpu 0 when closing them
- achieves this. */
+ /*
+ * This is a slight hack. Interdomain ports can be allocated directly
+ * by userspace, and at that point they get bound by Xen to vcpu 0. We
+ * therefore need to make sure that if we get an event on an event
+ * channel we don't know about vcpu 0 handles it. Binding channels to
+ * vcpu 0 when closing them achieves this.
+ */
bind_evtchn_to_cpu(evtchn, 0);
evtchn_to_irq[evtchn] = -1;
irq_to_evtchn[irq] = -1;
@@ -244,7 +245,7 @@
spin_unlock(&irq_mapping_update_lock);
}
-int bind_ipi_on_cpu_to_irq(int ipi)
+int bind_ipi_to_irq(int ipi)
{
evtchn_op_t op;
int evtchn, irq;
@@ -306,7 +307,7 @@
spin_unlock(&irq_mapping_update_lock);
}
-int bind_evtchn_to_irq(int evtchn)
+int bind_evtchn_to_irq(unsigned int evtchn)
{
int irq;
@@ -326,7 +327,7 @@
return irq;
}
-void unbind_evtchn_from_irq(int evtchn)
+void unbind_evtchn_from_irq(unsigned int evtchn)
{
int irq = evtchn_to_irq[evtchn];
@@ -339,6 +340,33 @@
}
spin_unlock(&irq_mapping_update_lock);
+}
+
+int bind_evtchn_to_irqhandler(
+ unsigned int evtchn,
+ irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char *devname,
+ void *dev_id)
+{
+ unsigned int irq;
+ int retval;
+
+ BUG_ON((irqflags & ~SA_SAMPLE_RANDOM) != 0);
+
+ irq = bind_evtchn_to_irq(evtchn);
+ retval = request_irq(irq, handler, irqflags, devname, dev_id);
+ if ( retval != 0 )
+ unbind_evtchn_from_irq(evtchn);
+
+ return retval;
+}
+
+void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id)
+{
+ unsigned int irq = evtchn_to_irq[evtchn];
+ free_irq(irq, dev_id);
+ unbind_evtchn_from_irq(evtchn);
}
static void do_nothing_function(void *ign)
@@ -358,34 +386,33 @@
return;
}
- /* Tell Xen to send future instances of this interrupt to the
- other vcpu */
+ /* Tell Xen to send future instances of this interrupt to other vcpu. */
op.cmd = EVTCHNOP_bind_vcpu;
op.u.bind_vcpu.port = evtchn;
op.u.bind_vcpu.vcpu = tcpu;
- /* If this fails, it usually just indicates that we're dealing
- with a virq or IPI channel, which don't actually need to be
- rebound. Ignore it, but don't do the xenlinux-level rebind
- in that case. */
+ /*
+ * If this fails, it usually just indicates that we're dealing with a virq
+ * or IPI channel, which don't actually need to be rebound. Ignore it,
+ * but don't do the xenlinux-level rebind in that case.
+ */
if (HYPERVISOR_event_channel_op(&op) >= 0)
bind_evtchn_to_cpu(evtchn, tcpu);
spin_unlock(&irq_mapping_update_lock);
- /* Now send the new target processor a NOP IPI. When this
- returns, it will check for any pending interrupts, and so
- service any that got delivered to the wrong processor by
- mistake. */
- /* XXX: The only time this is called with interrupts disabled is
- from the hotplug/hotunplug path. In that case, all cpus are
- stopped with interrupts disabled, and the missed interrupts
- will be picked up when they start again. This is kind of a
- hack.
- */
- if (!irqs_disabled()) {
+ /*
+ * Now send the new target processor a NOP IPI. When this returns, it
+ * will check for any pending interrupts, and so service any that got
+ * delivered to the wrong processor by mistake.
+ *
+ * XXX: The only time this is called with interrupts disabled is from the
+ * hotplug/hotunplug path. In that case, all cpus are stopped with
+ * interrupts disabled, and the missed interrupts will be picked up when
+ * they start again. This is kind of a hack.
+ */
+ if (!irqs_disabled())
smp_call_function(do_nothing_function, NULL, 0, 0);
- }
}
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 3 09:35:38 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 3 12:51:35 2005
@@ -12,6 +12,7 @@
#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm-xen/ctrl_if.h>
+#include <asm-xen/evtchn.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/xen-public/dom0_ops.h>
#include <asm-xen/linux-public/suspend.h>
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Wed Aug 3
09:35:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Wed Aug 3
12:51:35 2005
@@ -12,7 +12,6 @@
*/
#include "common.h"
-#include <asm-xen/evtchn.h>
#ifdef CONFIG_XEN_BLKDEV_GRANT
#include <asm-xen/xen-public/grant_table.h>
#endif
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/drivers/xen/blkback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Wed Aug 3 09:35:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Wed Aug 3 12:51:35 2005
@@ -13,6 +13,7 @@
#include <asm/setup.h>
#include <asm/pgalloc.h>
#include <asm-xen/ctrl_if.h>
+#include <asm-xen/evtchn.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/xen-public/io/blkif.h>
#include <asm-xen/xen-public/io/ring.h>
@@ -42,7 +43,6 @@
/* Physical parameters of the comms window. */
unsigned long shmem_frame;
unsigned int evtchn;
- int irq;
/* Comms information. */
blkif_back_ring_t blk_ring;
/* VBDs attached to this interface. */
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Wed Aug 3
09:35:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Wed Aug 3
12:51:35 2005
@@ -38,7 +38,7 @@
* may be outstanding requests at the disc whose asynchronous responses
* must still be notified to the remote driver.
*/
- unbind_evtchn_from_irq(blkif->evtchn);
+ unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
#ifdef CONFIG_XEN_BLKDEV_GRANT
{
@@ -247,12 +247,12 @@
BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
blkif->evtchn = evtchn;
- blkif->irq = bind_evtchn_to_irq(evtchn);
blkif->shmem_frame = shmem_frame;
blkif->status = CONNECTED;
blkif_get(blkif);
- request_irq(blkif->irq, blkif_be_int, 0, "blkif-backend", blkif);
+ bind_evtchn_to_irqhandler(
+ blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
connect->status = BLKIF_BE_STATUS_OKAY;
}
@@ -277,7 +277,6 @@
blkif->status = DISCONNECTING;
blkif->disconnect_rspid = rsp_id;
wmb(); /* Let other CPUs see the status change. */
- free_irq(blkif->irq, blkif);
blkif_deschedule(blkif);
blkif_put(blkif);
return 0; /* Caller should not send response message. */
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Wed Aug 3
09:35:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Wed Aug 3
12:51:35 2005
@@ -78,7 +78,6 @@
static int blkif_handle = 0;
static unsigned int blkif_state = BLKIF_STATE_CLOSED;
static unsigned int blkif_evtchn = 0;
-static unsigned int blkif_irq = 0;
static int blkif_control_rsp_valid;
static blkif_response_t blkif_control_rsp;
@@ -1159,10 +1158,7 @@
free_page((unsigned long)blk_ring.sring);
blk_ring.sring = NULL;
}
- free_irq(blkif_irq, NULL);
- blkif_irq = 0;
-
- unbind_evtchn_from_irq(blkif_evtchn);
+ unbind_evtchn_from_irqhandler(blkif_evtchn, NULL);
blkif_evtchn = 0;
}
@@ -1266,12 +1262,12 @@
int err = 0;
blkif_evtchn = status->evtchn;
- blkif_irq = bind_evtchn_to_irq(blkif_evtchn);
-
- err = request_irq(blkif_irq, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL);
- if ( err )
- {
- WPRINTK("request_irq failed (err=%d)\n", err);
+
+ err = bind_evtchn_to_irqhandler(
+ blkif_evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL);
+ if ( err != 0 )
+ {
+ WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
return;
}
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 3 09:35:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 3 12:51:35 2005
@@ -15,6 +15,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <asm-xen/ctrl_if.h>
+#include <asm-xen/evtchn.h>
#include <asm-xen/xen-public/io/netif.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 3
09:35:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 3
12:51:35 2005
@@ -12,7 +12,6 @@
#include "common.h"
#include <asm-xen/balloon.h>
-#include <asm-xen/evtchn.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
#include <linux/delay.h>
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
Wed Aug 3 09:35:38 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
Wed Aug 3 12:51:35 2005
@@ -124,18 +124,4 @@
#define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE)
#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
-#ifndef __ASSEMBLY__
-/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
-extern int bind_virq_to_irq(int virq);
-extern void unbind_virq_from_irq(int virq);
-extern int bind_ipi_to_irq(int ipi);
-extern int bind_ipi_on_cpu_to_irq(int ipi);
-extern void unbind_ipi_from_irq(int ipi);
-extern int bind_evtchn_to_irq(int evtchn);
-extern void unbind_evtchn_from_irq(int evtchn);
-
-extern void irq_suspend(void);
-extern void irq_resume(void);
-#endif /* __ASSEMBLY__ */
-
#endif /* _ASM_IRQ_VECTORS_H */
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
Wed Aug 3 09:35:38 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h
Wed Aug 3 12:51:35 2005
@@ -122,18 +122,4 @@
#define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE)
#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
-#ifndef __ASSEMBLY__
-/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
-extern int bind_virq_to_irq(int virq);
-extern void unbind_virq_from_irq(int virq);
-extern int bind_ipi_to_irq(int ipi);
-extern int bind_ipi_on_cpu_to_irq(int ipi);
-extern void unbind_ipi_from_irq(int ipi);
-extern int bind_evtchn_to_irq(int evtchn);
-extern void unbind_evtchn_from_irq(int evtchn);
-
-extern void irq_suspend(void);
-extern void irq_resume(void);
-#endif /* __ASSEMBLY__ */
-
#endif /* _ASM_IRQ_VECTORS_H */
diff -r f294acb25858 -r d9442abaa980
linux-2.6-xen-sparse/include/asm-xen/evtchn.h
--- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Wed Aug 3 09:35:38 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Wed Aug 3 12:51:35 2005
@@ -32,6 +32,7 @@
#define __ASM_EVTCHN_H__
#include <linux/config.h>
+#include <linux/interrupt.h>
#include <asm-xen/hypervisor.h>
#include <asm/ptrace.h>
#include <asm-xen/synch_bitops.h>
@@ -41,6 +42,34 @@
/*
* LOW-LEVEL DEFINITIONS
*/
+
+/* Dynamically bind a VIRQ source to Linux IRQ space. */
+extern int bind_virq_to_irq(int virq);
+extern void unbind_virq_from_irq(int virq);
+
+/* Dynamically bind an IPI source to Linux IRQ space. */
+extern int bind_ipi_to_irq(int ipi);
+extern void unbind_ipi_from_irq(int ipi);
+
+/* Dynamically bind an event-channel port to Linux IRQ space. */
+extern int bind_evtchn_to_irq(unsigned int evtchn);
+extern void unbind_evtchn_from_irq(unsigned int evtchn);
+
+/*
+ * Dynamically bind an event-channel port to an IRQ-like callback handler.
+ * On some platforms this may not be implemented via the Linux IRQ subsystem.
+ * You *cannot* trust the irq argument passed to the callback handler.
+ */
+extern int bind_evtchn_to_irqhandler(
+ unsigned int evtchn,
+ irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char *devname,
+ void *dev_id);
+extern void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id);
+
+extern void irq_suspend(void);
+extern void irq_resume(void);
/* Entry point for notifications into Linux subsystems. */
asmlinkage void evtchn_do_upcall(struct pt_regs *regs);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|