aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-10-15 11:58:15 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-10-15 11:58:15 +0100
commitf0064d9c2b46a9032863ea05378672e4c5735292 (patch)
tree52cab1a0953a39fd605c2be3ce84c51762d930d6
parent41a0f8dc4488e0415bda939c42fe3497247f47e1 (diff)
downloadxen-f0064d9c2b46a9032863ea05378672e4c5735292.tar.gz
xen-f0064d9c2b46a9032863ea05378672e4c5735292.tar.bz2
xen-f0064d9c2b46a9032863ea05378672e4c5735292.zip
vt-d: Fix MSI-x interrupt remapping
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>
-rw-r--r--xen/arch/x86/msi.c1
-rw-r--r--xen/drivers/passthrough/vtd/intremap.c31
-rw-r--r--xen/include/asm-x86/msi.h7
3 files changed, 15 insertions, 24 deletions
diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index 5a87e30037..75d45d2eef 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -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;
}
diff --git a/xen/drivers/passthrough/vtd/intremap.c b/xen/drivers/passthrough/vtd/intremap.c
index 2d81277ede..e2ed43db17 100644
--- a/xen/drivers/passthrough/vtd/intremap.c
+++ b/xen/drivers/passthrough/vtd/intremap.c
@@ -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(
diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h
index a72f348e53..c72f9d69c5 100644
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -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 */
};
/*