Merge branches 'stable/ia64', 'stable/blkfront-cleanup' and 'stable/cleanup' of git...
[pandora-kernel.git] / drivers / xen / events.c
index c8826b5..149fa87 100644 (file)
@@ -114,7 +114,7 @@ struct cpu_evtchn_s {
 static __initdata struct cpu_evtchn_s init_evtchn_mask = {
        .bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul,
 };
-static struct cpu_evtchn_s *cpu_evtchn_mask_p = &init_evtchn_mask;
+static struct cpu_evtchn_s __refdata *cpu_evtchn_mask_p = &init_evtchn_mask;
 
 static inline unsigned long *cpu_evtchn_mask(int cpu)
 {
@@ -277,7 +277,7 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
 
        BUG_ON(irq == -1);
 #ifdef CONFIG_SMP
-       cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu));
+       cpumask_copy(irq_to_desc(irq)->irq_data.affinity, cpumask_of(cpu));
 #endif
 
        clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq)));
@@ -294,7 +294,7 @@ static void init_evtchn_cpu_bindings(void)
 
        /* By default all event channels notify CPU#0. */
        for_each_irq_desc(i, desc) {
-               cpumask_copy(desc->affinity, cpumask_of(0));
+               cpumask_copy(desc->irq_data.affinity, cpumask_of(0));
        }
 #endif
 
@@ -474,7 +474,7 @@ static bool probing_irq(int irq)
        return desc && desc->action == NULL;
 }
 
-static unsigned int startup_pirq(unsigned int irq)
+static unsigned int __startup_pirq(unsigned int irq)
 {
        struct evtchn_bind_pirq bind_pirq;
        struct irq_info *info = info_for_irq(irq);
@@ -512,9 +512,15 @@ out:
        return 0;
 }
 
-static void shutdown_pirq(unsigned int irq)
+static unsigned int startup_pirq(struct irq_data *data)
+{
+       return __startup_pirq(data->irq);
+}
+
+static void shutdown_pirq(struct irq_data *data)
 {
        struct evtchn_close close;
+       unsigned int irq = data->irq;
        struct irq_info *info = info_for_irq(irq);
        int evtchn = evtchn_from_irq(irq);
 
@@ -534,20 +540,20 @@ static void shutdown_pirq(unsigned int irq)
        info->evtchn = 0;
 }
 
-static void enable_pirq(unsigned int irq)
+static void enable_pirq(struct irq_data *data)
 {
-       startup_pirq(irq);
+       startup_pirq(data);
 }
 
-static void disable_pirq(unsigned int irq)
+static void disable_pirq(struct irq_data *data)
 {
 }
 
-static void ack_pirq(unsigned int irq)
+static void ack_pirq(struct irq_data *data)
 {
-       int evtchn = evtchn_from_irq(irq);
+       int evtchn = evtchn_from_irq(data->irq);
 
-       move_native_irq(irq);
+       move_native_irq(data->irq);
 
        if (VALID_EVTCHN(evtchn)) {
                mask_evtchn(evtchn);
@@ -638,104 +644,46 @@ out:
 }
 
 #ifdef CONFIG_PCI_MSI
-#include <linux/msi.h>
-#include "../pci/msi.h"
-
-static int find_unbound_pirq(int type)
+int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
 {
-       int rc, i;
+       int rc;
        struct physdev_get_free_pirq op_get_free_pirq;
-       op_get_free_pirq.type = type;
 
+       op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI;
        rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq);
-       if (!rc)
-               return op_get_free_pirq.pirq;
-
-       for (i = 0; i < nr_irqs; i++) {
-               if (pirq_to_irq[i] < 0)
-                       return i;
-       }
-       return -1;
-}
 
-void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc)
-{
-       spin_lock(&irq_mapping_update_lock);
+       WARN_ONCE(rc == -ENOSYS,
+                 "hypervisor does not support the PHYSDEVOP_get_free_pirq interface\n");
 
-       if (alloc & XEN_ALLOC_IRQ) {
-               *irq = xen_allocate_irq_dynamic();
-               if (*irq == -1)
-                       goto out;
-       }
-
-       if (alloc & XEN_ALLOC_PIRQ) {
-               *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI);
-               if (*pirq == -1)
-                       goto out;
-       }
-
-       set_irq_chip_and_handler_name(*irq, &xen_pirq_chip,
-                                     handle_level_irq, name);
-
-       irq_info[*irq] = mk_pirq_info(0, *pirq, 0, 0);
-       pirq_to_irq[*pirq] = *irq;
-
-out:
-       spin_unlock(&irq_mapping_update_lock);
+       return rc ? -1 : op_get_free_pirq.pirq;
 }
 
