Skip to content

Commit c45b1fa

Browse files
Ming Leiaxboe
authored andcommitted
nvme-pci: fix nvme_setup_irqs()
When -ENOSPC is returned from pci_alloc_irq_vectors_affinity(), we still try to allocate multiple irq vectors again, so irq queues covers the admin queue actually. But we don't consider that, then number of the allocated irq vector may be same with sum of io_queues[HCTX_TYPE_DEFAULT] and io_queues[HCTX_TYPE_READ], this way is obviously wrong, and finally breaks nvme_pci_map_queues(), and warning from pci_irq_get_affinity() is triggered. IRQ queues should cover admin queues, this patch makes this point explicitely in nvme_calc_io_queues(). We got severl boot failure internal report on aarch64, so please consider to fix it in v4.20. Fixes: 6451fe7 ("nvme: fix irq vs io_queue calculations") Signed-off-by: Ming Lei <[email protected]> Reviewed-by: Keith Busch <[email protected]> Tested-by: fin4478 <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent fb86585 commit c45b1fa

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

drivers/nvme/host/pci.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,36 +2041,40 @@ static int nvme_setup_host_mem(struct nvme_dev *dev)
20412041
return ret;
20422042
}
20432043

2044+
/* irq_queues covers admin queue */
20442045
static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues)
20452046
{
20462047
unsigned int this_w_queues = write_queues;
20472048

2049+
WARN_ON(!irq_queues);
2050+
20482051
/*
2049-
* Setup read/write queue split
2052+
* Setup read/write queue split, assign admin queue one independent
2053+
* irq vector if irq_queues is > 1.
20502054
*/
2051-
if (irq_queues == 1) {
2055+
if (irq_queues <= 2) {
20522056
dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
20532057
dev->io_queues[HCTX_TYPE_READ] = 0;
20542058
return;
20552059
}
20562060

20572061
/*
20582062
* If 'write_queues' is set, ensure it leaves room for at least
2059-
* one read queue
2063+
* one read queue and one admin queue
20602064
*/
20612065
if (this_w_queues >= irq_queues)
2062-
this_w_queues = irq_queues - 1;
2066+
this_w_queues = irq_queues - 2;
20632067

20642068
/*
20652069
* If 'write_queues' is set to zero, reads and writes will share
20662070
* a queue set.
20672071
*/
20682072
if (!this_w_queues) {
2069-
dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues;
2073+
dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues - 1;
20702074
dev->io_queues[HCTX_TYPE_READ] = 0;
20712075
} else {
20722076
dev->io_queues[HCTX_TYPE_DEFAULT] = this_w_queues;
2073-
dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues;
2077+
dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues - 1;
20742078
}
20752079
}
20762080

@@ -2095,7 +2099,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
20952099
this_p_queues = nr_io_queues - 1;
20962100
irq_queues = 1;
20972101
} else {
2098-
irq_queues = nr_io_queues - this_p_queues;
2102+
irq_queues = nr_io_queues - this_p_queues + 1;
20992103
}
21002104
dev->io_queues[HCTX_TYPE_POLL] = this_p_queues;
21012105

@@ -2115,8 +2119,9 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
21152119
* If we got a failure and we're down to asking for just
21162120
* 1 + 1 queues, just ask for a single vector. We'll share
21172121
* that between the single IO queue and the admin queue.
2122+
* Otherwise, we assign one independent vector to admin queue.
21182123
*/
2119-
if (result >= 0 && irq_queues > 1)
2124+
if (irq_queues > 1)
21202125
irq_queues = irq_sets[0] + irq_sets[1] + 1;
21212126

21222127
result = pci_alloc_irq_vectors_affinity(pdev, irq_queues,

0 commit comments

Comments
 (0)