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

[Xen-changelog] [linux-2.6.18-xen] Do not unmap all MSI-X pirqs when enabling MSI-X



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1210842209 -3600
# Node ID c3f9cc7789af995b7edfa8a8de4ae099a3750e9e
# Parent  a741afb717006a6751044d1d11cd5412f0bbce3c
Do not unmap all MSI-X pirqs when enabling MSI-X

Originally, all existing MSI-X pirqs of that device are unmapped
before mapping the required MSI-X entries. This is actually not
right. This function may be called several times, with each time
requiring enabling different parts of the device MSI-X entry. Former
pirqs should not be unmapped.

Thanks for Neil Turton's comments on this problem.

Signed-off-by: Shan Haitao <Haitao.shan@xxxxxxxxx>
---
 drivers/pci/msi-xen.c |   60 ++++++++++++++++++++++++++++++++------------------
 1 files changed, 39 insertions(+), 21 deletions(-)

diff -r a741afb71700 -r c3f9cc7789af drivers/pci/msi-xen.c
--- a/drivers/pci/msi-xen.c     Thu May 15 09:42:27 2008 +0100
+++ b/drivers/pci/msi-xen.c     Thu May 15 10:03:29 2008 +0100
@@ -33,7 +33,6 @@ int msi_register(struct msi_ops *ops)
 }
 
 static LIST_HEAD(msi_dev_head);
-static int msi_dev_head_inited = 0;
 DEFINE_SPINLOCK(msi_dev_lock);
 
 struct msi_dev_list {
@@ -95,6 +94,23 @@ static int attach_pirq_entry(int pirq, i
        list_add_tail(&entry->list, &msi_dev_entry->pirq_list_head);
        spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
        return 0;
+}
+
+static void detach_pirq_entry(int entry_nr,
+                                                       struct msi_dev_list 
*msi_dev_entry)
+{
+       unsigned long flags;
+       struct msi_pirq_entry *pirq_entry;
+
+       list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
+               if (pirq_entry->entry_nr == entry_nr) {
+                       spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, 
flags);
+                       list_del(&pirq_entry->list);
+                       spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, 
flags);
+                       kfree(pirq_entry);
+                       return;
+               }
+       }
 }
 
 /*
@@ -379,40 +395,42 @@ static int msix_capability_init(struct p
 static int msix_capability_init(struct pci_dev *dev,
                                struct msix_entry *entries, int nvec)
 {
-       int pirq, i, pos;
+       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, *tmp;
-       unsigned long flags;
+       struct msi_pirq_entry *pirq_entry;
 
        if (!msi_dev_entry)
                return -ENOMEM;
 
-       spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
-       if (!list_empty(&msi_dev_entry->pirq_list_head))
-       {
-               printk(KERN_WARNING "msix pirqs for dev %02x:%02x:%01x are not 
freed \
-                      before acquire again.\n", dev->bus->number, 
PCI_SLOT(dev->devfn),
-                          PCI_FUNC(dev->devfn));
-               list_for_each_entry_safe(pirq_entry, tmp,
-                                        &msi_dev_entry->pirq_list_head, list) {
-                       msi_unmap_pirq(dev, pirq_entry->pirq);
-                       list_del(&pirq_entry->list);
-                       kfree(pirq_entry);
-               }
-       }
-       spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
-
        /* MSI-X Table Initialization */
        for (i = 0; i < nvec; i++) {
+               mapped = 0;
+               list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, 
list) {
+                       if (pirq_entry->entry_nr == entries[i].entry) {
+                               printk(KERN_WARNING "msix entry %d for dev 
%02x:%02x:%01x are \
+                                      not freed before acquire again.\n", 
entries[i].entry,
+                                          dev->bus->number, 
PCI_SLOT(dev->devfn),
+                                          PCI_FUNC(dev->devfn));
+                               (entries + i)->vector = pirq_entry->pirq;
+                               mapped = 1;
+                               break;
+                       }
+               }
+               if (mapped)
+                       continue;
                pirq = msi_map_vector(dev, entries[i].entry, 0);
                if (pirq < 0)
                        break;
                attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
                (entries + i)->vector = pirq;
        }
+
        if (i != nvec) {
-               msi_unmap_pirq(dev, dev->irq);
-               (entries + i)->vector = 0;
+               for (j = --i; j >= 0; j--) {
+                       msi_unmap_pirq(dev, entries[j].vector);
+                       detach_pirq_entry(entries[j].entry, msi_dev_entry);
+                       entries[j].vector = 0;
+               }
                return -EBUSY;
        }
 

_______________________________________________
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®.