Merge branches 'stable/backend.base.v3' and 'stable/gntalloc.v7' of git://git.kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 May 2011 23:14:25 +0000 (16:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 May 2011 23:14:25 +0000 (16:14 -0700)
* 'stable/backend.base.v3' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen/pci: Fix compiler error when CONFIG_XEN_PRIVILEGED_GUEST is not set.
  xen/p2m: Add EXPORT_SYMBOL_GPL to the M2P override functions.
  xen/p2m/m2p/gnttab: Support GNTMAP_host_map in the M2P override.
  xen/irq: The Xen hypervisor cleans up the PIRQs if the other domain forgot.
  xen/irq: Export 'xen_pirq_from_irq' function.
  xen/irq: Add support to check if IRQ line is shared with other domains.
  xen/irq: Check if the PCI device is owned by a domain different than DOMID_SELF.
  xen/pci: Add xen_[find|register|unregister]_device_domain_owner functions.

* 'stable/gntalloc.v7' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen/gntdev,gntalloc: Remove unneeded VM flags

1  2  3 
drivers/xen/events.c
drivers/xen/gntdev.c

@@@@ -119,86 -120,88 -128,46 +120,88 @@@@ static struct irq_chip xen_dynamic_chip
   static struct irq_chip xen_percpu_chip;
   static struct irq_chip xen_pirq_chip;
   
  -/* Constructor for packed IRQ information. */
  -static struct irq_info mk_unbound_info(void)
  +/* Get info for IRQ */
  +static struct irq_info *info_for_irq(unsigned irq)
   {
  -     return (struct irq_info) { .type = IRQT_UNBOUND };
  +     return irq_get_handler_data(irq);
   }
   
  -static struct irq_info mk_evtchn_info(unsigned short evtchn)
  +/* Constructors for packed IRQ information. */
  +static void xen_irq_info_common_init(struct irq_info *info,
  +                                  unsigned irq,
  +                                  enum xen_irq_type type,
  +                                  unsigned short evtchn,
  +                                  unsigned short cpu)
   {
  -     return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn,
  -                     .cpu = 0 };
  +
  +     BUG_ON(info->type != IRQT_UNBOUND && info->type != type);
  +
  +     info->type = type;
  +     info->irq = irq;
  +     info->evtchn = evtchn;
  +     info->cpu = cpu;
  +
  +     evtchn_to_irq[evtchn] = irq;
   }
   
  -static struct irq_info mk_ipi_info(unsigned short evtchn, enum ipi_vector ipi)
  +static void xen_irq_info_evtchn_init(unsigned irq,
  +                                  unsigned short evtchn)
   {
  -     return (struct irq_info) { .type = IRQT_IPI, .evtchn = evtchn,
  -                     .cpu = 0, .u.ipi = ipi };
  +     struct irq_info *info = info_for_irq(irq);
  +
  +     xen_irq_info_common_init(info, irq, IRQT_EVTCHN, evtchn, 0);
   }
   
  -static struct irq_info mk_virq_info(unsigned short evtchn, unsigned short virq)
  +static void xen_irq_info_ipi_init(unsigned cpu,
  +                               unsigned irq,
  +                               unsigned short evtchn,
  +                               enum ipi_vector ipi)
   {
  -     return (struct irq_info) { .type = IRQT_VIRQ, .evtchn = evtchn,
  -                     .cpu = 0, .u.virq = virq };
  +     struct irq_info *info = info_for_irq(irq);
  +
  +     xen_irq_info_common_init(info, irq, IRQT_IPI, evtchn, 0);
  +
  +     info->u.ipi = ipi;
  +
  +     per_cpu(ipi_to_irq, cpu)[ipi] = irq;
   }
   
  -static struct irq_info mk_pirq_info(unsigned short evtchn, unsigned short pirq,
  -                                 unsigned short gsi, unsigned short vector)
  +static void xen_irq_info_virq_init(unsigned cpu,
  +                                unsigned irq,
  +                                unsigned short evtchn,
  +                                unsigned short virq)
   {
  -     return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn,
  -                     .cpu = 0,
  -                     .u.pirq = { .pirq = pirq, .gsi = gsi, .vector = vector } };
  +     struct irq_info *info = info_for_irq(irq);
  +
  +     xen_irq_info_common_init(info, irq, IRQT_VIRQ, evtchn, 0);
  +
  +     info->u.virq = virq;
  +
  +     per_cpu(virq_to_irq, cpu)[virq] = irq;
   }
   
  -/*
  - * Accessors for packed IRQ information.
  - */
  -static struct irq_info *info_for_irq(unsigned irq)
  +static void xen_irq_info_pirq_init(unsigned irq,
  +                                unsigned short evtchn,
  +                                unsigned short pirq,
  +                                unsigned short gsi,
  +                                unsigned short vector,
+ +                                uint16_t domid,
  +                                unsigned char flags)
   {
  -     return &irq_info[irq];
  +     struct irq_info *info = info_for_irq(irq);
  +
  +     xen_irq_info_common_init(info, irq, IRQT_PIRQ, evtchn, 0);
  +
  +     info->u.pirq.pirq = pirq;
  +     info->u.pirq.gsi = gsi;
  +     info->u.pirq.vector = vector;
+ +     info->u.pirq.domid = domid;
  +     info->u.pirq.flags = flags;
   }
   
  +/*
  + * Accessors for packed IRQ information.
  + */
   static unsigned int evtchn_from_irq(unsigned irq)
   {
        if (unlikely(WARN(irq < 0 || irq >= nr_irqs, "Invalid irq %d!\n", irq)))
@@@@ -655,8 -658,8 -663,9 +658,8 @@@@ int xen_bind_pirq_gsi_to_irq(unsigned g
                goto out;
        }
   
-       xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector,
  -     irq_info[irq] = mk_pirq_info(0, pirq, gsi, irq_op.vector);
  -     irq_info[irq].u.pirq.flags |= shareable ? PIRQ_SHAREABLE : 0;
  -     pirq_to_irq[pirq] = irq;
+ +     xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, DOMID_SELF,
  +                            shareable ? PIRQ_SHAREABLE : 0);
   
   out:
        spin_unlock(&irq_mapping_update_lock);
   }
   
   #ifdef CONFIG_PCI_MSI
  -#include <linux/msi.h>
  -#include "../pci/msi.h"
  -
  -void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc)
  +int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
   {
  -     spin_lock(&irq_mapping_update_lock);
  -
  -     if (alloc & XEN_ALLOC_IRQ) {
  -             *irq = find_unbound_irq();
  -             if (*irq == -1)
  -                     goto out;
  -     }
  -
  -     if (alloc & XEN_ALLOC_PIRQ) {
  -             *pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI);
  -             if (*pirq == -1)
  -                     goto out;
  -     }
  +     int rc;
  +     struct physdev_get_free_pirq op_get_free_pirq;
   
  -     set_irq_chip_and_handler_name(*irq, &xen_pirq_chip,
  -                                   handle_level_irq, name);
  +     op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI;
  +     rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq);
   
  -     irq_info[*irq] = mk_pirq_info(0, *pirq, 0, 0);
  -     pirq_to_irq[*pirq] = *irq;
  +     WARN_ONCE(rc == -ENOSYS,
  +               "hypervisor does not support the PHYSDEVOP_get_free_pirq interface\n");
   
  -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 pirq, int vector, const char *name,
