Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NVMe: Add MSI support

Some devices only have support for MSI, not MSI-X. While MSI is more
limited, it still provides better performance than line-based interrupts.

Signed-off-by: Ramachandra Gajula <rama@fastorsystems.com>
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>

authored by

Ramachandra Rao Gajula and committed by
Matthew Wilcox
fa08a396 cf9f123b

+32 -8
+32 -8
drivers/block/nvme-core.c
··· 1637 1637 1638 1638 static int nvme_setup_io_queues(struct nvme_dev *dev) 1639 1639 { 1640 - int result, cpu, i, nr_io_queues, db_bar_size, q_depth; 1640 + struct pci_dev *pdev = dev->pci_dev; 1641 + int result, cpu, i, nr_io_queues, db_bar_size, q_depth, q_count; 1641 1642 1642 1643 nr_io_queues = num_online_cpus(); 1643 1644 result = set_queue_count(dev, nr_io_queues); ··· 1647 1646 if (result < nr_io_queues) 1648 1647 nr_io_queues = result; 1649 1648 1649 + q_count = nr_io_queues; 1650 1650 /* Deregister the admin queue's interrupt */ 1651 1651 free_irq(dev->entry[0].vector, dev->queues[0]); 1652 1652 1653 1653 db_bar_size = 4096 + ((nr_io_queues + 1) << (dev->db_stride + 3)); 1654 1654 if (db_bar_size > 8192) { 1655 1655 iounmap(dev->bar); 1656 - dev->bar = ioremap(pci_resource_start(dev->pci_dev, 0), 1657 - db_bar_size); 1656 + dev->bar = ioremap(pci_resource_start(pdev, 0), db_bar_size); 1658 1657 dev->dbs = ((void __iomem *)dev->bar) + 4096; 1659 1658 dev->queues[0]->q_db = dev->dbs; 1660 1659 } ··· 1662 1661 for (i = 0; i < nr_io_queues; i++) 1663 1662 dev->entry[i].entry = i; 1664 1663 for (;;) { 1665 - result = pci_enable_msix(dev->pci_dev, dev->entry, 1666 - nr_io_queues); 1664 + result = pci_enable_msix(pdev, dev->entry, nr_io_queues); 1667 1665 if (result == 0) { 1668 1666 break; 1669 1667 } else if (result > 0) { 1670 1668 nr_io_queues = result; 1671 1669 continue; 1672 1670 } else { 1673 - nr_io_queues = 1; 1671 + nr_io_queues = 0; 1674 1672 break; 1673 + } 1674 + } 1675 + 1676 + if (nr_io_queues == 0) { 1677 + nr_io_queues = q_count; 1678 + for (;;) { 1679 + result = pci_enable_msi_block(pdev, nr_io_queues); 1680 + if (result == 0) { 1681 + for (i = 0; i < nr_io_queues; i++) 1682 + dev->entry[i].vector = i + pdev->irq; 1683 + break; 1684 + } else if (result > 0) { 1685 + nr_io_queues = result; 1686 + continue; 1687 + } else { 1688 + nr_io_queues = 1; 1689 + break; 1690 + } 1675 1691 } 1676 1692 } 1677 1693 ··· 1872 1854 { 1873 1855 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref); 1874 1856 nvme_dev_remove(dev); 1875 - pci_disable_msix(dev->pci_dev); 1857 + if (dev->pci_dev->msi_enabled) 1858 + pci_disable_msi(dev->pci_dev); 1859 + else if (dev->pci_dev->msix_enabled) 1860 + pci_disable_msix(dev->pci_dev); 1876 1861 iounmap(dev->bar); 1877 1862 nvme_release_instance(dev); 1878 1863 nvme_release_prp_pools(dev); ··· 2008 1987 unmap: 2009 1988 iounmap(dev->bar); 2010 1989 disable_msix: 2011 - pci_disable_msix(pdev); 1990 + if (dev->pci_dev->msi_enabled) 1991 + pci_disable_msi(dev->pci_dev); 1992 + else if (dev->pci_dev->msix_enabled) 1993 + pci_disable_msix(dev->pci_dev); 2012 1994 nvme_release_instance(dev); 2013 1995 nvme_release_prp_pools(dev); 2014 1996 disable: