Skip to content

Commit d5887dc

Browse files
Sean Andersonkeithbusch
authored andcommitted
nvme-pci: Add quirk for broken MSIs
Sandisk SN530 NVMe drives have broken MSIs. On systems without MSI-X support, all commands time out resulting in the following message: nvme nvme0: I/O tag 12 (100c) QID 0 timeout, completion polled These timeouts cause the boot to take an excessively-long time (over 20 minutes) while the initial command queue is flushed. Address this by adding a quirk for drives with buggy MSIs. The lspci output for this device (recorded on a system with MSI-X support) is: 02:00.0 Non-Volatile memory controller: Sandisk Corp Device 5008 (rev 01) (prog-if 02 [NVM Express]) Subsystem: Sandisk Corp Device 5008 Flags: bus master, fast devsel, latency 0, IRQ 16, NUMA node 0 Memory at f7e00000 (64-bit, non-prefetchable) [size=16K] Memory at f7e04000 (64-bit, non-prefetchable) [size=256] Capabilities: [80] Power Management version 3 Capabilities: [90] MSI: Enable- Count=1/32 Maskable- 64bit+ Capabilities: [b0] MSI-X: Enable+ Count=17 Masked- Capabilities: [c0] Express Endpoint, MSI 00 Capabilities: [100] Advanced Error Reporting Capabilities: [150] Device Serial Number 00-00-00-00-00-00-00-00 Capabilities: [1b8] Latency Tolerance Reporting Capabilities: [300] Secondary PCI Express Capabilities: [900] L1 PM Substates Kernel driver in use: nvme Kernel modules: nvme Cc: <stable@vger.kernel.org> Signed-off-by: Sean Anderson <sean.anderson@linux.dev> Reviewed-by: Christoph Hellwig <hch@lst.de>
1 parent ffd379c commit d5887dc

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

drivers/nvme/host/nvme.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ enum nvme_quirks {
162162
* Disables simple suspend/resume path.
163163
*/
164164
NVME_QUIRK_FORCE_NO_SIMPLE_SUSPEND = (1 << 20),
165+
166+
/*
167+
* MSI (but not MSI-X) interrupts are broken and never fire.
168+
*/
169+
NVME_QUIRK_BROKEN_MSI = (1 << 21),
165170
};
166171

167172
/*

drivers/nvme/host/pci.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,6 +2224,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
22242224
.priv = dev,
22252225
};
22262226
unsigned int irq_queues, poll_queues;
2227+
unsigned int flags = PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY;
22272228

22282229
/*
22292230
* Poll queues don't need interrupts, but we need at least one I/O queue
@@ -2247,8 +2248,10 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
22472248
irq_queues = 1;
22482249
if (!(dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR))
22492250
irq_queues += (nr_io_queues - poll_queues);
2250-
return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues,
2251-
PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
2251+
if (dev->ctrl.quirks & NVME_QUIRK_BROKEN_MSI)
2252+
flags &= ~PCI_IRQ_MSI;
2253+
return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues, flags,
2254+
&affd);
22522255
}
22532256

22542257
static unsigned int nvme_max_io_queues(struct nvme_dev *dev)
@@ -2477,6 +2480,7 @@ static int nvme_pci_enable(struct nvme_dev *dev)
24772480
{
24782481
int result = -ENOMEM;
24792482
struct pci_dev *pdev = to_pci_dev(dev->dev);
2483+
unsigned int flags = PCI_IRQ_ALL_TYPES;
24802484

24812485
if (pci_enable_device_mem(pdev))
24822486
return result;
@@ -2493,7 +2497,9 @@ static int nvme_pci_enable(struct nvme_dev *dev)
24932497
* interrupts. Pre-enable a single MSIX or MSI vec for setup. We'll
24942498
* adjust this later.
24952499
*/
2496-
result = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
2500+
if (dev->ctrl.quirks & NVME_QUIRK_BROKEN_MSI)
2501+
flags &= ~PCI_IRQ_MSI;
2502+
result = pci_alloc_irq_vectors(pdev, 1, 1, flags);
24972503
if (result < 0)
24982504
goto disable;
24992505

@@ -3390,6 +3396,8 @@ static const struct pci_device_id nvme_id_table[] = {
33903396
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY |
33913397
NVME_QUIRK_DISABLE_WRITE_ZEROES|
33923398
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
3399+
{ PCI_DEVICE(0x15b7, 0x5008), /* Sandisk SN530 */
3400+
.driver_data = NVME_QUIRK_BROKEN_MSI },
33933401
{ PCI_DEVICE(0x1987, 0x5012), /* Phison E12 */
33943402
.driver_data = NVME_QUIRK_BOGUS_NID, },
33953403
{ PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */

0 commit comments

Comments
 (0)