+ +                          domid_t domid)
   {
  -     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);
   
        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);
  -
  -             irq_free_desc(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");
  +     irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq,
  +                                   name);
   
-       xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0);
+ +     xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, domid, 0);
  +     ret = irq_set_msi_desc(irq, msidesc);
  +     if (ret < 0)
  +             goto error_irq;
   out:
        spin_unlock(&irq_mapping_update_lock);
        return irq;
        return rc;
   }
   
  -int xen_vector_from_irq(unsigned irq)
  +int xen_irq_from_pirq(unsigned pirq)
   {
  -     return vector_from_irq(irq);
  -}
  +     int irq;
   
  -int xen_gsi_from_irq(unsigned irq)
  -{
  -     return gsi_from_irq(irq);
  +     struct irq_info *info;
  +
  +     spin_lock(&irq_mapping_update_lock);
  +
  +     list_for_each_entry(info, &xen_irq_list_head, list) {
  +             if (info == NULL || info->type != IRQT_PIRQ)
  +                     continue;
  +             irq = info->irq;
  +             if (info->u.pirq.pirq == pirq)
  +                     goto out;
  +     }
  +     irq = -1;
  +out:
  +     spin_unlock(&irq_mapping_update_lock);
  +
  +     return irq;
   }
   
  -int xen_irq_from_pirq(unsigned pirq)
+ +
+ +int xen_pirq_from_irq(unsigned irq)
+  {
  -     return pirq_to_irq[pirq];
+ +     return pirq_from_irq(irq);
+  }
  -
+ +EXPORT_SYMBOL_GPL(xen_pirq_from_irq);
   int bind_evtchn_to_irq(unsigned int evtchn)
   {
        int irq;
@@@@ -912,11 -929,12 -945,10 +929,11 @@@@ int bind_evtchn_to_irqhandler(unsigned 
                              unsigned long irqflags,
                              const char *devname, void *dev_id)
   {
 --     unsigned int irq;
 --     int retval;
 ++     int irq, retval;
   
        irq = bind_evtchn_to_irq(evtchn);
  +     if (irq < 0)
  +             return irq;
        retval = request_irq(irq, handler, irqflags, devname, dev_id);
        if (retval != 0) {
                unbind_from_irq(irq);
@@@@ -954,11 -972,12 -963,10 +971,11 @@@@ int bind_virq_to_irqhandler(unsigned in
                            irq_handler_t handler,
                            unsigned long irqflags, const char *devname, void *dev_id)
   {
 --     unsigned int irq;
 --     int retval;
 ++     int irq, retval;
   
        irq = bind_virq_to_irq(virq, cpu);
  +     if (irq < 0)
  +             return irq;
        retval = request_irq(irq, handler, irqflags, devname, dev_id);
        if (retval != 0) {
                unbind_from_irq(irq);
@@@@ -1502,10 -1521,22 -1442,10 +1519,22 @@@@ void xen_poll_irq(int irq
        xen_poll_irq_timeout(irq, 0 /* no timeout */);
   }
   
+ +/* Check whether the IRQ line is shared with other guests. */
+ +int xen_test_irq_shared(int irq)
+ +{
+ +     struct irq_info *info = info_for_irq(irq);
+ +     struct physdev_irq_status_query irq_status = { .irq = info->u.pirq.pirq };
+ +
+ +     if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
+ +             return 0;
+ +     return !(irq_status.flags & XENIRQSTAT_shared);
+ +}
+ +EXPORT_SYMBOL_GPL(xen_test_irq_shared);
+ +
   void xen_irq_resume(void)
   {
  -     unsigned int cpu, irq, evtchn;
  -     struct irq_desc *desc;
  +     unsigned int cpu, evtchn;
  +     struct irq_info *info;
   
        init_evtchn_cpu_bindings();
   
Simple merge