From: Keir Fraser Date: Wed, 2 Jul 2008 08:44:09 +0000 (+0100) Subject: x86: Fix MSI cleanup. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14188^2~134 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=94ab7ad96bfeb557b8e9f66e400ffc4a5ee1a345;p=xen.git x86: Fix MSI cleanup. Fixes bugzilla bug #1279. From: Haitao Shan Signed-off-by: Keir Fraser --- diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c index 9c321aac17..e206ad5deb 100644 --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -435,14 +435,6 @@ static void msi_free_vector(int vector) xfree(entry); } -void msi_free_vectors(struct pci_dev* dev) -{ - struct msi_desc *entry, *tmp; - - list_for_each_entry_safe( entry, tmp, &dev->msi_list, list ) - msi_free_vector(entry->vector); -} - static struct msi_desc *find_msi_entry(struct pci_dev *dev, int vector, int cap_id) { @@ -790,16 +782,40 @@ void pci_disable_msi(int vector) __pci_disable_msix(vector); } +extern struct hw_interrupt_type pci_msi_type; +static void msi_free_vectors(struct pci_dev* dev) +{ + struct msi_desc *entry, *tmp; + irq_desc_t *desc; + unsigned long flags; + + list_for_each_entry_safe( entry, tmp, &dev->msi_list, list ) + { + desc = &irq_desc[entry->vector]; + + spin_lock_irqsave(&desc->lock, flags); + if ( desc->handler == &pci_msi_type ) + { + /* MSI is not shared, so should be released already */ + BUG_ON(desc->status & IRQ_GUEST); + desc->handler = &no_irq_type; + } + spin_unlock_irqrestore(&desc->lock, flags); + + msi_free_vector(entry->vector); + } +} + void pci_cleanup_msi(u8 bus, u8 devfn) { struct pci_dev *dev = get_msi_pdev(bus, devfn); if ( !dev ) return; - msi_free_vectors(dev); /* Disable MSI and/or MSI-X */ msi_set_enable(dev, 0); msix_set_enable(dev, 0); + msi_free_vectors(dev); } diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c index 432b34ae23..7e38237907 100644 --- a/xen/drivers/passthrough/io.c +++ b/xen/drivers/passthrough/io.c @@ -75,13 +75,18 @@ int pt_irq_create_bind_vtd( { int pirq = pt_irq_bind->machine_irq; + if ( !(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_VALID ) ) + { + hvm_irq_dpci->mirq[pirq].flags |= HVM_IRQ_DPCI_VALID | + HVM_IRQ_DPCI_MSI ; + pirq_guest_bind(d->vcpu[0], pirq, 0); + } + hvm_irq_dpci->mirq[pirq].flags |= HVM_IRQ_DPCI_VALID |HVM_IRQ_DPCI_MSI ; hvm_irq_dpci->mirq[pirq].gmsi.gvec = pt_irq_bind->u.msi.gvec; hvm_irq_dpci->mirq[pirq].gmsi.gflags = pt_irq_bind->u.msi.gflags; - hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] = pirq; - pirq_guest_bind(d->vcpu[0], pirq, BIND_PIRQ__WILL_SHARE); } else {