[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] MSI-X: enhancement



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1218631539 -3600
# Node ID 0638a5c2cc9f2053f6025edf3ddc5ff12300924d
# Parent  644a9d219973b9b21fd0590eec38370f4fb8caae
MSI-X: enhancement

Signed-off-by: Yu Zhao <yu.zhao@xxxxxxxxx>
---
 tools/ioemu/hw/pass-through.h |    1 
 tools/ioemu/hw/pt-msi.c       |   24 +++++-------
 tools/libxc/xc_physdev.c      |   10 ++---
 tools/libxc/xenctrl.h         |    2 -
 xen/arch/x86/msi.c            |   82 +++++++++++++++---------------------------
 xen/arch/x86/physdev.c        |   15 +++++--
 xen/drivers/passthrough/io.c  |    3 +
 xen/include/asm-x86/msi.h     |   10 ++++-
 xen/include/public/physdev.h  |   11 +++--
 9 files changed, 76 insertions(+), 82 deletions(-)

diff -r 644a9d219973 -r 0638a5c2cc9f tools/ioemu/hw/pass-through.h
--- a/tools/ioemu/hw/pass-through.h     Wed Aug 13 13:42:30 2008 +0100
+++ b/tools/ioemu/hw/pass-through.h     Wed Aug 13 13:45:39 2008 +0100
@@ -120,6 +120,7 @@ struct pt_msix_info {
     int enabled;
     int total_entries;
     int bar_index;
+    uint64_t table_base;
     uint32_t table_off;
     uint64_t mmio_base_addr;
     int mmio_index;
diff -r 644a9d219973 -r 0638a5c2cc9f tools/ioemu/hw/pt-msi.c
--- a/tools/ioemu/hw/pt-msi.c   Wed Aug 13 13:42:30 2008 +0100
+++ b/tools/ioemu/hw/pt-msi.c   Wed Aug 13 13:45:39 2008 +0100
@@ -38,8 +38,8 @@ int pt_msi_setup(struct pt_dev *dev)
     }
 
     if ( xc_physdev_map_pirq_msi(xc_handle, domid, AUTO_ASSIGN, &pirq,
-                                                       dev->pci_dev->dev << 3 
| dev->pci_dev->func,
-                                                       dev->pci_dev->bus, 0, 
1) )
+                                 dev->pci_dev->dev << 3 | dev->pci_dev->func,
+                                 dev->pci_dev->bus, 0, 0) )
     {
         PT_LOG("error map msi\n");
         return -1;
@@ -121,7 +121,8 @@ static int pt_msix_update_one(struct pt_
     {
         ret = xc_physdev_map_pirq_msi(xc_handle, domid, AUTO_ASSIGN, &pirq,
                                 dev->pci_dev->dev << 3 | dev->pci_dev->func,
-                                dev->pci_dev->bus, entry_nr, 0);
+                                dev->pci_dev->bus, entry_nr,
+                                dev->msix->table_base);
         if ( ret )
         {
             PT_LOG("error map msix entry %x\n", entry_nr);
@@ -183,7 +184,7 @@ static void pci_msix_writel(void *opaque
     entry = &msix->msix_entry[entry_nr];
     offset = ((addr - msix->mmio_base_addr) % 16) / 4;
 
-    if ( offset != 3 && msix->enabled && entry->io_mem[3] & 0x1 )
+    if ( offset != 3 && msix->enabled && !(entry->io_mem[3] & 0x1) )
     {
         PT_LOG("can not update msix entry %d since MSI-X is already \
                 function now.\n", entry_nr);
@@ -196,7 +197,7 @@ static void pci_msix_writel(void *opaque
 
     if ( offset == 3 )
     {
-        if ( !(val & 0x1) )
+        if ( msix->enabled && !(val & 0x1) )
             pt_msix_update_one(dev, entry_nr);
         mask_physical_msix_entry(dev, entry_nr, entry->io_mem[3] & 0x1);
     }
@@ -280,7 +281,6 @@ int pt_msix_init(struct pt_dev *dev, int
     uint8_t id;
     uint16_t control;
     int i, total_entries, table_off, bar_index;
-    uint64_t bar_base;
     struct pci_dev *pd = dev->pci_dev;
 
     id = pci_read_byte(pd, pos + PCI_CAP_LIST_ID);
@@ -314,18 +314,14 @@ int pt_msix_init(struct pt_dev *dev, int
     table_off = pci_read_long(pd, pos + PCI_MSIX_TABLE);
     bar_index = dev->msix->bar_index = table_off & PCI_MSIX_BIR;
     table_off &= table_off & ~PCI_MSIX_BIR;
-    bar_base = pci_read_long(pd, 0x10 + 4 * bar_index);
-    if ( (bar_base & 0x6) == 0x4 )
-    {
-        bar_base &= ~0xf;
-        bar_base += (uint64_t)pci_read_long(pd, 0x10 + 4 * (bar_index + 1)) << 
32;
-    }
-    PT_LOG("get MSI-X table bar base %lx\n", bar_base);
+    dev->msix->table_base = dev->pci_dev->base_addr[bar_index];
+    PT_LOG("get MSI-X table bar base %llx\n",
+           (unsigned long long)dev->msix->table_base);
 
     dev->msix->fd = open("/dev/mem", O_RDWR);
     dev->msix->phys_iomem_base = mmap(0, total_entries * 16,
                           PROT_WRITE | PROT_READ, MAP_SHARED | MAP_LOCKED,
-                          dev->msix->fd, bar_base + table_off);
+                          dev->msix->fd, dev->msix->table_base + table_off);
     PT_LOG("mapping physical MSI-X table to %lx\n",
            (unsigned long)dev->msix->phys_iomem_base);
     return 0;
diff -r 644a9d219973 -r 0638a5c2cc9f tools/libxc/xc_physdev.c
--- a/tools/libxc/xc_physdev.c  Wed Aug 13 13:42:30 2008 +0100
+++ b/tools/libxc/xc_physdev.c  Wed Aug 13 13:45:39 2008 +0100
@@ -51,7 +51,7 @@ int xc_physdev_map_pirq_msi(int xc_handl
                             int devfn,
                             int bus,
                             int entry_nr,
-                            int msi_type)
+                            uint64_t table_base)
 {
     int rc;
     struct physdev_map_pirq map;
@@ -63,10 +63,10 @@ int xc_physdev_map_pirq_msi(int xc_handl
     map.type = MAP_PIRQ_TYPE_MSI;
     map.index = index;
     map.pirq = *pirq;
-    map.msi_info.devfn = devfn;
-    map.msi_info.bus = bus;
-    map.msi_info.entry_nr = entry_nr;
-    map.msi_info.msi = msi_type;
+    map.bus = bus;
+    map.devfn = devfn;
+    map.entry_nr = entry_nr;
+    map.table_base = table_base;
 
     rc = do_physdev_op(xc_handle, PHYSDEVOP_map_pirq, &map);
 
diff -r 644a9d219973 -r 0638a5c2cc9f tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Wed Aug 13 13:42:30 2008 +0100
+++ b/tools/libxc/xenctrl.h     Wed Aug 13 13:45:39 2008 +0100
@@ -917,7 +917,7 @@ int xc_physdev_map_pirq_msi(int xc_handl
                             int devfn,
                             int bus,
                             int entry_nr,
-                            int msi_type);
+                            uint64_t table_base);
 
 int xc_physdev_unmap_pirq(int xc_handle,
                           int domid,
diff -r 644a9d219973 -r 0638a5c2cc9f xen/arch/x86/msi.c
--- a/xen/arch/x86/msi.c        Wed Aug 13 13:42:30 2008 +0100
+++ b/xen/arch/x86/msi.c        Wed Aug 13 13:45:39 2008 +0100
@@ -490,28 +490,6 @@ static int msi_capability_init(struct pc
     return 0;
 }
 
-static u64 pci_resource_start(struct pci_dev *dev, u8 bar_index)
-{
-    u64 bar_base;
-    u32 reg_val;
-    u8 bus = dev->bus;
-    u8 slot = PCI_SLOT(dev->devfn);
-    u8 func = PCI_FUNC(dev->devfn);
-
-    reg_val = pci_conf_read32(bus, slot, func,
-                              PCI_BASE_ADDRESS_0 + 4 * bar_index);
-    bar_base = reg_val & PCI_BASE_ADDRESS_MEM_MASK;
-    if ( ( reg_val & PCI_BASE_ADDRESS_MEM_TYPE_MASK ) ==
-         PCI_BASE_ADDRESS_MEM_TYPE_64 )
-    {
-        reg_val = pci_conf_read32(bus, slot, func,
-                                  PCI_BASE_ADDRESS_0 + 4 * (bar_index + 1));
-        bar_base |= ((u64)reg_val) << 32;
-    }
-
-    return bar_base;
-}
-
 /**
  * msix_capability_init - configure device's MSI-X capability
  * @dev: pointer to the pci_dev data structure of MSI-X device function
@@ -522,7 +500,7 @@ static u64 pci_resource_start(struct pci
  * single MSI-X irq. A return of zero indicates the successful setup of
  * requested MSI-X entries with allocated irqs or non-zero for otherwise.
  **/
-static int msix_capability_init(struct pci_dev *dev, int vector, int entry_nr)
+static int msix_capability_init(struct pci_dev *dev, struct msi_info *msi)
 {
     struct msi_desc *entry;
     int pos;
@@ -549,7 +527,7 @@ static int msix_capability_init(struct p
     table_offset = pci_conf_read32(bus, slot, func, 
msix_table_offset_reg(pos));
     bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
     table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
-    phys_addr = pci_resource_start(dev, bir) + table_offset;
+    phys_addr = msi->table_base + table_offset;
     idx = msix_fixmap_alloc();
     if ( idx < 0 )
     {
@@ -561,11 +539,11 @@ static int msix_capability_init(struct p
 
     entry->msi_attrib.type = PCI_CAP_ID_MSIX;
     entry->msi_attrib.is_64 = 1;
-    entry->msi_attrib.entry_nr = entry_nr;
+    entry->msi_attrib.entry_nr = msi->entry_nr;
     entry->msi_attrib.maskbit = 1;
     entry->msi_attrib.masked = 1;
     entry->msi_attrib.pos = pos;
-    entry->vector = vector;
+    entry->vector = msi->vector;
     entry->dev = dev;
     entry->mask_base = base;
 
@@ -589,24 +567,25 @@ static int msix_capability_init(struct p
  * indicates the successful setup of an entry zero with the new MSI
  * irq or non-zero for otherwise.
  **/
-static int __pci_enable_msi(u8 bus, u8 devfn, int vector)
+static int __pci_enable_msi(struct msi_info *msi)
 {
     int status;
     struct pci_dev *pdev;
 
-    pdev = pci_lock_pdev(bus, devfn);
+    pdev = pci_lock_pdev(msi->bus, msi->devfn);
     if ( !pdev )
        return -ENODEV;
 
-    if ( find_msi_entry(pdev, vector, PCI_CAP_ID_MSI) )
+    if ( find_msi_entry(pdev, msi->vector, PCI_CAP_ID_MSI) )
     {
        spin_unlock(&pdev->lock);
-        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSI on device 
\
-            %02x:%02x.%01x.\n", vector, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSI on "
+            "device %02x:%02x.%01x.\n", msi->vector, msi->bus,
+            PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
         return 0;
     }
 
-    status = msi_capability_init(pdev, vector);
+    status = msi_capability_init(pdev, msi->vector);
     spin_unlock(&pdev->lock);
     return status;
 }
@@ -659,37 +638,37 @@ static void __pci_disable_msi(int vector
  * of irqs available. Driver should use the returned value to re-send
  * its request.
  **/
-static int __pci_enable_msix(u8 bus, u8 devfn, int vector, int entry_nr)
+static int __pci_enable_msix(struct msi_info *msi)
 {
     int status, pos, nr_entries;
     struct pci_dev *pdev;
     u16 control;
-    u8 slot = PCI_SLOT(devfn);
-    u8 func = PCI_FUNC(devfn);
-
-    pdev = pci_lock_pdev(bus, devfn);
+    u8 slot = PCI_SLOT(msi->devfn);
+    u8 func = PCI_FUNC(msi->devfn);
+
+    pdev = pci_lock_pdev(msi->bus, msi->devfn);
     if ( !pdev )
        return -ENODEV;
 
-    pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
-    control = pci_conf_read16(bus, slot, func, msi_control_reg(pos));
+    pos = pci_find_cap_offset(msi->bus, slot, func, PCI_CAP_ID_MSIX);
+    control = pci_conf_read16(msi->bus, slot, func, msi_control_reg(pos));
     nr_entries = multi_msix_capable(control);
-    if (entry_nr > nr_entries)
+    if (msi->entry_nr > nr_entries)
     {
        spin_unlock(&pdev->lock);
         return -EINVAL;
     }
 
-    if ( find_msi_entry(pdev, vector, PCI_CAP_ID_MSIX) )
+    if ( find_msi_entry(pdev, msi->vector, PCI_CAP_ID_MSIX) )
     {
        spin_unlock(&pdev->lock);
-        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSIX on \
-                device %02x:%02x.%01x.\n", vector, bus,
-                PCI_SLOT(devfn), PCI_FUNC(devfn));
+        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSIX on "
+                "device %02x:%02x.%01x.\n", msi->vector, msi->bus,
+                PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
         return 0;
     }
 
-    status = msix_capability_init(pdev, vector, entry_nr);
+    status = msix_capability_init(pdev, msi);
     spin_unlock(&pdev->lock);
     return status;
 }
@@ -727,13 +706,12 @@ static void __pci_disable_msix(int vecto
     spin_unlock(&dev->lock);
 }
 
-int pci_enable_msi(u8 bus, u8 devfn, int vector, int entry_nr, int msi)
-{
-    ASSERT(spin_is_locked(&irq_desc[vector].lock));
-    if ( msi )
-        return __pci_enable_msi(bus, devfn, vector);
-    else
-        return __pci_enable_msix(bus, devfn, vector, entry_nr);
+int pci_enable_msi(struct msi_info *msi)
+{
+    ASSERT(spin_is_locked(&irq_desc[msi->vector].lock));
+
+    return  msi->table_base ? __pci_enable_msix(msi) :
+                              __pci_enable_msi(msi);
 }
 
 void pci_disable_msi(int vector)
diff -r 644a9d219973 -r 0638a5c2cc9f xen/arch/x86/physdev.c
--- a/xen/arch/x86/physdev.c    Wed Aug 13 13:42:30 2008 +0100
+++ b/xen/arch/x86/physdev.c    Wed Aug 13 13:45:39 2008 +0100
@@ -66,6 +66,7 @@ static int map_domain_pirq(struct domain
 {
     int ret = 0;
     int old_vector, old_pirq;
+    struct msi_info msi;
 
     if ( d == NULL )
         return -EINVAL;
@@ -115,10 +116,14 @@ static int map_domain_pirq(struct domain
                      vector);
         desc->handler = &pci_msi_type;
 
-        ret = pci_enable_msi(map->msi_info.bus,
-                                    map->msi_info.devfn, vector,
-                                                        map->msi_info.entry_nr,
-                                                        map->msi_info.msi);
+        msi.bus = map->bus;
+        msi.devfn = map->devfn;
+        msi.entry_nr = map->entry_nr;
+        msi.table_base = map->table_base;
+        msi.vector = vector;
+
+        ret = pci_enable_msi(&msi);
+
         spin_unlock_irqrestore(&desc->lock, flags);
         if ( ret )
             goto done;
@@ -139,7 +144,7 @@ static int unmap_domain_pirq(struct doma
     int ret = 0;
     int vector;
 
-    if ( d == NULL || pirq < 0 || pirq > NR_PIRQS )
+    if ( d == NULL || pirq < 0 || pirq >= NR_PIRQS )
         return -EINVAL;
 
     if ( !IS_PRIV(current->domain) )
diff -r 644a9d219973 -r 0638a5c2cc9f xen/drivers/passthrough/io.c
--- a/xen/drivers/passthrough/io.c      Wed Aug 13 13:42:30 2008 +0100
+++ b/xen/drivers/passthrough/io.c      Wed Aug 13 13:45:39 2008 +0100
@@ -74,6 +74,9 @@ int pt_irq_create_bind_vtd(
     if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
     {
         int pirq = pt_irq_bind->machine_irq;
+
+        if ( pirq < 0 || pirq >= NR_IRQS )
+            return -EINVAL;
 
         if ( !(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_VALID ) )
         {
diff -r 644a9d219973 -r 0638a5c2cc9f xen/include/asm-x86/msi.h
--- a/xen/include/asm-x86/msi.h Wed Aug 13 13:42:30 2008 +0100
+++ b/xen/include/asm-x86/msi.h Wed Aug 13 13:45:39 2008 +0100
@@ -53,6 +53,14 @@
 #else
 #define MAX_MSIX_PAGES              32
 #endif
+
+struct msi_info {
+    int bus;
+    int devfn;
+    int vector;
+    int entry_nr;
+    uint64_t table_base;
+};
 
 struct msi_msg {
        u32     address_lo;     /* low 32 bits of msi message address */
@@ -64,7 +72,7 @@ extern void mask_msi_irq(unsigned int ir
 extern void mask_msi_irq(unsigned int irq);
 extern void unmask_msi_irq(unsigned int irq);
 extern void set_msi_irq_affinity(unsigned int irq, cpumask_t mask);
-extern int pci_enable_msi(u8 bus, u8 devfn, int vector, int entry_nr, int msi);
+extern int pci_enable_msi(struct msi_info *msi);
 extern void pci_disable_msi(int vector);
 extern void pci_cleanup_msi(struct pci_dev *pdev);
 
diff -r 644a9d219973 -r 0638a5c2cc9f xen/include/public/physdev.h
--- a/xen/include/public/physdev.h      Wed Aug 13 13:42:30 2008 +0100
+++ b/xen/include/public/physdev.h      Wed Aug 13 13:45:39 2008 +0100
@@ -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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.