-int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type)
+int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
+                            int pirq, int vector, const char *name)
 {
-       int irq = -1;
-       struct physdev_map_pirq map_irq;
-       int rc;
-       int pos;
-       u32 table_offset, bir;
-
-       memset(&map_irq, 0, sizeof(map_irq));
-       map_irq.domid = DOMID_SELF;
-       map_irq.type = MAP_PIRQ_TYPE_MSI;
-       map_irq.index = -1;
-       map_irq.pirq = -1;
-       map_irq.bus = dev->bus->number;
-       map_irq.devfn = dev->devfn;
-
-       if (type == PCI_CAP_ID_MSIX) {
-               pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-
-               pci_read_config_dword(dev, msix_table_offset_reg(pos),
-                                       &table_offset);
-               bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
-
-               map_irq.table_base = pci_resource_start(dev, bir);
-               map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
-       }
+       int irq, ret;
 
        spin_lock(&irq_mapping_update_lock);
 
        irq = xen_allocate_irq_dynamic();
-
        if (irq == -1)
                goto out;
 
-       rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
-       if (rc) {
-               printk(KERN_WARNING "xen map irq failed %d\n", rc);
-
-               xen_free_irq(irq);
-
-               irq = -1;
-               goto out;
-       }
-       irq_info[irq] = mk_pirq_info(0, map_irq.pirq, 0, map_irq.index);
-
        set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
-                       handle_level_irq,
-                       (type == PCI_CAP_ID_MSIX) ? "msi-x":"msi");
+                                     handle_level_irq, name);
 
+       irq_info[irq] = mk_pirq_info(0, pirq, 0, vector);
+       pirq_to_irq[pirq] = irq;
+       ret = set_irq_msi(irq, msidesc);
+       if (ret < 0)
+               goto error_irq;
 out:
        spin_unlock(&irq_mapping_update_lock);
        return irq;
+error_irq:
+       spin_unlock(&irq_mapping_update_lock);
+       xen_free_irq(irq);
+       return -1;
 }
 #endif
 
@@ -760,8 +708,9 @@ int xen_destroy_irq(int irq)
                        printk(KERN_WARNING "unmap irq failed %d\n", rc);
                        goto out;
                }
-               pirq_to_irq[info->u.pirq.pirq] = -1;
        }
+       pirq_to_irq[info->u.pirq.pirq] = -1;
+
        irq_info[irq] = mk_unbound_info();
 
        xen_free_irq(irq);
@@ -971,7 +920,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
        if (irq < 0)
                return irq;
 
-       irqflags |= IRQF_NO_SUSPEND;
+       irqflags |= IRQF_NO_SUSPEND | IRQF_FORCE_RESUME;
        retval = request_irq(irq, handler, irqflags, devname, dev_id);
        if (retval != 0) {
                unbind_from_irq(irq);
@@ -1215,11 +1164,12 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
        return 0;
 }
 
-static int set_affinity_irq(unsigned irq, const struct cpumask *dest)
+static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
+                           bool force)
 {
        unsigned tcpu = cpumask_first(dest);
 
-       return rebind_irq_to_cpu(irq, tcpu);
+       return rebind_irq_to_cpu(data->irq, tcpu);
 }
 
 int resend_irq_on_evtchn(unsigned int irq)
@@ -1238,35 +1188,35 @@ int resend_irq_on_evtchn(unsigned int irq)
        return 1;
 }
 
-static void enable_dynirq(unsigned int irq)
+static void enable_dynirq(struct irq_data *data)
 {
-       int evtchn = evtchn_from_irq(irq);
+       int evtchn = evtchn_from_irq(data->irq);
 
        if (VALID_EVTCHN(evtchn))
                unmask_evtchn(evtchn);
 }
 
-static void disable_dynirq(unsigned int irq)
+static void disable_dynirq(struct irq_data *data)
 {
-       int evtchn = evtchn_from_irq(irq);
+       int evtchn = evtchn_from_irq(data->irq);
 
        if (VALID_EVTCHN(evtchn))
                mask_evtchn(evtchn);
 }
 
