ia64/linux-2.6.18-xen.hg

changeset 751:63a878f8851b

Fix buggy mask_base in saving/restoring MSI-X table during S3

Fix mask_base (actually MSI-X table base, copy name from native) to be
a virtual address rather than a physical address. And remove wrong
printk in pci_disable_msix.

Signed-off-by: Shan Haitao <haitao.shan@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Dec 02 11:54:47 2008 +0000 (2008-12-02)
parents cdc6729dc702
children ca213a56dba1
files drivers/pci/msi-xen.c
line diff
     1.1 --- a/drivers/pci/msi-xen.c	Fri Nov 28 13:41:38 2008 +0000
     1.2 +++ b/drivers/pci/msi-xen.c	Tue Dec 02 11:54:47 2008 +0000
     1.3 @@ -42,6 +42,8 @@ struct msi_dev_list {
     1.4  	struct list_head list;
     1.5  	spinlock_t pirq_list_lock;
     1.6  	struct list_head pirq_list_head;
     1.7 +	/* Used for saving/restoring MSI-X tables */
     1.8 +	void __iomem *mask_base;
     1.9  };
    1.10  
    1.11  struct msi_pirq_entry {
    1.12 @@ -50,7 +52,6 @@ struct msi_pirq_entry {
    1.13  	int entry_nr;
    1.14  #ifdef CONFIG_PM
    1.15  	/* PM save area for MSIX address/data */
    1.16 -	void __iomem *mask_base;
    1.17  	u32	address_hi_save;
    1.18  	u32	address_lo_save;
    1.19  	u32	data_save;
    1.20 @@ -90,7 +91,7 @@ static struct msi_dev_list *get_msi_dev_
    1.21  	return ret;
    1.22  }
    1.23  
    1.24 -static int attach_pirq_entry(int pirq, int entry_nr, u64 table_base,
    1.25 +static int attach_pirq_entry(int pirq, int entry_nr,
    1.26                               struct msi_dev_list *msi_dev_entry)
    1.27  {
    1.28  	struct msi_pirq_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
    1.29 @@ -100,9 +101,6 @@ static int attach_pirq_entry(int pirq, i
    1.30  		return -ENOMEM;
    1.31  	entry->pirq = pirq;
    1.32  	entry->entry_nr = entry_nr;
    1.33 -#ifdef COMFIG_PM
    1.34 -	entry->mask_base = table_base;
    1.35 -#endif
    1.36  	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
    1.37  	list_add_tail(&entry->list, &msi_dev_entry->pirq_list_head);
    1.38  	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
    1.39 @@ -381,17 +379,24 @@ int pci_save_msix_state(struct pci_dev *
    1.40  	unsigned long flags;
    1.41  	struct msi_dev_list *msi_dev_entry;
    1.42  	struct msi_pirq_entry *pirq_entry;
    1.43 +	void __iomem *base;
    1.44  
    1.45  	pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
    1.46  	if (pos <= 0 || dev->no_msi)
    1.47  		return 0;
    1.48  
    1.49 -	printk(KERN_CRIT "Saving MSIX cap\n");
    1.50 -
    1.51  	/* save the capability */
    1.52  	pci_read_config_word(dev, msi_control_reg(pos), &control);
    1.53  	if (!(control & PCI_MSIX_FLAGS_ENABLE))
    1.54  		return 0;
    1.55 +
    1.56 +	msi_dev_entry = get_msi_dev_pirq_list(dev);
    1.57 +	/* If we failed to map the MSI-X table at pci_enable_msix,
    1.58 +	 * We could not support saving them here.
    1.59 +	 */
    1.60 +	if (!(base = msi_dev_entry->mask_base))
    1.61 +		return -ENOMEM;
    1.62 +
    1.63  	save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16),
    1.64  		GFP_KERNEL);
    1.65  	if (!save_state) {
    1.66 @@ -400,19 +405,12 @@ int pci_save_msix_state(struct pci_dev *
    1.67  	}
    1.68  	*((u16 *)&save_state->data[0]) = control;
    1.69  
    1.70 -	msi_dev_entry = get_msi_dev_pirq_list(dev);
    1.71 -
    1.72  	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
    1.73  	list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
    1.74  		int j;
    1.75 -		void __iomem *base;
    1.76  
    1.77  		/* save the table */
    1.78 -		base = pirq_entry->mask_base;
    1.79  		j = pirq_entry->entry_nr;
    1.80 -		printk(KERN_CRIT "Save msix table entry %d pirq %x base %p\n",
    1.81 -		       j, pirq_entry->pirq, base);
    1.82 -
    1.83  		pirq_entry->address_lo_save =
    1.84  			readl(base + j * PCI_MSIX_ENTRY_SIZE +
    1.85  			      PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
    1.86 @@ -443,7 +441,6 @@ void pci_restore_msix_state(struct pci_d
    1.87  	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX);
    1.88  	if (!save_state)
    1.89  		return;
    1.90 -	printk(KERN_CRIT "Restoring MSIX cap\n");
    1.91  
    1.92  	save = *((u16 *)&save_state->data[0]);
    1.93  	pci_remove_saved_cap(save_state);
    1.94 @@ -454,15 +451,12 @@ void pci_restore_msix_state(struct pci_d
    1.95  		return;
    1.96  
    1.97  	msi_dev_entry = get_msi_dev_pirq_list(dev);
    1.98 +	base = msi_dev_entry->mask_base;
    1.99  
   1.100  	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
   1.101  	list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) {
   1.102  		/* route the table */
   1.103 -		base = pirq_entry->mask_base;
   1.104  		j = pirq_entry->entry_nr;
   1.105 -
   1.106 -		printk(KERN_CRIT "Restore msix table entry %d pirq %x base %p\n",
   1.107 -		       j, pirq_entry->pirq, base);
   1.108  		writel(pirq_entry->address_lo_save,
   1.109  			base + j * PCI_MSIX_ENTRY_SIZE +
   1.110  			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
   1.111 @@ -523,7 +517,8 @@ static int msix_capability_init(struct p
   1.112  				struct msix_entry *entries, int nvec)
   1.113  {
   1.114  	u64 table_base;
   1.115 -	int pirq, i, j, mapped, pos;
   1.116 +	u16 control;
   1.117 +	int pirq, i, j, mapped, pos, nr_entries;
   1.118  	struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev);
   1.119  	struct msi_pirq_entry *pirq_entry;
   1.120  
   1.121 @@ -535,6 +530,12 @@ static int msix_capability_init(struct p
   1.122  	if (!table_base)
   1.123  		return -ENODEV;
   1.124  
   1.125 +	pci_read_config_word(dev, msi_control_reg(pos), &control);
   1.126 +	nr_entries = multi_msix_capable(control);
   1.127 +	if (!msi_dev_entry->mask_base)
   1.128 +		msi_dev_entry->mask_base = 
   1.129 +			ioremap_nocache(table_base, nr_entries * PCI_MSIX_ENTRY_SIZE);
   1.130 +
   1.131  	/* MSI-X Table Initialization */
   1.132  	for (i = 0; i < nvec; i++) {
   1.133  		mapped = 0;
   1.134 @@ -554,7 +555,7 @@ static int msix_capability_init(struct p
   1.135  		pirq = msi_map_vector(dev, entries[i].entry, table_base);
   1.136  		if (pirq < 0)
   1.137  			break;
   1.138 -		attach_pirq_entry(pirq, entries[i].entry, table_base, msi_dev_entry);
   1.139 +		attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry);
   1.140  		(entries + i)->vector = pirq;
   1.141  	}
   1.142  
   1.143 @@ -739,7 +740,7 @@ int pci_enable_msix(struct pci_dev* dev,
   1.144  			if (mapped)
   1.145  				continue;
   1.146  			irq = evtchn_map_pirq(-1, entries[i].vector);
   1.147 -			attach_pirq_entry(irq, entries[i].entry, 0, msi_dev_entry);
   1.148 +			attach_pirq_entry(irq, entries[i].entry, msi_dev_entry);
   1.149  			entries[i].vector = irq;
   1.150  		}
   1.151          return 0;
   1.152 @@ -857,18 +858,15 @@ void msi_remove_pci_irq_vectors(struct p
   1.153  
   1.154  	spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags);
   1.155  	if (!list_empty(&msi_dev_entry->pirq_list_head))
   1.156 -	{
   1.157 -		printk(KERN_WARNING "msix pirqs for dev %02x:%02x:%01x are not freed \
   1.158 -		       before acquire again.\n", dev->bus->number, PCI_SLOT(dev->devfn),
   1.159 -			   PCI_FUNC(dev->devfn));
   1.160  		list_for_each_entry_safe(pirq_entry, tmp,
   1.161  		                         &msi_dev_entry->pirq_list_head, list) {
   1.162  			msi_unmap_pirq(dev, pirq_entry->pirq);
   1.163  			list_del(&pirq_entry->list);
   1.164  			kfree(pirq_entry);
   1.165  		}
   1.166 -	}
   1.167  	spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags);
   1.168 +	iounmap(msi_dev_entry->mask_base);
   1.169 +	msi_dev_entry->mask_base = NULL;
   1.170  	dev->irq = dev->irq_old;
   1.171  }
   1.172