The patch titled genirq: msi: simplify msi enable and disable has been added to the -mm tree. Its filename is genirq-msi-simplify-msi-enable-and-disable.patch See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find out what to do about this ------------------------------------------------------ Subject: genirq: msi: simplify msi enable and disable From: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> The problem. Because the disable routines leave the msi interrupts in all sorts of half enabled states the enable routines become impossible to implement correctly, and almost impossible to understand. Simplifing this allows me to simply kill the buggy reroute_msix_table, and generally makes the code more maintainable. Signed-off-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx> Cc: Rajesh Shah <rajesh.shah@xxxxxxxxx> Cc: Andi Kleen <ak@xxxxxx> Cc: "Protasevich, Natalie" <Natalie.Protasevich@xxxxxxxxxx> Cc: "Luck, Tony" <tony.luck@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- drivers/pci/msi.c | 122 +++++--------------------------------------- 1 file changed, 16 insertions(+), 106 deletions(-) diff -puN drivers/pci/msi.c~genirq-msi-simplify-msi-enable-and-disable drivers/pci/msi.c --- a/drivers/pci/msi.c~genirq-msi-simplify-msi-enable-and-disable +++ a/drivers/pci/msi.c @@ -915,7 +915,6 @@ int pci_enable_msi(struct pci_dev* dev) { struct pci_bus *bus; int pos, temp, status = -EINVAL; - u16 control; if (!pci_msi_enable || !dev) return status; @@ -937,27 +936,8 @@ int pci_enable_msi(struct pci_dev* dev) if (!pos) return -EINVAL; - if (!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { - /* Lookup Sucess */ - unsigned long flags; + BUG_ON(!msi_lookup_vector(dev, PCI_CAP_ID_MSI)); - pci_read_config_word(dev, msi_control_reg(pos), &control); - if (control & PCI_MSI_FLAGS_ENABLE) - return 0; /* Already in MSI mode */ - spin_lock_irqsave(&msi_lock, flags); - if (!vector_irq[dev->irq]) { - msi_desc[dev->irq]->msi_attrib.state = 0; - vector_irq[dev->irq] = -1; - nr_released_vectors--; - spin_unlock_irqrestore(&msi_lock, flags); - status = msi_register_init(dev, msi_desc[dev->irq]); - if (status == 0) - enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); - return status; - } - spin_unlock_irqrestore(&msi_lock, flags); - dev->irq = temp; - } /* Check whether driver already requested for MSI-X vectors */ pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { @@ -999,6 +979,8 @@ void pci_disable_msi(struct pci_dev* dev if (!(control & PCI_MSI_FLAGS_ENABLE)) return; + disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); + spin_lock_irqsave(&msi_lock, flags); entry = msi_desc[dev->irq]; if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { @@ -1012,14 +994,12 @@ void pci_disable_msi(struct pci_dev* dev pci_name(dev), dev->irq); BUG_ON(entry->msi_attrib.state > 0); } else { - vector_irq[dev->irq] = 0; /* free it */ - nr_released_vectors++; default_vector = entry->msi_attrib.default_vector; spin_unlock_irqrestore(&msi_lock, flags); + msi_free_vector(dev, dev->irq, 0); + /* Restore dev->irq to its default pin-assertion vector */ dev->irq = default_vector; - disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), - PCI_CAP_ID_MSI); } } @@ -1067,57 +1047,6 @@ static int msi_free_vector(struct pci_de return 0; } -static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec) -{ - int vector = head, tail = 0; - int i, j = 0, nr_entries = 0; - void __iomem *base; - unsigned long flags; - - spin_lock_irqsave(&msi_lock, flags); - while (head != tail) { - nr_entries++; - tail = msi_desc[vector]->link.tail; - if (entries[0].entry == msi_desc[vector]->msi_attrib.entry_nr) - j = vector; - vector = tail; - } - if (*nvec > nr_entries) { - spin_unlock_irqrestore(&msi_lock, flags); - *nvec = nr_entries; - return -EINVAL; - } - vector = ((j > 0) ? j : head); - for (i = 0; i < *nvec; i++) { - j = msi_desc[vector]->msi_attrib.entry_nr; - msi_desc[vector]->msi_attrib.state = 0; /* Mark it not active */ - vector_irq[vector] = -1; /* Mark it busy */ - nr_released_vectors--; - entries[i].vector = vector; - if (j != (entries + i)->entry) { - base = msi_desc[vector]->mask_base; - msi_desc[vector]->msi_attrib.entry_nr = - (entries + i)->entry; - writel( readl(base + j * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET), base + - (entries + i)->entry * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); - writel( readl(base + j * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET), base + - (entries + i)->entry * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); - writel( (readl(base + j * PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_DATA_OFFSET) & 0xff00) | vector, - base + (entries+i)->entry*PCI_MSIX_ENTRY_SIZE + - PCI_MSIX_ENTRY_DATA_OFFSET); - } - vector = msi_desc[vector]->link.tail; - } - spin_unlock_irqrestore(&msi_lock, flags); - - return 0; -} - /** * pci_enable_msix - configure device's MSI-X capability structure * @dev: pointer to the pci_dev data structure of MSI-X device function @@ -1160,9 +1089,6 @@ int pci_enable_msix(struct pci_dev* dev, return -EINVAL; pci_read_config_word(dev, msi_control_reg(pos), &control); - if (control & PCI_MSIX_FLAGS_ENABLE) - return -EINVAL; /* Already in MSI-X mode */ - nr_entries = multi_msix_capable(control); if (nvec > nr_entries) return -EINVAL; @@ -1177,19 +1103,8 @@ int pci_enable_msix(struct pci_dev* dev, } } temp = dev->irq; - if (!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { - /* Lookup Sucess */ - nr_entries = nvec; - /* Reroute MSI-X table */ - if (reroute_msix_table(dev->irq, entries, &nr_entries)) { - /* #requested > #previous-assigned */ - dev->irq = temp; - return nr_entries; - } - dev->irq = temp; - enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); - return 0; - } + BUG_ON(!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)); + /* Check whether driver already requested for MSI vector */ if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { @@ -1248,37 +1163,32 @@ void pci_disable_msix(struct pci_dev* de if (!(control & PCI_MSIX_FLAGS_ENABLE)) return; + disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); + temp = dev->irq; if (!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { int state, vector, head, tail = 0, warning = 0; unsigned long flags; vector = head = dev->irq; - spin_lock_irqsave(&msi_lock, flags); + dev->irq = temp; /* Restore pin IRQ */ while (head != tail) { + spin_lock_irqsave(&msi_lock, flags); state = msi_desc[vector]->msi_attrib.state; + tail = msi_desc[vector]->link.tail; + spin_unlock_irqrestore(&msi_lock, flags); if (state) warning = 1; - else { - vector_irq[vector] = 0; /* free it */ - nr_released_vectors++; - } - tail = msi_desc[vector]->link.tail; + else if (vector != head) /* Release MSI-X vector */ + msi_free_vector(dev, vector, 0); vector = tail; } - spin_unlock_irqrestore(&msi_lock, flags); + msi_free_vector(dev, vector, 0); if (warning) { - dev->irq = temp; printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " "free_irq() on all MSI-X vectors\n", pci_name(dev)); BUG_ON(warning > 0); - } else { - dev->irq = temp; - disable_msi_mode(dev, - pci_find_capability(dev, PCI_CAP_ID_MSIX), - PCI_CAP_ID_MSIX); - } } } _ Patches currently in -mm which might be from ebiederm@xxxxxxxxxxxx are add-a-sysfs-file-to-determine-if-a-kexec-kernel-is-loaded.patch avoid-tasklist_lock-at-getrusage-for-multithreaded-case-too.patch ptrace-document-the-locking-rules.patch proc-fix-the-inode-number-on-proc-pid-fd.patch proc-remove-useless-bkl-in-proc_pid_readlink.patch proc-remove-unnecessary-and-misleading-assignments.patch proc-simplify-the-ownership-rules-for-proc.patch proc-replace-proc_inodetype-with-proc_inodefd.patch proc-remove-bogus-proc_task_permission.patch proc-kill-proc_mem_inode_operations.patch proc-properly-filter-out-files-that-are-not-visible.patch proc-fix-the-link-count-for-proc-pid-task.patch proc-move-proc_maps_operations-into-task_mmuc.patch proc-rewrite-the-proc-dentry-flush-on-exit.patch proc-close-the-race-of-a-process-dying-durning.patch proc-refactor-reading-directories-of-tasks.patch proc-remove-tasklist_lock-from-proc_pid_readdir.patch proc-remove-tasklist_lock-from-proc_pid_lookup-and.patch proc-remove-tasklist_lock-from-proc_pid_readdir-simply-fix-first_tgid.patch proc-make-proc_numbuf-the-buffer-size-for-holding-a.patch proc-dont-lock-task_structs-indefinitely.patch proc-dont-lock-task_structs-indefinitely-task_mmu-small-fixes.patch proc-use-struct-pid-not-struct-task_ref.patch proc-optimize-proc_check_dentry_visible.patch proc-use-sane-permission-checks-on-the-proc-pid-fd.patch proc-cleanup-proc_fd_access_allowed.patch proc-remove-tasklist_lock-from-proc_task_readdir.patch simplify-fix-first_tid.patch cleanup-next_tid.patch de_thread-fix-lockless-do_each_thread.patch coredump-optimize-mm-users-traversal.patch coredump-speedup-sigkill-sending.patch coredump-kill-ptrace-related-stuff.patch coredump-kill-ptrace-related-stuff-fix.patch coredump-dont-take-tasklist_lock.patch proc-sysctl-add-_proc_do_string-helper.patch namespaces-add-nsproxy.patch namespaces-add-nsproxy-dont-include-compileh.patch namespaces-incorporate-fs-namespace-into-nsproxy.patch namespaces-utsname-introduce-temporary-helpers.patch namespaces-utsname-switch-to-using-uts-namespaces.patch namespaces-utsname-switch-to-using-uts-namespaces-alpha-fix.patch namespaces-utsname-switch-to-using-uts-namespaces-cleanup.patch namespaces-utsname-use-init_utsname-when-appropriate.patch namespaces-utsname-use-init_utsname-when-appropriate-cifs-update.patch namespaces-utsname-implement-utsname-namespaces.patch namespaces-utsname-implement-utsname-namespaces-export.patch namespaces-utsname-implement-utsname-namespaces-dont-include-compileh.patch namespaces-utsname-sysctl-hack.patch namespaces-utsname-sysctl-hack-cleanup.patch namespaces-utsname-sysctl-hack-cleanup-2.patch namespaces-utsname-sysctl-hack-cleanup-2-fix.patch namespaces-utsname-remove-system_utsname.patch namespaces-utsname-implement-clone_newuts-flag.patch uts-copy-nsproxy-only-when-needed.patch ipc-namespace-core-fix.patch ipc-namespace-core-unshare-fix.patch ipc-namespace-utils-compilation-fix.patch genirq-irq-convert-the-move_irq-flag-from-a-32bit-word-to-a-single-bit.patch genirq-irq-add-moved_masked_irq.patch genirq-x86_64-irq-reenable-migrating-irqs-to-other-cpus.patch genirq-msi-simplify-msi-enable-and-disable.patch genirq-msi-simplify-msi-enable-and-disable-fix.patch genirq-msi-make-the-msi-boolean-tests-return-either-0-or-1.patch genirq-msi-implement-helper-functions-read_msi_msg-and-write_msi_msg.patch genirq-msi-refactor-the-msi_ops.patch genirq-msi-simplify-the-msi-irq-limit-policy.patch genirq-irq-add-a-dynamic-irq-creation-api.patch genirq-ia64-irq-dynamic-irq-support.patch genirq-i386-irq-dynamic-irq-support.patch genirq-i386-irq-dynamic-irq-support-fix.patch genirq-x86_64-irq-dynamic-irq-support.patch genirq-msi-make-the-msi-code-irq-based-and-not-vector-based.patch genirq-x86_64-irq-move-msi-message-composition-into-io_apicc.patch genirq-i386-irq-move-msi-message-composition-into-io_apicc.patch genirq-msi-only-build-msi-apicc-on-ia64.patch genirq-x86_64-irq-remove-the-msi-assumption-that-irq-==-vector.patch genirq-i386-irq-remove-the-msi-assumption-that-irq-==-vector.patch genirq-i386-irq-remove-the-msi-assumption-that-irq-==-vector-fix.patch genirq-irq-remove-msi-hacks.patch genirq-irq-generalize-the-check-for-hardirq_bits.patch genirq-x86_64-irq-make-the-external-irq-handlers-report-their-vector-not-the-irq-number.patch genirq-x86_64-irq-make-vector_irq-per-cpu.patch genirq-x86_64-irq-kill-gsi_irq_sharing.patch genirq-x86_64-irq-kill-irq-compression.patch genirq-irq-document-what-an-irq-is.patch pidhash-temporary-debug-checks.patch genirq-i386-irq-remove-the-msi-assumption-that-irq-==-vector-fix-tidies.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html