[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [linux-2.6.18-xen] Fix buggy mask_base in saving/restoring MSI-X table during S3
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1228218887 0 # Node ID 63a878f8851b3b15c21e83ddda4aa36fe3bd9a80 # Parent cdc6729dc7025594b902ef01795bfafd4c14ea3c 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@xxxxxxxxx> --- drivers/pci/msi-xen.c | 52 ++++++++++++++++++++++++-------------------------- 1 files changed, 25 insertions(+), 27 deletions(-) diff -r cdc6729dc702 -r 63a878f8851b drivers/pci/msi-xen.c --- a/drivers/pci/msi-xen.c Fri Nov 28 13:41:38 2008 +0000 +++ b/drivers/pci/msi-xen.c Tue Dec 02 11:54:47 2008 +0000 @@ -42,6 +42,8 @@ struct msi_dev_list { struct list_head list; spinlock_t pirq_list_lock; struct list_head pirq_list_head; + /* Used for saving/restoring MSI-X tables */ + void __iomem *mask_base; }; struct msi_pirq_entry { @@ -50,7 +52,6 @@ struct msi_pirq_entry { int entry_nr; #ifdef CONFIG_PM /* PM save area for MSIX address/data */ - void __iomem *mask_base; u32 address_hi_save; u32 address_lo_save; u32 data_save; @@ -90,7 +91,7 @@ static struct msi_dev_list *get_msi_dev_ return ret; } -static int attach_pirq_entry(int pirq, int entry_nr, u64 table_base, +static int attach_pirq_entry(int pirq, int entry_nr, struct msi_dev_list *msi_dev_entry) { struct msi_pirq_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC); @@ -100,9 +101,6 @@ static int attach_pirq_entry(int pirq, i return -ENOMEM; entry->pirq = pirq; entry->entry_nr = entry_nr; -#ifdef COMFIG_PM - entry->mask_base = table_base; -#endif spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags); list_add_tail(&entry->list, &msi_dev_entry->pirq_list_head); spin_unlock_irqrestore(&msi_dev_entry->pirq_list_lock, flags); @@ -381,17 +379,24 @@ int pci_save_msix_state(struct pci_dev * unsigned long flags; struct msi_dev_list *msi_dev_entry; struct msi_pirq_entry *pirq_entry; + void __iomem *base; pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); if (pos <= 0 || dev->no_msi) return 0; - - printk(KERN_CRIT "Saving MSIX cap\n"); /* save the capability */ pci_read_config_word(dev, msi_control_reg(pos), &control); if (!(control & PCI_MSIX_FLAGS_ENABLE)) return 0; + + msi_dev_entry = get_msi_dev_pirq_list(dev); + /* If we failed to map the MSI-X table at pci_enable_msix, + * We could not support saving them here. + */ + if (!(base = msi_dev_entry->mask_base)) + return -ENOMEM; + save_state = kzalloc(sizeof(struct pci_cap_saved_state) + sizeof(u16), GFP_KERNEL); if (!save_state) { @@ -400,19 +405,12 @@ int pci_save_msix_state(struct pci_dev * } *((u16 *)&save_state->data[0]) = control; - msi_dev_entry = get_msi_dev_pirq_list(dev); - spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags); list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) { int j; - void __iomem *base; /* save the table */ - base = pirq_entry->mask_base; j = pirq_entry->entry_nr; - printk(KERN_CRIT "Save msix table entry %d pirq %x base %p\n", - j, pirq_entry->pirq, base); - pirq_entry->address_lo_save = readl(base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); @@ -443,7 +441,6 @@ void pci_restore_msix_state(struct pci_d save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); if (!save_state) return; - printk(KERN_CRIT "Restoring MSIX cap\n"); save = *((u16 *)&save_state->data[0]); pci_remove_saved_cap(save_state); @@ -454,15 +451,12 @@ void pci_restore_msix_state(struct pci_d return; msi_dev_entry = get_msi_dev_pirq_list(dev); + base = msi_dev_entry->mask_base; spin_lock_irqsave(&msi_dev_entry->pirq_list_lock, flags); list_for_each_entry(pirq_entry, &msi_dev_entry->pirq_list_head, list) { /* route the table */ - base = pirq_entry->mask_base; j = pirq_entry->entry_nr; - - printk(KERN_CRIT "Restore msix table entry %d pirq %x base %p\n", - j, pirq_entry->pirq, base); writel(pirq_entry->address_lo_save, base + j * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); @@ -523,7 +517,8 @@ static int msix_capability_init(struct p struct msix_entry *entries, int nvec) { u64 table_base; - int pirq, i, j, mapped, pos; + u16 control; + int pirq, i, j, mapped, pos, nr_entries; struct msi_dev_list *msi_dev_entry = get_msi_dev_pirq_list(dev); struct msi_pirq_entry *pirq_entry; @@ -534,6 +529,12 @@ static int msix_capability_init(struct p table_base = find_table_base(dev, pos); if (!table_base) return -ENODEV; + + pci_read_config_word(dev, msi_control_reg(pos), &control); + nr_entries = multi_msix_capable(control); + if (!msi_dev_entry->mask_base) + msi_dev_entry->mask_base = + ioremap_nocache(table_base, nr_entries * PCI_MSIX_ENTRY_SIZE); /* MSI-X Table Initialization */ for (i = 0; i < nvec; i++) { @@ -554,7 +555,7 @@ static int msix_capability_init(struct p pirq = msi_map_vector(dev, entries[i].entry, table_base); if (pirq < 0) break; - attach_pirq_entry(pirq, entries[i].entry, table_base, msi_dev_entry); + attach_pirq_entry(pirq, entries[i].entry, msi_dev_entry); (entries + i)->vector = pirq; } @@ -739,7 +740,7 @@ int pci_enable_msix(struct pci_dev* dev, if (mapped) continue; irq = evtchn_map_pirq(-1, entries[i].vector); - attach_pirq_entry(irq, entries[i].entry, 0, msi_dev_entry); + attach_pirq_entry(irq, entries[i].entry, msi_dev_entry); entries[i].vector = irq; } return 0; @@ -857,18 +858,15 @@ void msi_remove_pci_irq_vectors(struct p 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); + iounmap(msi_dev_entry->mask_base); + msi_dev_entry->mask_base = NULL; dev->irq = dev->irq_old; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |