diff options
author | Jens Axboe <axboe@fb.com> | 2014-11-14 09:49:26 -0700 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-11-19 12:46:17 -0700 |
commit | e32efbfc35c1b06f1bfe3e6d737acdd14d27baed (patch) | |
tree | 9bf27a8af281e65bad379c641529399f300320ad /drivers/block | |
parent | b3521729769ec71567a2e32a38609f87e781e41b (diff) | |
download | blackbird-obmc-linux-e32efbfc35c1b06f1bfe3e6d737acdd14d27baed.tar.gz blackbird-obmc-linux-e32efbfc35c1b06f1bfe3e6d737acdd14d27baed.zip |
NVMe: make setup work for devices that don't do INTx
The setup/probe part currently relies on INTx being there and
working, that's not always the case. For devices that don't
advertise INTx, enable a single MSIx vector early on and disable
it again before we ask for our full range of queue vecs.
Acked-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/nvme-core.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 677d7b9ff454..9310fe51382e 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c @@ -1998,6 +1998,13 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) /* Deregister the admin queue's interrupt */ free_irq(dev->entry[0].vector, adminq); + /* + * If we enable msix early due to not intx, disable it again before + * setting up the full range we need. + */ + if (!pdev->irq) + pci_disable_msix(pdev); + for (i = 0; i < nr_io_queues; i++) dev->entry[i].entry = i; vecs = pci_enable_msix_range(pdev, dev->entry, 1, nr_io_queues); @@ -2150,10 +2157,22 @@ static int nvme_dev_map(struct nvme_dev *dev) dev->bar = ioremap(pci_resource_start(pdev, 0), 8192); if (!dev->bar) goto disable; + if (readl(&dev->bar->csts) == -1) { result = -ENODEV; goto unmap; } + + /* + * Some devices don't advertse INTx interrupts, pre-enable a single + * MSIX vec for setup. We'll adjust this later. + */ + if (!pdev->irq) { + result = pci_enable_msix(pdev, dev->entry, 1); + if (result < 0) + goto unmap; + } + cap = readq(&dev->bar->cap); dev->q_depth = min_t(int, NVME_CAP_MQES(cap) + 1, NVME_Q_DEPTH); dev->db_stride = 1 << NVME_CAP_STRIDE(cap); |