# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1218631574 -3600
# Node ID 359b1e70d9eb7afbad732bfdc6a52169af7ff8c1
# Parent c110692c140f99169a88a4904e37438acd5b656d
MSI-X: enhancement
Signed-off-by: Yu Zhao <yu.zhao@xxxxxxxxx>
---
drivers/pci/msi-xen.c | 56 +++++++++++++++++++++++++++++-----------
include/xen/interface/physdev.h | 13 +++++----
2 files changed, 49 insertions(+), 20 deletions(-)
diff -r c110692c140f -r 359b1e70d9eb drivers/pci/msi-xen.c
--- a/drivers/pci/msi-xen.c Wed Aug 13 10:00:09 2008 +0100
+++ b/drivers/pci/msi-xen.c Wed Aug 13 13:46:14 2008 +0100
@@ -166,11 +166,27 @@ static int msi_unmap_pirq(struct pci_dev
return 0;
}
+static u64 find_table_base(struct pci_dev *dev, int pos)
+{
+ u8 bar;
+ u32 reg;
+ unsigned long flags;
+
+ pci_read_config_dword(dev, msix_table_offset_reg(pos), ®);
+ bar = reg & PCI_MSIX_FLAGS_BIRMASK;
+
+ flags = pci_resource_flags(dev, bar);
+ if (flags & (IORESOURCE_DISABLED | IORESOURCE_UNSET | IORESOURCE_BUSY))
+ return 0;
+
+ return pci_resource_start(dev, bar);
+}
+
/*
* Protected by msi_lock
*/
static int msi_map_pirq_to_vector(struct pci_dev *dev, int pirq,
- int entry_nr, int msi)
+ int entry_nr, u64 table_base)
{
struct physdev_map_pirq map_irq;
int rc;
@@ -182,10 +198,10 @@ static int msi_map_pirq_to_vector(struct
map_irq.type = MAP_PIRQ_TYPE_MSI;
map_irq.index = -1;
map_irq.pirq = pirq;
- map_irq.msi_info.bus = dev->bus->number;
- map_irq.msi_info.devfn = dev->devfn;
- map_irq.msi_info.entry_nr = entry_nr;
- map_irq.msi_info.msi = msi;
+ map_irq.bus = dev->bus->number;
+ map_irq.devfn = dev->devfn;
+ map_irq.entry_nr = entry_nr;
+ map_irq.table_base = table_base;
if ((rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq)))
printk(KERN_WARNING "map irq failed\n");
@@ -196,9 +212,9 @@ static int msi_map_pirq_to_vector(struct
return map_irq.pirq;
}
-static int msi_map_vector(struct pci_dev *dev, int entry_nr, int msi)
-{
- return msi_map_pirq_to_vector(dev, -1, entry_nr, msi);
+static int msi_map_vector(struct pci_dev *dev, int entry_nr, u64 table_base)
+{
+ return msi_map_pirq_to_vector(dev, -1, entry_nr, table_base);
}
static int msi_init(void)
@@ -290,7 +306,7 @@ void pci_restore_msi_state(struct pci_de
if (!dev->msi_enabled)
return;
- pirq = msi_map_pirq_to_vector(dev, dev->irq, 0, 1);
+ pirq = msi_map_pirq_to_vector(dev, dev->irq, 0, 0);
if (pirq < 0)
return;
enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
@@ -330,6 +346,7 @@ void pci_restore_msix_state(struct pci_d
{
int pos;
unsigned long flags;
+ u64 table_base;
struct msi_dev_list *msi_dev_entry;
struct msi_pirq_entry *pirq_entry, *tmp;
@@ -341,11 +358,15 @@ void pci_restore_msix_state(struct pci_d
return;
msi_dev_entry = get_msi_dev_pirq_list(dev);
+ table_base = find_table_base(dev, pos);
+ if (!table_base)
+ return;
spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
list_for_each_entry_safe(pirq_entry, tmp,
-
&msi_dev_entry->pirq_list_head, list)
- msi_map_pirq_to_vector(dev, pirq_entry->pirq,
pirq_entry->entry_nr, 0);
+ &msi_dev_entry->pirq_list_head, list)
+ msi_map_pirq_to_vector(dev, pirq_entry->pirq,
+ pirq_entry->entry_nr, table_base);
spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
@@ -366,10 +387,10 @@ static int msi_capability_init(struct pc
int pos, pirq;
u16 control;
- pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
pci_read_config_word(dev, msi_control_reg(pos), &control);
- pirq = msi_map_vector(dev, 0, 1);
+ pirq = msi_map_vector(dev, 0, 0);
if (pirq < 0)
return -EBUSY;
@@ -394,12 +415,18 @@ static int msix_capability_init(struct p
static int msix_capability_init(struct pci_dev *dev,
struct msix_entry *entries, int nvec)
{
+ u64 table_base;
int pirq, i, j, mapped, pos;
struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
struct msi_pirq_entry *pirq_entry;
if (!msi_dev_entry)
return -ENOMEM;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+ table_base = find_table_base(dev, pos);
+ if (!table_base)
+ return -ENODEV;
/* MSI-X Table Initialization */
for (i = 0; i < nvec; i++) {
@@ -417,7 +444,7 @@ static int msix_capability_init(struct p
}
if (mapped)
continue;
- pirq = msi_map_vector(dev, entries[i].entry, 0);
+ pirq = msi_map_vector(dev, entries[i].entry, table_base);
if (pirq < 0)
break;
attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
@@ -433,7 +460,6 @@ static int msix_capability_init(struct p
return -EBUSY;
}
- pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
dev->msix_enabled = 1;
diff -r c110692c140f -r 359b1e70d9eb include/xen/interface/physdev.h
--- a/include/xen/interface/physdev.h Wed Aug 13 10:00:09 2008 +0100
+++ b/include/xen/interface/physdev.h Wed Aug 13 13:46:14 2008 +0100
@@ -121,7 +121,7 @@ struct physdev_irq {
};
typedef struct physdev_irq physdev_irq_t;
DEFINE_XEN_GUEST_HANDLE(physdev_irq_t);
-
+
#define MAP_PIRQ_TYPE_MSI 0x0
#define MAP_PIRQ_TYPE_GSI 0x1
#define MAP_PIRQ_TYPE_UNKNOWN 0x2
@@ -136,10 +136,13 @@ struct physdev_map_pirq {
/* IN or OUT */
int pirq;
/* IN */
- struct {
- int bus, devfn, entry_nr;
- int msi; /* 0 - MSIX 1 - MSI */
- } msi_info;
+ int bus;
+ /* IN */
+ int devfn;
+ /* IN */
+ int entry_nr;
+ /* IN */
+ uint64_t table_base;
};
typedef struct physdev_map_pirq physdev_map_pirq_t;
DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|