]> xenbits.xensource.com Git - xenclient/kernel.git/commitdiff
MSI-X: enhancement
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 13 Aug 2008 12:46:14 +0000 (13:46 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 13 Aug 2008 12:46:14 +0000 (13:46 +0100)
Signed-off-by: Yu Zhao <yu.zhao@intel.com>
drivers/pci/msi-xen.c
include/xen/interface/physdev.h

index e43e96bc95be1683da8f8896db9afcfa2b71fdf2..25ebcda33ef935eb7122281072bd868341484b16 100644 (file)
@@ -166,11 +166,27 @@ static int msi_unmap_pirq(struct pci_dev *dev, int pirq)
        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), &reg);
+       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 pci_dev *dev, int pirq,
        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 pci_dev *dev, int pirq,
        return map_irq.pirq;
 }
 
-static int msi_map_vector(struct pci_dev *dev, int entry_nr, int 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, msi);
+       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_dev *dev)
        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_dev *dev)
 {
        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_dev *dev)
                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 pci_dev *dev)
        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,6 +415,7 @@ static int msi_capability_init(struct pci_dev *dev)
 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;
@@ -401,6 +423,11 @@ static int msix_capability_init(struct pci_dev *dev,
        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++) {
                mapped = 0;
@@ -417,7 +444,7 @@ static int msix_capability_init(struct pci_dev *dev,
                }
                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 pci_dev *dev,
                return -EBUSY;
        }
 
-       pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
        enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
        dev->msix_enabled = 1;
 
index c2ddbf5b46babb149fbcebd527460a18fe392752..99ffaeba27a9db5cd56ea325d8dee6570ed2aff6 100644 (file)
@@ -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);