-static void ack_dynirq(unsigned int irq)
+static void ack_dynirq(struct irq_data *data)
 {
-       int evtchn = evtchn_from_irq(irq);
+       int evtchn = evtchn_from_irq(data->irq);
 
-       move_masked_irq(irq);
+       move_masked_irq(data->irq);
 
        if (VALID_EVTCHN(evtchn))
                unmask_evtchn(evtchn);
 }
 
-static int retrigger_dynirq(unsigned int irq)
+static int retrigger_dynirq(struct irq_data *data)
 {
-       int evtchn = evtchn_from_irq(irq);
+       int evtchn = evtchn_from_irq(data->irq);
        struct shared_info *sh = HYPERVISOR_shared_info;
        int ret = 0;
 
@@ -1315,7 +1265,7 @@ static void restore_cpu_pirqs(void)
 
                printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq);
 
-               startup_pirq(irq);
+               __startup_pirq(irq);
        }
 }
 
@@ -1426,7 +1376,6 @@ void xen_poll_irq(int irq)
 void xen_irq_resume(void)
 {
        unsigned int cpu, irq, evtchn;
-       struct irq_desc *desc;
 
        init_evtchn_cpu_bindings();
 
@@ -1446,65 +1395,48 @@ void xen_irq_resume(void)
                restore_cpu_ipis(cpu);
        }
 
-       /*
-        * Unmask any IRQF_NO_SUSPEND IRQs which are enabled. These
-        * are not handled by the IRQ core.
-        */
-       for_each_irq_desc(irq, desc) {
-               if (!desc->action || !(desc->action->flags & IRQF_NO_SUSPEND))
-                       continue;
-               if (desc->status & IRQ_DISABLED)
-                       continue;
-
-               evtchn = evtchn_from_irq(irq);
-               if (evtchn == -1)
-                       continue;
-
-               unmask_evtchn(evtchn);
-       }
-
        restore_cpu_pirqs();
 }
 
 static struct irq_chip xen_dynamic_chip __read_mostly = {
-       .name           = "xen-dyn",
+       .name                   = "xen-dyn",
 
-       .disable        = disable_dynirq,
-       .mask           = disable_dynirq,
-       .unmask         = enable_dynirq,
+       .irq_disable            = disable_dynirq,
+       .irq_mask               = disable_dynirq,
+       .irq_unmask             = enable_dynirq,
 
-       .eoi            = ack_dynirq,
-       .set_affinity   = set_affinity_irq,
-       .retrigger      = retrigger_dynirq,
+       .irq_eoi                = ack_dynirq,
+       .irq_set_affinity       = set_affinity_irq,
+       .irq_retrigger          = retrigger_dynirq,
 };
 
 static struct irq_chip xen_pirq_chip __read_mostly = {
-       .name           = "xen-pirq",
+       .name                   = "xen-pirq",
 
-       .startup        = startup_pirq,
-       .shutdown       = shutdown_pirq,
+       .irq_startup            = startup_pirq,
+       .irq_shutdown           = shutdown_pirq,
 
-       .enable         = enable_pirq,
-       .unmask         = enable_pirq,
+       .irq_enable             = enable_pirq,
+       .irq_unmask             = enable_pirq,
 
-       .disable        = disable_pirq,
-       .mask           = disable_pirq,
+       .irq_disable            = disable_pirq,
+       .irq_mask               = disable_pirq,
 
-       .ack            = ack_pirq,
+       .irq_ack                = ack_pirq,
 
-       .set_affinity   = set_affinity_irq,
+       .irq_set_affinity       = set_affinity_irq,
 
-       .retrigger      = retrigger_dynirq,
+       .irq_retrigger          = retrigger_dynirq,
 };
 
 static struct irq_chip xen_percpu_chip __read_mostly = {
-       .name           = "xen-percpu",
+       .name                   = "xen-percpu",
 
-       .disable        = disable_dynirq,
-       .mask           = disable_dynirq,
-       .unmask         = enable_dynirq,
+       .irq_disable            = disable_dynirq,
+       .irq_mask               = disable_dynirq,
+       .irq_unmask             = enable_dynirq,
 
-       .ack            = ack_dynirq,
+       .irq_ack                = ack_dynirq,
 };
 
 int xen_set_callback_via(uint64_t via)