nfsd: new interface to advertise export features
[safe/jmp/linux-2.6] / drivers / xen / events.c
index 459121c..2f57276 100644 (file)
 static DEFINE_SPINLOCK(irq_mapping_update_lock);
 
 /* IRQ <-> VIRQ mapping. */
-static DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]) = {[0 ... NR_VIRQS-1] = -1};
+static DEFINE_PER_CPU(int [NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1};
 
 /* IRQ <-> IPI mapping */
-static DEFINE_PER_CPU(int, ipi_to_irq[XEN_NR_IPIS]) = {[0 ... XEN_NR_IPIS-1] = -1};
+static DEFINE_PER_CPU(int [XEN_NR_IPIS], ipi_to_irq) = {[0 ... XEN_NR_IPIS-1] = -1};
 
 /* Interrupt types. */
 enum xen_irq_type {
@@ -115,26 +115,27 @@ static struct irq_info mk_unbound_info(void)
 
 static struct irq_info mk_evtchn_info(unsigned short evtchn)
 {
-       return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn };
+       return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn,
+                       .cpu = 0 };
 }
 
 static struct irq_info mk_ipi_info(unsigned short evtchn, enum ipi_vector ipi)
 {
        return (struct irq_info) { .type = IRQT_IPI, .evtchn = evtchn,
-                       .u.ipi = ipi };
+                       .cpu = 0, .u.ipi = ipi };
 }
 
 static struct irq_info mk_virq_info(unsigned short evtchn, unsigned short virq)
 {
        return (struct irq_info) { .type = IRQT_VIRQ, .evtchn = evtchn,
-                       .u.virq = virq };
+                       .cpu = 0, .u.virq = virq };
 }
 
 static struct irq_info mk_pirq_info(unsigned short evtchn,
                                    unsigned short gsi, unsigned short vector)
 {
        return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn,
-                       .u.pirq = { .gsi = gsi, .vector = vector } };
+                       .cpu = 0, .u.pirq = { .gsi = gsi, .vector = vector } };
 }
 
 /*
@@ -150,6 +151,12 @@ static unsigned int evtchn_from_irq(unsigned irq)
        return info_for_irq(irq)->evtchn;
 }
 
+unsigned irq_from_evtchn(unsigned int evtchn)
+{
+       return evtchn_to_irq[evtchn];
+}
+EXPORT_SYMBOL_GPL(irq_from_evtchn);
+
 static enum ipi_vector ipi_from_irq(unsigned irq)
 {
        struct irq_info *info = info_for_irq(irq);
@@ -334,7 +341,7 @@ static int find_unbound_irq(void)
        if (irq == nr_irqs)
                panic("No available IRQ to bind to: increase nr_irqs!\n");
 
-       desc = irq_to_desc_alloc_cpu(irq, 0);
+       desc = irq_to_desc_alloc_node(irq, 0);
        if (WARN_ON(desc == NULL))
                return -1;
 
@@ -375,6 +382,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
        spin_lock(&irq_mapping_update_lock);
 
        irq = per_cpu(ipi_to_irq, cpu)[ipi];
+
        if (irq == -1) {
                irq = find_unbound_irq();
                if (irq < 0)
@@ -391,7 +399,6 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
 
                evtchn_to_irq[evtchn] = irq;
                irq_info[irq] = mk_ipi_info(evtchn, ipi);
-
                per_cpu(ipi_to_irq, cpu)[ipi] = irq;
 
                bind_evtchn_to_cpu(evtchn, cpu);
@@ -595,24 +602,7 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-
-static void xen_do_irq(unsigned irq, struct pt_regs *regs)
-{
-       struct pt_regs *old_regs = set_irq_regs(regs);
-
-       if (WARN_ON(irq == -1))
-               return;
-
-       exit_idle();
-       irq_enter();
-
-       //printk("cpu %d handling irq %d\n", smp_processor_id(), info->irq);
-       handle_irq(irq, regs);
-
-       irq_exit();
-
-       set_irq_regs(old_regs);
-}
+static DEFINE_PER_CPU(unsigned, xed_nesting_count);
 
 /*
  * Search the CPUs pending events bitmasks.  For each one found, map
@@ -626,17 +616,20 @@ static void xen_do_irq(unsigned irq, struct pt_regs *regs)
 void xen_evtchn_do_upcall(struct pt_regs *regs)
 {
        int cpu = get_cpu();
+       struct pt_regs *old_regs = set_irq_regs(regs);
        struct shared_info *s = HYPERVISOR_shared_info;
        struct vcpu_info *vcpu_info = __get_cpu_var(xen_vcpu);
-       static DEFINE_PER_CPU(unsigned, nesting_count);
        unsigned count;
 
+       exit_idle();
+       irq_enter();
+
        do {
                unsigned long pending_words;
 
                vcpu_info->evtchn_upcall_pending = 0;
 
-               if (__get_cpu_var(nesting_count)++)
+               if (__get_cpu_var(xed_nesting_count)++)
                        goto out;
 
 #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
@@ -654,17 +647,21 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
                                int port = (word_idx * BITS_PER_LONG) + bit_idx;
                                int irq = evtchn_to_irq[port];
 
-                               xen_do_irq(irq, regs);
+                               if (irq != -1)
+                                       handle_irq(irq, regs);
                        }
                }
 
                BUG_ON(!irqs_disabled());
 
-               count = __get_cpu_var(nesting_count);
-               __get_cpu_var(nesting_count) = 0;
+               count = __get_cpu_var(xed_nesting_count);
+               __get_cpu_var(xed_nesting_count) = 0;
        } while(count != 1);
 
 out:
+       irq_exit();
+       set_irq_regs(old_regs);
+
        put_cpu();
 }
 
@@ -698,13 +695,13 @@ void rebind_evtchn_irq(int evtchn, int irq)
 }
 
 /* Rebind an evtchn so that it gets delivered to a specific cpu */
-static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
+static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 {
        struct evtchn_bind_vcpu bind_vcpu;
        int evtchn = evtchn_from_irq(irq);
 
        if (!VALID_EVTCHN(evtchn))
-               return;
+               return -1;
 
        /* Send future instances of this interrupt to other vcpu. */
        bind_vcpu.port = evtchn;
@@ -717,13 +714,15 @@ static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
         */
        if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
                bind_evtchn_to_cpu(evtchn, tcpu);
-}
 
+       return 0;
+}
 
-static void set_affinity_irq(unsigned irq, const struct cpumask *dest)
+static int set_affinity_irq(unsigned irq, const struct cpumask *dest)
 {
        unsigned tcpu = cpumask_first(dest);
-       rebind_irq_to_cpu(irq, tcpu);
+
+       return rebind_irq_to_cpu(irq, tcpu);
 }
 
 int resend_irq_on_evtchn(unsigned int irq)
@@ -929,9 +928,9 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
 void __init xen_init_IRQ(void)
 {
        int i;
-       size_t size = nr_cpu_ids * sizeof(struct cpu_evtchn_s);
 
-       cpu_evtchn_mask_p = alloc_bootmem(size);
+       cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s),
+                                   GFP_KERNEL);
        BUG_ON(cpu_evtchn_mask_p == NULL);
 
        init_evtchn_cpu_bindings();