Skip to content

Commit

Permalink
NVMe: Always use MSI/MSI-x interrupts
Browse files Browse the repository at this point in the history
BugLink: http://bugs.launchpad.net/bugs/1602724

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>
(back ported from commit a522905)
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>

 Conflicts:
	drivers/nvme/host/pci.c

Acked-by: Brad Figg <brad.figg@canonical.com>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
  • Loading branch information
Keith Busch authored and smb49 committed Aug 9, 2016
1 parent de60690 commit 90c9712
Showing 1 changed file with 17 additions and 11 deletions.
28 changes: 17 additions & 11 deletions drivers/nvme/host/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1513,9 +1513,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
* access to the admin queue, as that might be only way to fix them up.
*/
if (result > 0) {
dev_err(dev->dev, "Could not set queue count (%d)\n", result);
nr_io_queues = 0;
result = 0;
dev_err(dev->ctrl.device,
"Could not set queue count (%d)\n", result);
return 0;
}

if (dev->cmb && NVME_CMB_SQS(dev->cmbsz)) {
Expand Down Expand Up @@ -1549,7 +1549,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
* If we enable msix early due to not intx, disable it again before
* setting up the full range we need.
*/
if (!pdev->irq)
if (pdev->msi_enabled)
pci_disable_msi(pdev);
else if (pdev->msix_enabled)
pci_disable_msix(pdev);

for (i = 0; i < nr_io_queues; i++)
Expand Down Expand Up @@ -1729,7 +1731,6 @@ static int nvme_dev_map(struct nvme_dev *dev)
if (pci_enable_device_mem(pdev))
return result;

dev->entry[0].vector = pdev->irq;
pci_set_master(pdev);
bars = pci_select_bars(pdev, IORESOURCE_MEM);
if (!bars)
Expand All @@ -1752,13 +1753,18 @@ static int nvme_dev_map(struct nvme_dev *dev)
}

/*
* Some devices don't advertse INTx interrupts, pre-enable a single
* MSIX vec for setup. We'll adjust this later.
* Some devices and/or platforms don't advertise or work with INTx
* interrupts. Pre-enable a single MSIX or MSI vec for setup. We'll
* adjust this later.
*/
if (!pdev->irq) {
result = pci_enable_msix(pdev, dev->entry, 1);
if (result < 0)
goto unmap;
if (pci_enable_msix(pdev, dev->entry, 1)) {
pci_enable_msi(pdev);
dev->entry[0].vector = pdev->irq;
}

if (!dev->entry[0].vector) {
result = -ENODEV;
goto unmap;
}

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

0 comments on commit 90c9712

Please sign in to comment.