Skip to content

Commit a522905

Browse files
Keith Buschaxboe
authored andcommitted
NVMe: Always use MSI/MSI-x interrupts
Multiple users have reported device initialization failure due the driver not receiving legacy PCI interrupts. This is not unique to any particular controller, but has been observed on multiple platforms. There have been no issues reported or observed when with message signaled interrupts, so this patch attempts to use MSI-x during initialization, falling back to MSI. If that fails, legacy would become the default. The setup_io_queues error handling had to change as a result: the admin queue's msix_entry used to be initialized to the legacy IRQ. The case where nr_io_queues is 0 would fail request_irq when setting up the admin queue's interrupt since re-enabling MSI-x fails with 0 vectors, leaving the admin queue's msix_entry invalid. Instead, return success immediately. Reported-by: Tim Muhlemmer <muhlemmer@gmail.com> Reported-by: Jon Derrick <jonathan.derrick@intel.com> Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Jens Axboe <axboe@fb.com>
1 parent 9bf2b97 commit a522905

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

drivers/nvme/host/pci.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,8 +1478,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
14781478
if (result > 0) {
14791479
dev_err(dev->ctrl.device,
14801480
"Could not set queue count (%d)\n", result);
1481-
nr_io_queues = 0;
1482-
result = 0;
1481+
return 0;
14831482
}
14841483

14851484
if (dev->cmb && NVME_CMB_SQS(dev->cmbsz)) {
@@ -1513,7 +1512,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
15131512
* If we enable msix early due to not intx, disable it again before
15141513
* setting up the full range we need.
15151514
*/
1516-
if (!pdev->irq)
1515+
if (pdev->msi_enabled)
1516+
pci_disable_msi(pdev);
1517+
else if (pdev->msix_enabled)
15171518
pci_disable_msix(pdev);
15181519

15191520
for (i = 0; i < nr_io_queues; i++)
@@ -1696,7 +1697,6 @@ static int nvme_pci_enable(struct nvme_dev *dev)
16961697
if (pci_enable_device_mem(pdev))
16971698
return result;
16981699

1699-
dev->entry[0].vector = pdev->irq;
17001700
pci_set_master(pdev);
17011701

17021702
if (dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)) &&
@@ -1709,13 +1709,18 @@ static int nvme_pci_enable(struct nvme_dev *dev)
17091709
}
17101710

17111711
/*
1712-
* Some devices don't advertse INTx interrupts, pre-enable a single
1713-
* MSIX vec for setup. We'll adjust this later.
1712+
* Some devices and/or platforms don't advertise or work with INTx
1713+
* interrupts. Pre-enable a single MSIX or MSI vec for setup. We'll
1714+
* adjust this later.
17141715
*/
1715-
if (!pdev->irq) {
1716-
result = pci_enable_msix(pdev, dev->entry, 1);
1717-
if (result < 0)
1718-
goto disable;
1716+
if (pci_enable_msix(pdev, dev->entry, 1)) {
1717+
pci_enable_msi(pdev);
1718+
dev->entry[0].vector = pdev->irq;
1719+
}
1720+
1721+
if (!dev->entry[0].vector) {
1722+
result = -ENODEV;
1723+
goto disable;
17191724
}
17201725

17211726
cap = lo_hi_readq(dev->bar + NVME_REG_CAP);

0 commit comments

Comments
 (0)