diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 56ab749..0150bc9 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -225,7 +225,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); if (msg.data != XEN_PIRQ_MSI_DATA || - xen_irq_from_pirq(pirq) < 0) { + xen_device_pirq_alloced(dev)) { pirq = xen_allocate_pirq_msi(dev, msidesc); if (pirq < 0) { irq = -ENODEV; @@ -234,6 +234,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) xen_msi_compose_msg(dev, pirq, &msg); __write_msi_msg(msidesc, &msg); dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); + xen_device_allocated(dev); } else { dev_dbg(&dev->dev, "xen: msi already bound to pirq=%d\n", pirq); @@ -500,6 +501,7 @@ int __init pci_xen_initial_domain(void) struct xen_device_domain_owner { domid_t domain; + bool used; struct pci_dev *dev; struct list_head list; }; @@ -570,4 +572,32 @@ int xen_unregister_device_domain_owner(struct pci_dev *dev) return 0; } EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner); + +int xen_device_allocated(struct pci_dev *dev) +{ + struct xen_device_domain_owner *owner; + + int rc = xen_register_device_domain_owner(dev, DOMID_SELF); + if (rc) + return rc; + + spin_lock(&dev_domain_list_spinlock); + owner = find_device(dev); + if (owner) + owner->used = true; + spin_unlock(&dev_domain_list_spinlock); + return 0; +} +bool xen_device_pirq_alloced(struct pci_dev *dev) +{ + struct xen_device_domain_owner *owner; + bool rc = false; + + spin_lock(&dev_domain_list_spinlock); + owner = find_device(dev); + if (owner && owner->used) + rc = true; + spin_unlock(&dev_domain_list_spinlock); + return rc; +} #endif