mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
synced 2025-04-19 20:58:31 +09:00
nvme fixes for Linux 6.15
- fix scan failure for non-ANA multipath controllers (Hannes Reinecke) - fix multipath sysfs links creation for some cases (Hannes Reinecke) - PCIe endpoint fixes (Damien Le Moal) - use NULL instead of 0 in the auth code (Damien Le Moal) -----BEGIN PGP SIGNATURE----- iQI/BAABCgApFiEEgdbnc3r/njty3Iq9D55TZVIEUYMFAmgAo4wLHGhjaEBsc3Qu ZGUACgkQD55TZVIEUYNmfw/9EbS9qrtCo8n8kwkhez7mzx+d36fveTGdA+XApm/3 M2ZHwosFqw8TgBQTVxvqqPeUit8ZeD78IGvSOwK7p+bO8R55h1m2BxVKbY+1VJhE r+5Cdq5BYsXb3C0P1MWnW3pu4VTzC/+kH1SH4yNw00rW//+W5xBgpKfWglzzMsw5 FGqgLa2venfMRGuqXtoya3iTPhyPvIQMzPXwhkLd/iBVioWuJlgZNX0vspzyYmjo XES90XcASItOa9aR5tdPz0nQ+cmVz7yEGJkzUNX2is50shn3llR43Jr2mLEyMKS9 3ZGfsX7jHLPv8l7aPOs5chGJOSOGYU+oLV64dKM8X/RtfyY4XCT6ImE6Eqstvblu q8x0lMk5iYX/wdNNJh2LH8/6RC30TxGn8/PGpm2qK2RYBOwF+kBOdRvr2F9w1MNV SAzJv4vQQd6+JjwubvvJknky2sB7ogZSgY1m+g+VoAGDrwPvS/PQPkfYUrJ8LH2O FaKoS/U+KOEJhcqEmJ//LQNZh+YpvXXdEMAHzC8ifhBqEBY/1F4+AcKpubYNGrHU 2jlvH9tgxSkA450McDPmNO+62ZH0gPvCHZbbABJIGuhoiR+lcycuu1l3uhJbms4p X5ZSYmzXbBRCTviOL0Qs9wPcNOUh/FLVN+DUS7ticvTDg8DLm2SA/fBiXtcnWw3b x2Y= =ZSJ5 -----END PGP SIGNATURE----- Merge tag 'nvme-6.15-2025-04-17' of git://git.infradead.org/nvme into block-6.15 Pull NVMe fixes from Christoph: "nvme fixes for Linux 6.15 - fix scan failure for non-ANA multipath controllers (Hannes Reinecke) - fix multipath sysfs links creation for some cases (Hannes Reinecke) - PCIe endpoint fixes (Damien Le Moal) - use NULL instead of 0 in the auth code (Damien Le Moal)" * tag 'nvme-6.15-2025-04-17' of git://git.infradead.org/nvme: nvmet: pci-epf: cleanup link state management nvmet: pci-epf: clear CC and CSTS when disabling the controller nvmet: pci-epf: always fully initialize completion entries nvmet: auth: use NULL to clear a pointer in nvmet_auth_sq_free() nvme-multipath: sysfs links may not be created for devices nvme: fixup scan failure for non-ANA multipath controllers
This commit is contained in:
commit
81dd1feb19
@ -4300,7 +4300,7 @@ static void nvme_scan_work(struct work_struct *work)
|
||||
if (test_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events))
|
||||
nvme_queue_scan(ctrl);
|
||||
#ifdef CONFIG_NVME_MULTIPATH
|
||||
else
|
||||
else if (ctrl->ana_log_buf)
|
||||
/* Re-read the ANA log page to not miss updates */
|
||||
queue_work(nvme_wq, &ctrl->ana_work);
|
||||
#endif
|
||||
|
@ -1050,6 +1050,13 @@ void nvme_mpath_add_sysfs_link(struct nvme_ns_head *head)
|
||||
srcu_idx = srcu_read_lock(&head->srcu);
|
||||
|
||||
list_for_each_entry_rcu(ns, &head->list, siblings) {
|
||||
/*
|
||||
* Ensure that ns path disk node is already added otherwise we
|
||||
* may get invalid kobj name for target
|
||||
*/
|
||||
if (!test_bit(GD_ADDED, &ns->disk->state))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Avoid creating link if it already exists for the given path.
|
||||
* When path ana state transitions from optimized to non-
|
||||
@ -1065,13 +1072,6 @@ void nvme_mpath_add_sysfs_link(struct nvme_ns_head *head)
|
||||
if (test_and_set_bit(NVME_NS_SYSFS_ATTR_LINK, &ns->flags))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Ensure that ns path disk node is already added otherwise we
|
||||
* may get invalid kobj name for target
|
||||
*/
|
||||
if (!test_bit(GD_ADDED, &ns->disk->state))
|
||||
continue;
|
||||
|
||||
target = disk_to_dev(ns->disk);
|
||||
/*
|
||||
* Create sysfs link from head gendisk kobject @kobj to the
|
||||
|
@ -240,7 +240,7 @@ void nvmet_auth_sq_free(struct nvmet_sq *sq)
|
||||
{
|
||||
cancel_delayed_work(&sq->auth_expired_work);
|
||||
#ifdef CONFIG_NVME_TARGET_TCP_TLS
|
||||
sq->tls_key = 0;
|
||||
sq->tls_key = NULL;
|
||||
#endif
|
||||
kfree(sq->dhchap_c1);
|
||||
sq->dhchap_c1 = NULL;
|
||||
|
@ -1648,16 +1648,17 @@ static int nvmet_pci_epf_process_sq(struct nvmet_pci_epf_ctrl *ctrl,
|
||||
{
|
||||
struct nvmet_pci_epf_iod *iod;
|
||||
int ret, n = 0;
|
||||
u16 head = sq->head;
|
||||
|
||||
sq->tail = nvmet_pci_epf_bar_read32(ctrl, sq->db);
|
||||
while (sq->head != sq->tail && (!ctrl->sq_ab || n < ctrl->sq_ab)) {
|
||||
while (head != sq->tail && (!ctrl->sq_ab || n < ctrl->sq_ab)) {
|
||||
iod = nvmet_pci_epf_alloc_iod(sq);
|
||||
if (!iod)
|
||||
break;
|
||||
|
||||
/* Get the NVMe command submitted by the host. */
|
||||
ret = nvmet_pci_epf_transfer(ctrl, &iod->cmd,
|
||||
sq->pci_addr + sq->head * sq->qes,
|
||||
sq->pci_addr + head * sq->qes,
|
||||
sq->qes, DMA_FROM_DEVICE);
|
||||
if (ret) {
|
||||
/* Not much we can do... */
|
||||
@ -1666,12 +1667,13 @@ static int nvmet_pci_epf_process_sq(struct nvmet_pci_epf_ctrl *ctrl,
|
||||
}
|
||||
|
||||
dev_dbg(ctrl->dev, "SQ[%u]: head %u, tail %u, command %s\n",
|
||||
sq->qid, sq->head, sq->tail,
|
||||
sq->qid, head, sq->tail,
|
||||
nvmet_pci_epf_iod_name(iod));
|
||||
|
||||
sq->head++;
|
||||
if (sq->head == sq->depth)
|
||||
sq->head = 0;
|
||||
head++;
|
||||
if (head == sq->depth)
|
||||
head = 0;
|
||||
WRITE_ONCE(sq->head, head);
|
||||
n++;
|
||||
|
||||
queue_work_on(WORK_CPU_UNBOUND, sq->iod_wq, &iod->work);
|
||||
@ -1761,8 +1763,17 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work)
|
||||
if (!iod)
|
||||
break;
|
||||
|
||||
/* Post the IOD completion entry. */
|
||||
/*
|
||||
* Post the IOD completion entry. If the IOD request was
|
||||
* executed (req->execute() called), the CQE is already
|
||||
* initialized. However, the IOD may have been failed before
|
||||
* that, leaving the CQE not properly initialized. So always
|
||||
* initialize it here.
|
||||
*/
|
||||
cqe = &iod->cqe;
|
||||
cqe->sq_head = cpu_to_le16(READ_ONCE(iod->sq->head));
|
||||
cqe->sq_id = cpu_to_le16(iod->sq->qid);
|
||||
cqe->command_id = iod->cmd.common.command_id;
|
||||
cqe->status = cpu_to_le16((iod->status << 1) | cq->phase);
|
||||
|
||||
dev_dbg(ctrl->dev,
|
||||
@ -1800,6 +1811,21 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work)
|
||||
NVMET_PCI_EPF_CQ_RETRY_INTERVAL);
|
||||
}
|
||||
|
||||
static void nvmet_pci_epf_clear_ctrl_config(struct nvmet_pci_epf_ctrl *ctrl)
|
||||
{
|
||||
struct nvmet_ctrl *tctrl = ctrl->tctrl;
|
||||
|
||||
/* Initialize controller status. */
|
||||
tctrl->csts = 0;
|
||||
ctrl->csts = 0;
|
||||
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CSTS, ctrl->csts);
|
||||
|
||||
/* Initialize controller configuration and start polling. */
|
||||
tctrl->cc = 0;
|
||||
ctrl->cc = 0;
|
||||
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CC, ctrl->cc);
|
||||
}
|
||||
|
||||
static int nvmet_pci_epf_enable_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
|
||||
{
|
||||
u64 pci_addr, asq, acq;
|
||||
@ -1865,18 +1891,20 @@ static int nvmet_pci_epf_enable_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
|
||||
return 0;
|
||||
|
||||
err:
|
||||
ctrl->csts = 0;
|
||||
nvmet_pci_epf_clear_ctrl_config(ctrl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void nvmet_pci_epf_disable_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
|
||||
static void nvmet_pci_epf_disable_ctrl(struct nvmet_pci_epf_ctrl *ctrl,
|
||||
bool shutdown)
|
||||
{
|
||||
int qid;
|
||||
|
||||
if (!ctrl->enabled)
|
||||
return;
|
||||
|
||||
dev_info(ctrl->dev, "Disabling controller\n");
|
||||
dev_info(ctrl->dev, "%s controller\n",
|
||||
shutdown ? "Shutting down" : "Disabling");
|
||||
|
||||
ctrl->enabled = false;
|
||||
cancel_delayed_work_sync(&ctrl->poll_sqs);
|
||||
@ -1893,6 +1921,11 @@ static void nvmet_pci_epf_disable_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
|
||||
nvmet_pci_epf_delete_cq(ctrl->tctrl, 0);
|
||||
|
||||
ctrl->csts &= ~NVME_CSTS_RDY;
|
||||
if (shutdown) {
|
||||
ctrl->csts |= NVME_CSTS_SHST_CMPLT;
|
||||
ctrl->cc &= ~NVME_CC_ENABLE;
|
||||
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CC, ctrl->cc);
|
||||
}
|
||||
}
|
||||
|
||||
static void nvmet_pci_epf_poll_cc_work(struct work_struct *work)
|
||||
@ -1919,12 +1952,10 @@ static void nvmet_pci_epf_poll_cc_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
if (!nvmet_cc_en(new_cc) && nvmet_cc_en(old_cc))
|
||||
nvmet_pci_epf_disable_ctrl(ctrl);
|
||||
nvmet_pci_epf_disable_ctrl(ctrl, false);
|
||||
|
||||
if (nvmet_cc_shn(new_cc) && !nvmet_cc_shn(old_cc)) {
|
||||
nvmet_pci_epf_disable_ctrl(ctrl);
|
||||
ctrl->csts |= NVME_CSTS_SHST_CMPLT;
|
||||
}
|
||||
if (nvmet_cc_shn(new_cc) && !nvmet_cc_shn(old_cc))
|
||||
nvmet_pci_epf_disable_ctrl(ctrl, true);
|
||||
|
||||
if (!nvmet_cc_shn(new_cc) && nvmet_cc_shn(old_cc))
|
||||
ctrl->csts &= ~NVME_CSTS_SHST_CMPLT;
|
||||
@ -1963,16 +1994,10 @@ static void nvmet_pci_epf_init_bar(struct nvmet_pci_epf_ctrl *ctrl)
|
||||
/* Clear Controller Memory Buffer Supported (CMBS). */
|
||||
ctrl->cap &= ~(0x1ULL << 57);
|
||||
|
||||
/* Controller configuration. */
|
||||
ctrl->cc = tctrl->cc & (~NVME_CC_ENABLE);
|
||||
|
||||
/* Controller status. */
|
||||
ctrl->csts = ctrl->tctrl->csts;
|
||||
|
||||
nvmet_pci_epf_bar_write64(ctrl, NVME_REG_CAP, ctrl->cap);
|
||||
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_VS, tctrl->subsys->ver);
|
||||
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CSTS, ctrl->csts);
|
||||
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CC, ctrl->cc);
|
||||
|
||||
nvmet_pci_epf_clear_ctrl_config(ctrl);
|
||||
}
|
||||
|
||||
static int nvmet_pci_epf_create_ctrl(struct nvmet_pci_epf *nvme_epf,
|
||||
@ -2070,14 +2095,22 @@ out_mempool_exit:
|
||||
|
||||
static void nvmet_pci_epf_start_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
|
||||
{
|
||||
|
||||
dev_info(ctrl->dev, "PCI link up\n");
|
||||
ctrl->link_up = true;
|
||||
|
||||
schedule_delayed_work(&ctrl->poll_cc, NVMET_PCI_EPF_CC_POLL_INTERVAL);
|
||||
}
|
||||
|
||||
static void nvmet_pci_epf_stop_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
|
||||
{
|
||||
dev_info(ctrl->dev, "PCI link down\n");
|
||||
ctrl->link_up = false;
|
||||
|
||||
cancel_delayed_work_sync(&ctrl->poll_cc);
|
||||
|
||||
nvmet_pci_epf_disable_ctrl(ctrl);
|
||||
nvmet_pci_epf_disable_ctrl(ctrl, false);
|
||||
nvmet_pci_epf_clear_ctrl_config(ctrl);
|
||||
}
|
||||
|
||||
static void nvmet_pci_epf_destroy_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
|
||||
@ -2300,10 +2333,8 @@ static int nvmet_pci_epf_epc_init(struct pci_epf *epf)
|
||||
if (ret)
|
||||
goto out_clear_bar;
|
||||
|
||||
if (!epc_features->linkup_notifier) {
|
||||
ctrl->link_up = true;
|
||||
if (!epc_features->linkup_notifier)
|
||||
nvmet_pci_epf_start_ctrl(&nvme_epf->ctrl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -2319,7 +2350,6 @@ static void nvmet_pci_epf_epc_deinit(struct pci_epf *epf)
|
||||
struct nvmet_pci_epf *nvme_epf = epf_get_drvdata(epf);
|
||||
struct nvmet_pci_epf_ctrl *ctrl = &nvme_epf->ctrl;
|
||||
|
||||
ctrl->link_up = false;
|
||||
nvmet_pci_epf_destroy_ctrl(ctrl);
|
||||
|
||||
nvmet_pci_epf_deinit_dma(nvme_epf);
|
||||
@ -2331,7 +2361,6 @@ static int nvmet_pci_epf_link_up(struct pci_epf *epf)
|
||||
struct nvmet_pci_epf *nvme_epf = epf_get_drvdata(epf);
|
||||
struct nvmet_pci_epf_ctrl *ctrl = &nvme_epf->ctrl;
|
||||
|
||||
ctrl->link_up = true;
|
||||
nvmet_pci_epf_start_ctrl(ctrl);
|
||||
|
||||
return 0;
|
||||
@ -2342,7 +2371,6 @@ static int nvmet_pci_epf_link_down(struct pci_epf *epf)
|
||||
struct nvmet_pci_epf *nvme_epf = epf_get_drvdata(epf);
|
||||
struct nvmet_pci_epf_ctrl *ctrl = &nvme_epf->ctrl;
|
||||
|
||||
ctrl->link_up = false;
|
||||
nvmet_pci_epf_stop_ctrl(ctrl);
|
||||
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user