vt-d: Fix MSI-x interrupt remapping
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 15 Oct 2008 10:58:15 +0000 (11:58 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 15 Oct 2008 10:58:15 +0000 (11:58 +0100)
MSI-x may have multiple vectors, however in current interrupt
remapping code, one device only has one entry in interrupt remapping
table.

This patch adds 'remap_index' in msi_desc structure to track its index
in interrupt remapping table.

Signed-off-by: Haitao Shan <haitao.shan@intel.com>
Signed-off-by: Weidong Han <weidong.han@intel.com>
xen/arch/x86/msi.c
xen/drivers/passthrough/vtd/intremap.c
xen/include/asm-x86/msi.h

index 5a87e300370b5bb0014af1ef61a0ab37dab50233..75d45d2eefffe6f84d04e6af09c2bad7753e1344 100644 (file)
@@ -364,6 +364,7 @@ static struct msi_desc* alloc_msi_entry(void)
 
     INIT_LIST_HEAD(&entry->list);
     entry->dev = NULL;
+    entry->remap_index = -1;
 
     return entry;
 }
index 2d81277edefdb33d4be47657094b5e9d8827361d..e2ed43db17e048ea069d61128f46d74ccd9800cc 100644 (file)
@@ -328,7 +328,8 @@ static int remap_entry_to_msi_msg(
 }
 
 static int msi_msg_to_remap_entry(
-    struct iommu *iommu, struct pci_dev *pdev, struct msi_msg *msg)
+    struct iommu *iommu, struct pci_dev *pdev,
+    struct msi_desc *msi_desc, struct msi_msg *msg)
 {
     struct iremap_entry *iremap_entry = NULL, *iremap_entries;
     struct iremap_entry new_ire;
@@ -336,32 +337,18 @@ static int msi_msg_to_remap_entry(
     unsigned int index;
     unsigned long flags;
     struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
-    int i = 0;
 
     remap_rte = (struct msi_msg_remap_entry *) msg;
     spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);
 
-    iremap_entries =
-        (struct iremap_entry *)map_vtd_domain_page(ir_ctrl->iremap_maddr);
-
-    /* If the entry for a PCI device has been there, use the old entry,
-     * Or, assign a new entry for it.
-     */
-    for ( i = 0; i <= ir_ctrl->iremap_index; i++ )
-    {
-        iremap_entry = &iremap_entries[i];
-        if ( iremap_entry->hi.sid ==
-             ((pdev->bus << 8) | pdev->devfn) )
-           break;
-    }
-
-    if ( i > ir_ctrl->iremap_index )
+    if ( msi_desc->remap_index < 0 )
     {
-       ir_ctrl->iremap_index++;
+        ir_ctrl->iremap_index++;
         index = ir_ctrl->iremap_index;
+        msi_desc->remap_index = index;
     }
     else
-        index = i;
+        index = msi_desc->remap_index;
 
     if ( index > IREMAP_ENTRY_NR - 1 )
     {
@@ -369,11 +356,13 @@ static int msi_msg_to_remap_entry(
                 "%s: intremap index (%d) is larger than"
                 " the maximum index (%ld)!\n",
                 __func__, index, IREMAP_ENTRY_NR - 1);
-        unmap_vtd_domain_page(iremap_entries);
+        msi_desc->remap_index = -1;
         spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
         return -EFAULT;
     }
 
+    iremap_entries =
+        (struct iremap_entry *)map_vtd_domain_page(ir_ctrl->iremap_maddr);
     iremap_entry = &iremap_entries[index];
     memcpy(&new_ire, iremap_entry, sizeof(struct iremap_entry));
 
@@ -450,7 +439,7 @@ void msi_msg_write_remap_rte(
     if ( !iommu || !ir_ctrl || ir_ctrl->iremap_maddr == 0 )
         return;
 
-    msi_msg_to_remap_entry(iommu, pdev, msg);
+    msi_msg_to_remap_entry(iommu, pdev, msi_desc, msg);
 }
 #elif defined(__ia64__)
 void msi_msg_read_remap_rte(
index a72f348e53cd29b9db79388254c7a8c0725cc4b5..c72f9d69c5aa6243f74226fc690e214edb5c1e32 100644 (file)
@@ -90,10 +90,11 @@ struct msi_desc {
 
        void __iomem *mask_base;
        struct pci_dev *dev;
-    int vector;
+       int vector;
+
+       struct msi_msg msg;             /* Last set MSI message */
 
-       /* Last set MSI message */
-       struct msi_msg msg;
+       int remap_index;                /* index in interrupt remapping table */
 };
 
 /*