[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |