x86: Fix MSI cleanup.
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 2 Jul 2008 08:44:09 +0000 (09:44 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 2 Jul 2008 08:44:09 +0000 (09:44 +0100)
Fixes bugzilla bug #1279.

From: Haitao Shan <haitao.shan@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/msi.c
xen/drivers/passthrough/io.c

index 9c321aac17bf856c83aa63a02f97dde7e996928a..e206ad5deb619f0fa0081e9e7febee583a3bbc88 100644 (file)
@@ -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);
 }
 
index 432b34ae23ecef568b77ea8ebd7f56960062f59f..7e3823790776128c40bfb467f131328f4669a526 100644 (file)
@@ -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
     {