ia64/linux-2.6.18-xen.hg

changeset 552:c3f9cc7789af

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@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 15 10:03:29 2008 +0100 (2008-05-15)
parents a741afb71700
children c6e36a53cf05
files drivers/pci/msi-xen.c
line diff
     1.1 --- a/drivers/pci/msi-xen.c	Thu May 15 09:42:27 2008 +0100
     1.2 +++ b/drivers/pci/msi-xen.c	Thu May 15 10:03:29 2008 +0100
     1.3 @@ -33,7 +33,6 @@ int msi_register(struct msi_ops *ops)
     1.4  }
     1.5  
     1.6  static LIST_HEAD(msi_dev_head);
     1.7 -static int msi_dev_head_inited = 0;
     1.8  DEFINE_SPINLOCK(msi_dev_lock);
     1.9  
    1.10  struct msi_dev_list {
    1.11 @@ -97,6 +96,23 @@ static int attach_pirq_entry(int pirq, i
    1.12  	return 0;
    1.13  }
    1.14  
    1.15 +static void detach_pirq_entry(int entry_nr,
    1.16 + 							struct msi_dev_list *msi_dev_entry)
    1.17 +{
    1.18 +	unsigned long flags;
    1.19 +	struct msi_pirq_entry *pirq_entry;
    1.20 +
    1.21 +	list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
    1.22 +		if (pirq_entry->entry_nr == entry_nr) {
    1.23 +			spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
    1.24 +			list_del(&pirq_entry->list);
    1.25 +			spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
    1.26 +			kfree(pirq_entry);
    1.27 +			return;
    1.28 +		}
    1.29 +	}
    1.30 +}
    1.31 +
    1.32  /*
    1.33   * pciback will provide device's owner
    1.34   */
    1.35 @@ -379,40 +395,42 @@ static int msi_capability_init(struct pc
    1.36  static int msix_capability_init(struct pci_dev *dev,
    1.37  				struct msix_entry *entries, int nvec)
    1.38  {
    1.39 -	int pirq, i, pos;
    1.40 +	int pirq, i, j, mapped, pos;
    1.41  	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
    1.42 -	struct msi_pirq_entry *pirq_entry, *tmp;
    1.43 -	unsigned long flags;
    1.44 +	struct msi_pirq_entry *pirq_entry;
    1.45  
    1.46  	if (!msi_dev_entry)
    1.47  		return -ENOMEM;
    1.48  
    1.49 -	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
    1.50 -	if (!list_empty(&msi_dev_entry->pirq_list_head))
    1.51 -	{
    1.52 -		printk(KERN_WARNING "msix pirqs for dev %02x:%02x:%01x are not freed \
    1.53 -		       before acquire again.\n", dev->bus->number, PCI_SLOT(dev->devfn),
    1.54 -			   PCI_FUNC(dev->devfn));
    1.55 -		list_for_each_entry_safe(pirq_entry, tmp,
    1.56 -		                         &msi_dev_entry->pirq_list_head, list) {
    1.57 -			msi_unmap_pirq(dev, pirq_entry->pirq);
    1.58 -			list_del(&pirq_entry->list);
    1.59 -			kfree(pirq_entry);
    1.60 -		}
    1.61 -	}
    1.62 -	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
    1.63 -
    1.64  	/* MSI-X Table Initialization */
    1.65  	for (i = 0; i < nvec; i++) {
    1.66 +		mapped = 0;
    1.67 +		list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
    1.68 +			if (pirq_entry->entry_nr == entries[i].entry) {
    1.69 +				printk(KERN_WARNING "msix entry %d for dev %02x:%02x:%01x are \
    1.70 +				       not freed before acquire again.\n", entries[i].entry,
    1.71 +					   dev->bus->number, PCI_SLOT(dev->devfn),
    1.72 +					   PCI_FUNC(dev->devfn));
    1.73 +				(entries + i)->vector = pirq_entry->pirq;
    1.74 +				mapped = 1;
    1.75 +				break;
    1.76 +			}
    1.77 +		}
    1.78 +		if (mapped)
    1.79 +			continue;
    1.80  		pirq = msi_map_vector(dev, entries[i].entry, 0);
    1.81  		if (pirq < 0)
    1.82  			break;
    1.83  		attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
    1.84  		(entries + i)->vector = pirq;
    1.85  	}
    1.86 +
    1.87  	if (i != nvec) {
    1.88 -		msi_unmap_pirq(dev, dev->irq);
    1.89 -		(entries + i)->vector = 0;
    1.90 +		for (j = --i; j >= 0; j--) {
    1.91 +			msi_unmap_pirq(dev, entries[j].vector);
    1.92 +			detach_pirq_entry(entries[j].entry, msi_dev_entry);
    1.93 +			entries[j].vector = 0;
    1.94 +		}
    1.95  		return -EBUSY;
    1.96  	}
    1.97