x86/MSI: fix 2nd S3 resume with interrupt remapping enabled
authorJan Beulich <jbeulich@suse.com>
Fri, 7 Sep 2012 15:57:10 +0000 (17:57 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 7 Sep 2012 15:57:10 +0000 (17:57 +0200)
The first resume from S3 was corrupting internal data structures (in
that pci_restore_msi_state() updated the globally stored MSI message
from traditional to interrupt remapped format, which would then be
translated a second time during the second resume, breaking interrupt
delivery).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
xen/arch/x86/msi.c

index 782b84b0fddd077533175f4f41abf573ad3b2c40..f982c45df8888456b568f7a8b920a30672b958d2 100644 (file)
@@ -210,7 +210,10 @@ static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
     entry->msg = *msg;
 
     if ( iommu_enabled )
+    {
+        ASSERT(msg != &entry->msg);
         iommu_update_ire_from_msi(entry, msg);
+    }
 
     switch ( entry->msi_attrib.type )
     {
@@ -996,6 +999,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
     int ret;
     struct msi_desc *entry, *tmp;
     struct irq_desc *desc;
+    struct msi_msg msg;
 
     ASSERT(spin_is_locked(&pcidevs_lock));
 
@@ -1030,7 +1034,8 @@ int pci_restore_msi_state(struct pci_dev *pdev)
         else if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
             msix_set_enable(pdev, 0);
 
-        write_msi_msg(entry, &entry->msg);
+        msg = entry->msg;
+        write_msi_msg(entry, &msg);
 
         msi_set_mask_bit(desc, entry->msi_attrib.masked);