mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-13 04:39:36 +02:00
nvme-pci: Add quirk for broken MSIs
commit d5887dc6b6
upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
377f3a9a3d
commit
a2da0e5c51
|
@ -161,6 +161,11 @@ enum nvme_quirks {
|
||||||
* Disables simple suspend/resume path.
|
* Disables simple suspend/resume path.
|
||||||
*/
|
*/
|
||||||
NVME_QUIRK_FORCE_NO_SIMPLE_SUSPEND = (1 << 20),
|
NVME_QUIRK_FORCE_NO_SIMPLE_SUSPEND = (1 << 20),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MSI (but not MSI-X) interrupts are broken and never fire.
|
||||||
|
*/
|
||||||
|
NVME_QUIRK_BROKEN_MSI = (1 << 21),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2216,6 +2216,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
|
||||||
.priv = dev,
|
.priv = dev,
|
||||||
};
|
};
|
||||||
unsigned int irq_queues, poll_queues;
|
unsigned int irq_queues, poll_queues;
|
||||||
|
unsigned int flags = PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Poll queues don't need interrupts, but we need at least one I/O queue
|
* Poll queues don't need interrupts, but we need at least one I/O queue
|
||||||
|
@ -2239,8 +2240,10 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
|
||||||
irq_queues = 1;
|
irq_queues = 1;
|
||||||
if (!(dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR))
|
if (!(dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR))
|
||||||
irq_queues += (nr_io_queues - poll_queues);
|
irq_queues += (nr_io_queues - poll_queues);
|
||||||
return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues,
|
if (dev->ctrl.quirks & NVME_QUIRK_BROKEN_MSI)
|
||||||
PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
|
flags &= ~PCI_IRQ_MSI;
|
||||||
|
return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues, flags,
|
||||||
|
&affd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int nvme_max_io_queues(struct nvme_dev *dev)
|
static unsigned int nvme_max_io_queues(struct nvme_dev *dev)
|
||||||
|
@ -2469,6 +2472,7 @@ static int nvme_pci_enable(struct nvme_dev *dev)
|
||||||
{
|
{
|
||||||
int result = -ENOMEM;
|
int result = -ENOMEM;
|
||||||
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
||||||
|
unsigned int flags = PCI_IRQ_ALL_TYPES;
|
||||||
|
|
||||||
if (pci_enable_device_mem(pdev))
|
if (pci_enable_device_mem(pdev))
|
||||||
return result;
|
return result;
|
||||||
|
@ -2485,7 +2489,9 @@ static int nvme_pci_enable(struct nvme_dev *dev)
|
||||||
* interrupts. Pre-enable a single MSIX or MSI vec for setup. We'll
|
* interrupts. Pre-enable a single MSIX or MSI vec for setup. We'll
|
||||||
* adjust this later.
|
* adjust this later.
|
||||||
*/
|
*/
|
||||||
result = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
|
if (dev->ctrl.quirks & NVME_QUIRK_BROKEN_MSI)
|
||||||
|
flags &= ~PCI_IRQ_MSI;
|
||||||
|
result = pci_alloc_irq_vectors(pdev, 1, 1, flags);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
goto disable;
|
goto disable;
|
||||||
|
|
||||||
|
@ -3382,6 +3388,8 @@ static const struct pci_device_id nvme_id_table[] = {
|
||||||
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY |
|
.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY |
|
||||||
NVME_QUIRK_DISABLE_WRITE_ZEROES|
|
NVME_QUIRK_DISABLE_WRITE_ZEROES|
|
||||||
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
|
NVME_QUIRK_IGNORE_DEV_SUBNQN, },
|
||||||
|
{ PCI_DEVICE(0x15b7, 0x5008), /* Sandisk SN530 */
|
||||||
|
.driver_data = NVME_QUIRK_BROKEN_MSI },
|
||||||
{ PCI_DEVICE(0x1987, 0x5012), /* Phison E12 */
|
{ PCI_DEVICE(0x1987, 0x5012), /* Phison E12 */
|
||||||
.driver_data = NVME_QUIRK_BOGUS_NID, },
|
.driver_data = NVME_QUIRK_BOGUS_NID, },
|
||||||
{ PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */
|
{ PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user