xen-vtx-unstable
changeset 6003:d9442abaa980
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@xensource.com>
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@xensource.com>
line diff
1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Wed Aug 03 09:35:38 2005 +0000 1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Wed Aug 03 12:51:35 2005 +0000 1.3 @@ -62,6 +62,8 @@ 1.4 #include <mach_wakecpu.h> 1.5 #include <smpboot_hooks.h> 1.6 1.7 +#include <asm-xen/evtchn.h> 1.8 + 1.9 /* Set if we find a B stepping CPU */ 1.10 static int __initdata smp_b_stepping; 1.11 1.12 @@ -1534,13 +1536,13 @@ void smp_intr_init(void) 1.13 int cpu = smp_processor_id(); 1.14 1.15 per_cpu(resched_irq, cpu) = 1.16 - bind_ipi_on_cpu_to_irq(RESCHEDULE_VECTOR); 1.17 + bind_ipi_to_irq(RESCHEDULE_VECTOR); 1.18 sprintf(resched_name[cpu], "resched%d", cpu); 1.19 BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt, 1.20 SA_INTERRUPT, resched_name[cpu], NULL)); 1.21 1.22 per_cpu(callfunc_irq, cpu) = 1.23 - bind_ipi_on_cpu_to_irq(CALL_FUNCTION_VECTOR); 1.24 + bind_ipi_to_irq(CALL_FUNCTION_VECTOR); 1.25 sprintf(callfunc_name[cpu], "callfunc%d", cpu); 1.26 BUG_ON(request_irq(per_cpu(callfunc_irq, cpu), 1.27 smp_call_function_interrupt,
2.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Wed Aug 03 09:35:38 2005 +0000 2.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Wed Aug 03 12:51:35 2005 +0000 2.3 @@ -70,6 +70,8 @@ 2.4 2.5 #include "io_ports.h" 2.6 2.7 +#include <asm-xen/evtchn.h> 2.8 + 2.9 extern spinlock_t i8259A_lock; 2.10 int pit_latch_buggy; /* extern */ 2.11
3.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Wed Aug 03 09:35:38 2005 +0000 3.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Wed Aug 03 12:51:35 2005 +0000 3.3 @@ -229,12 +229,13 @@ void unbind_virq_from_irq(int virq) 3.4 if ( HYPERVISOR_event_channel_op(&op) != 0 ) 3.5 panic("Failed to unbind virtual IRQ %d\n", virq); 3.6 3.7 - /* This is a slight hack. Interdomain ports can be allocated 3.8 - directly by userspace, and at that point they get bound by 3.9 - Xen to vcpu 0. We therefore need to make sure that if we 3.10 - get an event on an event channel we don't know about vcpu 0 3.11 - handles it. Binding channels to vcpu 0 when closing them 3.12 - achieves this. */ 3.13 + /* 3.14 + * This is a slight hack. Interdomain ports can be allocated directly 3.15 + * by userspace, and at that point they get bound by Xen to vcpu 0. We 3.16 + * therefore need to make sure that if we get an event on an event 3.17 + * channel we don't know about vcpu 0 handles it. Binding channels to 3.18 + * vcpu 0 when closing them achieves this. 3.19 + */ 3.20 bind_evtchn_to_cpu(evtchn, 0); 3.21 evtchn_to_irq[evtchn] = -1; 3.22 irq_to_evtchn[irq] = -1; 3.23 @@ -244,7 +245,7 @@ void unbind_virq_from_irq(int virq) 3.24 spin_unlock(&irq_mapping_update_lock); 3.25 } 3.26 3.27 -int bind_ipi_on_cpu_to_irq(int ipi) 3.28 +int bind_ipi_to_irq(int ipi) 3.29 { 3.30 evtchn_op_t op; 3.31 int evtchn, irq; 3.32 @@ -306,7 +307,7 @@ void unbind_ipi_from_irq(int ipi) 3.33 spin_unlock(&irq_mapping_update_lock); 3.34 } 3.35 3.36 -int bind_evtchn_to_irq(int evtchn) 3.37 +int bind_evtchn_to_irq(unsigned int evtchn) 3.38 { 3.39 int irq; 3.40 3.41 @@ -326,7 +327,7 @@ int bind_evtchn_to_irq(int evtchn) 3.42 return irq; 3.43 } 3.44 3.45 -void unbind_evtchn_from_irq(int evtchn) 3.46 +void unbind_evtchn_from_irq(unsigned int evtchn) 3.47 { 3.48 int irq = evtchn_to_irq[evtchn]; 3.49 3.50 @@ -341,6 +342,33 @@ void unbind_evtchn_from_irq(int evtchn) 3.51 spin_unlock(&irq_mapping_update_lock); 3.52 } 3.53 3.54 +int bind_evtchn_to_irqhandler( 3.55 + unsigned int evtchn, 3.56 + irqreturn_t (*handler)(int, void *, struct pt_regs *), 3.57 + unsigned long irqflags, 3.58 + const char *devname, 3.59 + void *dev_id) 3.60 +{ 3.61 + unsigned int irq; 3.62 + int retval; 3.63 + 3.64 + BUG_ON((irqflags & ~SA_SAMPLE_RANDOM) != 0); 3.65 + 3.66 + irq = bind_evtchn_to_irq(evtchn); 3.67 + retval = request_irq(irq, handler, irqflags, devname, dev_id); 3.68 + if ( retval != 0 ) 3.69 + unbind_evtchn_from_irq(evtchn); 3.70 + 3.71 + return retval; 3.72 +} 3.73 + 3.74 +void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id) 3.75 +{ 3.76 + unsigned int irq = evtchn_to_irq[evtchn]; 3.77 + free_irq(irq, dev_id); 3.78 + unbind_evtchn_from_irq(evtchn); 3.79 +} 3.80 + 3.81 static void do_nothing_function(void *ign) 3.82 { 3.83 } 3.84 @@ -358,34 +386,33 @@ static void rebind_irq_to_cpu(unsigned i 3.85 return; 3.86 } 3.87 3.88 - /* Tell Xen to send future instances of this interrupt to the 3.89 - other vcpu */ 3.90 + /* Tell Xen to send future instances of this interrupt to other vcpu. */ 3.91 op.cmd = EVTCHNOP_bind_vcpu; 3.92 op.u.bind_vcpu.port = evtchn; 3.93 op.u.bind_vcpu.vcpu = tcpu; 3.94 3.95 - /* If this fails, it usually just indicates that we're dealing 3.96 - with a virq or IPI channel, which don't actually need to be 3.97 - rebound. Ignore it, but don't do the xenlinux-level rebind 3.98 - in that case. */ 3.99 + /* 3.100 + * If this fails, it usually just indicates that we're dealing with a virq 3.101 + * or IPI channel, which don't actually need to be rebound. Ignore it, 3.102 + * but don't do the xenlinux-level rebind in that case. 3.103 + */ 3.104 if (HYPERVISOR_event_channel_op(&op) >= 0) 3.105 bind_evtchn_to_cpu(evtchn, tcpu); 3.106 3.107 spin_unlock(&irq_mapping_update_lock); 3.108 3.109 - /* Now send the new target processor a NOP IPI. When this 3.110 - returns, it will check for any pending interrupts, and so 3.111 - service any that got delivered to the wrong processor by 3.112 - mistake. */ 3.113 - /* XXX: The only time this is called with interrupts disabled is 3.114 - from the hotplug/hotunplug path. In that case, all cpus are 3.115 - stopped with interrupts disabled, and the missed interrupts 3.116 - will be picked up when they start again. This is kind of a 3.117 - hack. 3.118 - */ 3.119 - if (!irqs_disabled()) { 3.120 + /* 3.121 + * Now send the new target processor a NOP IPI. When this returns, it 3.122 + * will check for any pending interrupts, and so service any that got 3.123 + * delivered to the wrong processor by mistake. 3.124 + * 3.125 + * XXX: The only time this is called with interrupts disabled is from the 3.126 + * hotplug/hotunplug path. In that case, all cpus are stopped with 3.127 + * interrupts disabled, and the missed interrupts will be picked up when 3.128 + * they start again. This is kind of a hack. 3.129 + */ 3.130 + if (!irqs_disabled()) 3.131 smp_call_function(do_nothing_function, NULL, 0, 0); 3.132 - } 3.133 } 3.134 3.135
4.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 03 09:35:38 2005 +0000 4.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 03 12:51:35 2005 +0000 4.3 @@ -12,6 +12,7 @@ static int errno; 4.4 #include <asm/irq.h> 4.5 #include <asm/mmu_context.h> 4.6 #include <asm-xen/ctrl_if.h> 4.7 +#include <asm-xen/evtchn.h> 4.8 #include <asm-xen/hypervisor.h> 4.9 #include <asm-xen/xen-public/dom0_ops.h> 4.10 #include <asm-xen/linux-public/suspend.h>
5.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Wed Aug 03 09:35:38 2005 +0000 5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Wed Aug 03 12:51:35 2005 +0000 5.3 @@ -12,7 +12,6 @@ 5.4 */ 5.5 5.6 #include "common.h" 5.7 -#include <asm-xen/evtchn.h> 5.8 #ifdef CONFIG_XEN_BLKDEV_GRANT 5.9 #include <asm-xen/xen-public/grant_table.h> 5.10 #endif
6.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Wed Aug 03 09:35:38 2005 +0000 6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Wed Aug 03 12:51:35 2005 +0000 6.3 @@ -13,6 +13,7 @@ 6.4 #include <asm/setup.h> 6.5 #include <asm/pgalloc.h> 6.6 #include <asm-xen/ctrl_if.h> 6.7 +#include <asm-xen/evtchn.h> 6.8 #include <asm-xen/hypervisor.h> 6.9 #include <asm-xen/xen-public/io/blkif.h> 6.10 #include <asm-xen/xen-public/io/ring.h> 6.11 @@ -42,7 +43,6 @@ typedef struct blkif_st { 6.12 /* Physical parameters of the comms window. */ 6.13 unsigned long shmem_frame; 6.14 unsigned int evtchn; 6.15 - int irq; 6.16 /* Comms information. */ 6.17 blkif_back_ring_t blk_ring; 6.18 /* VBDs attached to this interface. */
7.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Wed Aug 03 09:35:38 2005 +0000 7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Wed Aug 03 12:51:35 2005 +0000 7.3 @@ -38,7 +38,7 @@ static void __blkif_disconnect_complete( 7.4 * may be outstanding requests at the disc whose asynchronous responses 7.5 * must still be notified to the remote driver. 7.6 */ 7.7 - unbind_evtchn_from_irq(blkif->evtchn); 7.8 + unbind_evtchn_from_irqhandler(blkif->evtchn, blkif); 7.9 7.10 #ifdef CONFIG_XEN_BLKDEV_GRANT 7.11 { 7.12 @@ -247,12 +247,12 @@ void blkif_connect(blkif_be_connect_t *c 7.13 BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); 7.14 7.15 blkif->evtchn = evtchn; 7.16 - blkif->irq = bind_evtchn_to_irq(evtchn); 7.17 blkif->shmem_frame = shmem_frame; 7.18 blkif->status = CONNECTED; 7.19 blkif_get(blkif); 7.20 7.21 - request_irq(blkif->irq, blkif_be_int, 0, "blkif-backend", blkif); 7.22 + bind_evtchn_to_irqhandler( 7.23 + blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif); 7.24 7.25 connect->status = BLKIF_BE_STATUS_OKAY; 7.26 } 7.27 @@ -277,7 +277,6 @@ int blkif_disconnect(blkif_be_disconnect 7.28 blkif->status = DISCONNECTING; 7.29 blkif->disconnect_rspid = rsp_id; 7.30 wmb(); /* Let other CPUs see the status change. */ 7.31 - free_irq(blkif->irq, blkif); 7.32 blkif_deschedule(blkif); 7.33 blkif_put(blkif); 7.34 return 0; /* Caller should not send response message. */
8.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Wed Aug 03 09:35:38 2005 +0000 8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Wed Aug 03 12:51:35 2005 +0000 8.3 @@ -78,7 +78,6 @@ static void vbd_update(void){}; 8.4 static int blkif_handle = 0; 8.5 static unsigned int blkif_state = BLKIF_STATE_CLOSED; 8.6 static unsigned int blkif_evtchn = 0; 8.7 -static unsigned int blkif_irq = 0; 8.8 8.9 static int blkif_control_rsp_valid; 8.10 static blkif_response_t blkif_control_rsp; 8.11 @@ -1159,10 +1158,7 @@ static void blkif_free(void) 8.12 free_page((unsigned long)blk_ring.sring); 8.13 blk_ring.sring = NULL; 8.14 } 8.15 - free_irq(blkif_irq, NULL); 8.16 - blkif_irq = 0; 8.17 - 8.18 - unbind_evtchn_from_irq(blkif_evtchn); 8.19 + unbind_evtchn_from_irqhandler(blkif_evtchn, NULL); 8.20 blkif_evtchn = 0; 8.21 } 8.22 8.23 @@ -1266,12 +1262,12 @@ static void blkif_connect(blkif_fe_inter 8.24 int err = 0; 8.25 8.26 blkif_evtchn = status->evtchn; 8.27 - blkif_irq = bind_evtchn_to_irq(blkif_evtchn); 8.28 8.29 - err = request_irq(blkif_irq, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL); 8.30 - if ( err ) 8.31 + err = bind_evtchn_to_irqhandler( 8.32 + blkif_evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL); 8.33 + if ( err != 0 ) 8.34 { 8.35 - WPRINTK("request_irq failed (err=%d)\n", err); 8.36 + WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); 8.37 return; 8.38 } 8.39
9.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 03 09:35:38 2005 +0000 9.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 03 12:51:35 2005 +0000 9.3 @@ -15,6 +15,7 @@ 9.4 #include <linux/netdevice.h> 9.5 #include <linux/etherdevice.h> 9.6 #include <asm-xen/ctrl_if.h> 9.7 +#include <asm-xen/evtchn.h> 9.8 #include <asm-xen/xen-public/io/netif.h> 9.9 #include <asm/io.h> 9.10 #include <asm/pgalloc.h>
10.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 03 09:35:38 2005 +0000 10.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 03 12:51:35 2005 +0000 10.3 @@ -12,7 +12,6 @@ 10.4 10.5 #include "common.h" 10.6 #include <asm-xen/balloon.h> 10.7 -#include <asm-xen/evtchn.h> 10.8 10.9 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) 10.10 #include <linux/delay.h>
11.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h Wed Aug 03 09:35:38 2005 +0000 11.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h Wed Aug 03 12:51:35 2005 +0000 11.3 @@ -124,18 +124,4 @@ 11.4 #define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE) 11.5 #define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE) 11.6 11.7 -#ifndef __ASSEMBLY__ 11.8 -/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */ 11.9 -extern int bind_virq_to_irq(int virq); 11.10 -extern void unbind_virq_from_irq(int virq); 11.11 -extern int bind_ipi_to_irq(int ipi); 11.12 -extern int bind_ipi_on_cpu_to_irq(int ipi); 11.13 -extern void unbind_ipi_from_irq(int ipi); 11.14 -extern int bind_evtchn_to_irq(int evtchn); 11.15 -extern void unbind_evtchn_from_irq(int evtchn); 11.16 - 11.17 -extern void irq_suspend(void); 11.18 -extern void irq_resume(void); 11.19 -#endif /* __ASSEMBLY__ */ 11.20 - 11.21 #endif /* _ASM_IRQ_VECTORS_H */
12.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h Wed Aug 03 09:35:38 2005 +0000 12.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h Wed Aug 03 12:51:35 2005 +0000 12.3 @@ -122,18 +122,4 @@ 12.4 #define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE) 12.5 #define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE) 12.6 12.7 -#ifndef __ASSEMBLY__ 12.8 -/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */ 12.9 -extern int bind_virq_to_irq(int virq); 12.10 -extern void unbind_virq_from_irq(int virq); 12.11 -extern int bind_ipi_to_irq(int ipi); 12.12 -extern int bind_ipi_on_cpu_to_irq(int ipi); 12.13 -extern void unbind_ipi_from_irq(int ipi); 12.14 -extern int bind_evtchn_to_irq(int evtchn); 12.15 -extern void unbind_evtchn_from_irq(int evtchn); 12.16 - 12.17 -extern void irq_suspend(void); 12.18 -extern void irq_resume(void); 12.19 -#endif /* __ASSEMBLY__ */ 12.20 - 12.21 #endif /* _ASM_IRQ_VECTORS_H */
13.1 --- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Wed Aug 03 09:35:38 2005 +0000 13.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Wed Aug 03 12:51:35 2005 +0000 13.3 @@ -32,6 +32,7 @@ 13.4 #define __ASM_EVTCHN_H__ 13.5 13.6 #include <linux/config.h> 13.7 +#include <linux/interrupt.h> 13.8 #include <asm-xen/hypervisor.h> 13.9 #include <asm/ptrace.h> 13.10 #include <asm-xen/synch_bitops.h> 13.11 @@ -42,6 +43,34 @@ 13.12 * LOW-LEVEL DEFINITIONS 13.13 */ 13.14 13.15 +/* Dynamically bind a VIRQ source to Linux IRQ space. */ 13.16 +extern int bind_virq_to_irq(int virq); 13.17 +extern void unbind_virq_from_irq(int virq); 13.18 + 13.19 +/* Dynamically bind an IPI source to Linux IRQ space. */ 13.20 +extern int bind_ipi_to_irq(int ipi); 13.21 +extern void unbind_ipi_from_irq(int ipi); 13.22 + 13.23 +/* Dynamically bind an event-channel port to Linux IRQ space. */ 13.24 +extern int bind_evtchn_to_irq(unsigned int evtchn); 13.25 +extern void unbind_evtchn_from_irq(unsigned int evtchn); 13.26 + 13.27 +/* 13.28 + * Dynamically bind an event-channel port to an IRQ-like callback handler. 13.29 + * On some platforms this may not be implemented via the Linux IRQ subsystem. 13.30 + * You *cannot* trust the irq argument passed to the callback handler. 13.31 + */ 13.32 +extern int bind_evtchn_to_irqhandler( 13.33 + unsigned int evtchn, 13.34 + irqreturn_t (*handler)(int, void *, struct pt_regs *), 13.35 + unsigned long irqflags, 13.36 + const char *devname, 13.37 + void *dev_id); 13.38 +extern void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id); 13.39 + 13.40 +extern void irq_suspend(void); 13.41 +extern void irq_resume(void); 13.42 + 13.43 /* Entry point for notifications into Linux subsystems. */ 13.44 asmlinkage void evtchn_do_upcall(struct pt_regs *regs); 13.45