Skip to content

Commit

Permalink
Merge tag 'nvme-6.14-2025-03-13' of git://git.infradead.org/nvme into…
Browse files Browse the repository at this point in the history
… block-6.14

Pull NVMe fixes from Keith:

"nvme fixes for Linux 6.14

 - Concurrent pci error and hotplug handling fix (Keith)
 - Endpoint function fixes (Damien)"

* tag 'nvme-6.14-2025-03-13' of git://git.infradead.org/nvme:
  nvmet: pci-epf: Do not add an IRQ vector if not needed
  nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created
  nvme-pci: fix stuck reset on concurrent DPC and HP
  • Loading branch information
Jens Axboe committed Mar 13, 2025
2 parents 9bce6b5 + 39393f5 commit a938135
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 15 deletions.
13 changes: 12 additions & 1 deletion drivers/nvme/host/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1412,17 +1412,28 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
struct nvme_dev *dev = nvmeq->dev;
struct request *abort_req;
struct nvme_command cmd = { };
struct pci_dev *pdev = to_pci_dev(dev->dev);
u32 csts = readl(dev->bar + NVME_REG_CSTS);
u8 opcode;

/*
* Shutdown the device immediately if we see it is disconnected. This
* unblocks PCIe error handling if the nvme driver is waiting in
* error_resume for a device that has been removed. We can't unbind the
* driver while the driver's error callback is waiting to complete, so
* we're relying on a timeout to break that deadlock if a removal
* occurs while reset work is running.
*/
if (pci_dev_is_disconnected(pdev))
nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING);
if (nvme_state_terminal(&dev->ctrl))
goto disable;

/* If PCI error recovery process is happening, we cannot reset or
* the recovery mechanism will surely fail.
*/
mb();
if (pci_channel_offline(to_pci_dev(dev->dev)))
if (pci_channel_offline(pdev))
return BLK_EH_RESET_TIMER;

/*
Expand Down
28 changes: 14 additions & 14 deletions drivers/nvme/target/pci-epf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1265,15 +1265,12 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
struct nvmet_pci_epf_queue *cq = &ctrl->cq[cqid];
u16 status;

if (test_and_set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags))
if (test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags))
return NVME_SC_QID_INVALID | NVME_STATUS_DNR;

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;
Expand All @@ -1290,24 +1287,27 @@ 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);
if (status != NVME_SC_SUCCESS)
goto err;

set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags);

dev_dbg(ctrl->dev, "CQ[%u]: %u entries of %zu B, IRQ vector %u\n",
cqid, qsize, cq->qes, cq->vector);

return NVME_SC_SUCCESS;

err:
clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags);
clear_bit(NVMET_PCI_EPF_Q_LIVE, &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;
}

Expand All @@ -1333,7 +1333,7 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl,
struct nvmet_pci_epf_queue *sq = &ctrl->sq[sqid];
u16 status;

if (test_and_set_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags))
if (test_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags))
return NVME_SC_QID_INVALID | NVME_STATUS_DNR;

if (!(flags & NVME_QUEUE_PHYS_CONTIG))
Expand All @@ -1355,7 +1355,7 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl,

status = nvmet_sq_create(tctrl, &sq->nvme_sq, sqid, sq->depth);
if (status != NVME_SC_SUCCESS)
goto out_clear_bit;
return status;

sq->iod_wq = alloc_workqueue("sq%d_wq", WQ_UNBOUND,
min_t(int, sq->depth, WQ_MAX_ACTIVE), sqid);
Expand All @@ -1365,15 +1365,15 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl,
goto out_destroy_sq;
}

set_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags);

dev_dbg(ctrl->dev, "SQ[%u]: %u entries of %zu B\n",
sqid, qsize, sq->qes);

return NVME_SC_SUCCESS;

out_destroy_sq:
nvmet_sq_destroy(&sq->nvme_sq);
out_clear_bit:
clear_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags);
return status;
}

Expand Down

0 comments on commit a938135

Please sign in to comment.