]> www.infradead.org Git - nvme.git/commitdiff
nvmet: pci-epf: Do not add an IRQ vector if not needed nvme-6.14 nvme-6.14-2025-03-13
authorDamien Le Moal <dlemoal@kernel.org>
Thu, 6 Mar 2025 08:55:49 +0000 (17:55 +0900)
committerKeith Busch <kbusch@kernel.org>
Mon, 10 Mar 2025 17:12:16 +0000 (10:12 -0700)
The function nvmet_pci_epf_create_cq() always unconditionally calls
nvmet_pci_epf_add_irq_vector() to add an IRQ vector for a completion
queue. But this is not correct if the host requested the creation of a
completion queue for polling, without an IRQ vector specified (i.e. the
flag NVME_CQ_IRQ_ENABLED is not set).

Fix this by calling nvmet_pci_epf_add_irq_vector() and setting the queue
flag NVMET_PCI_EPF_Q_IRQ_ENABLED for the cq only if NVME_CQ_IRQ_ENABLED
is set. While at it, also fix the error path to add the missing removal
of the added IRQ vector if nvmet_cq_create() fails.

Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver")
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
drivers/nvme/target/pci-epf.c

index d55ad334670c57095dfb656be3dbf578edb29709..b1e31483f1574a1f68443911f87a93b60abbfdbb 100644 (file)
@@ -1271,9 +1271,6 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
        if (!(flags & NVME_QUEUE_PHYS_CONTIG))
                return NVME_SC_INVALID_QUEUE | NVME_STATUS_DNR;
 
-       if (flags & NVME_CQ_IRQ_ENABLED)
-               set_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags);
-
        cq->pci_addr = pci_addr;
        cq->qid = cqid;
        cq->depth = qsize + 1;
@@ -1290,10 +1287,11 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
                cq->qes = ctrl->io_cqes;
        cq->pci_size = cq->qes * cq->depth;
 
-       cq->iv = nvmet_pci_epf_add_irq_vector(ctrl, vector);
-       if (!cq->iv) {
-               status = NVME_SC_INTERNAL | NVME_STATUS_DNR;
-               goto err;
+       if (flags & NVME_CQ_IRQ_ENABLED) {
+               cq->iv = nvmet_pci_epf_add_irq_vector(ctrl, vector);
+               if (!cq->iv)
+                       return NVME_SC_INTERNAL | NVME_STATUS_DNR;
+               set_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags);
        }
 
        status = nvmet_cq_create(tctrl, &cq->nvme_cq, cqid, cq->depth);
@@ -1308,7 +1306,8 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
        return NVME_SC_SUCCESS;
 
 err:
-       clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags);
+       if (test_and_clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags))
+               nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector);
        return status;
 }