ia64/xen-unstable

changeset 6018: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>
author kaf24@firebug.cl.cam.ac.uk
date Wed Aug 03 12:51:35 2005 +0000 (2005-08-03)
parents f294acb25858
children 33bb0b41aa73 e9b950192ba6
files linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c linux-2.6-xen-sparse/arch/xen/kernel/reboot.c linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c linux-2.6-xen-sparse/drivers/xen/blkback/common.h linux-2.6-xen-sparse/drivers/xen/blkback/interface.c linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6-xen-sparse/drivers/xen/netback/common.h linux-2.6-xen-sparse/drivers/xen/netback/netback.c linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/irq_vectors.h linux-2.6-xen-sparse/include/asm-xen/evtchn.h
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