Skip to content

Commit f8e01fa

Browse files
damien-lemoalChristoph Hellwig
authored andcommitted
nvmet: pci-epf: clear CC and CSTS when disabling the controller
When a host shuts down the controller when shutting down but does so without first disabling the controller, the enable bit remains set in the controller configuration register. When the host restarts and attempts to enable the controller again, the nvmet_pci_epf_poll_cc_work() function is unable to detect the change from 0 to 1 of the enable bit, and thus the controller is not enabled again, which result in a device scan timeout on the host. This problem also occurs if the host shuts down uncleanly or if the PCIe link goes down: as the CC.EN value is not reset, the controller is not enabled again when the host restarts. Fix this by introducing the function nvmet_pci_epf_clear_ctrl_config() to clear the CC and CSTS registers of the controller when the PCIe link is lost (nvmet_pci_epf_stop_ctrl() function), or when starting the controller fails (nvmet_pci_epf_enable_ctrl() fails). Also use this function in nvmet_pci_epf_init_bar() to simplify the initialization of the CC and CSTS registers. Furthermore, modify the function nvmet_pci_epf_disable_ctrl() to clear the CC.EN bit and write this updated value to the BAR register when the controller is shutdown by the host, to ensure that upon restart, we can detect the host setting CC.EN. Fixes: 0faa0fe ("nvmet: New NVMe PCI endpoint function target driver") Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Niklas Cassel <cassel@kernel.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent ffe0398 commit f8e01fa

File tree

1 file changed

+32
-17
lines changed

1 file changed

+32
-17
lines changed

drivers/nvme/target/pci-epf.c

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,21 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work)
18111811
NVMET_PCI_EPF_CQ_RETRY_INTERVAL);
18121812
}
18131813

1814+
static void nvmet_pci_epf_clear_ctrl_config(struct nvmet_pci_epf_ctrl *ctrl)
1815+
{
1816+
struct nvmet_ctrl *tctrl = ctrl->tctrl;
1817+
1818+
/* Initialize controller status. */
1819+
tctrl->csts = 0;
1820+
ctrl->csts = 0;
1821+
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CSTS, ctrl->csts);
1822+
1823+
/* Initialize controller configuration and start polling. */
1824+
tctrl->cc = 0;
1825+
ctrl->cc = 0;
1826+
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CC, ctrl->cc);
1827+
}
1828+
18141829
static int nvmet_pci_epf_enable_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
18151830
{
18161831
u64 pci_addr, asq, acq;
@@ -1876,18 +1891,20 @@ static int nvmet_pci_epf_enable_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
18761891
return 0;
18771892

18781893
err:
1879-
ctrl->csts = 0;
1894+
nvmet_pci_epf_clear_ctrl_config(ctrl);
18801895
return -EINVAL;
18811896
}
18821897

1883-
static void nvmet_pci_epf_disable_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
1898+
static void nvmet_pci_epf_disable_ctrl(struct nvmet_pci_epf_ctrl *ctrl,
1899+
bool shutdown)
18841900
{
18851901
int qid;
18861902

18871903
if (!ctrl->enabled)
18881904
return;
18891905

1890-
dev_info(ctrl->dev, "Disabling controller\n");
1906+
dev_info(ctrl->dev, "%s controller\n",
1907+
shutdown ? "Shutting down" : "Disabling");
18911908

18921909
ctrl->enabled = false;
18931910
cancel_delayed_work_sync(&ctrl->poll_sqs);
@@ -1904,6 +1921,11 @@ static void nvmet_pci_epf_disable_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
19041921
nvmet_pci_epf_delete_cq(ctrl->tctrl, 0);
19051922

19061923
ctrl->csts &= ~NVME_CSTS_RDY;
1924+
if (shutdown) {
1925+
ctrl->csts |= NVME_CSTS_SHST_CMPLT;
1926+
ctrl->cc &= ~NVME_CC_ENABLE;
1927+
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CC, ctrl->cc);
1928+
}
19071929
}
19081930

19091931
static void nvmet_pci_epf_poll_cc_work(struct work_struct *work)
@@ -1930,12 +1952,10 @@ static void nvmet_pci_epf_poll_cc_work(struct work_struct *work)
19301952
}
19311953

19321954
if (!nvmet_cc_en(new_cc) && nvmet_cc_en(old_cc))
1933-
nvmet_pci_epf_disable_ctrl(ctrl);
1955+
nvmet_pci_epf_disable_ctrl(ctrl, false);
19341956

1935-
if (nvmet_cc_shn(new_cc) && !nvmet_cc_shn(old_cc)) {
1936-
nvmet_pci_epf_disable_ctrl(ctrl);
1937-
ctrl->csts |= NVME_CSTS_SHST_CMPLT;
1938-
}
1957+
if (nvmet_cc_shn(new_cc) && !nvmet_cc_shn(old_cc))
1958+
nvmet_pci_epf_disable_ctrl(ctrl, true);
19391959

19401960
if (!nvmet_cc_shn(new_cc) && nvmet_cc_shn(old_cc))
19411961
ctrl->csts &= ~NVME_CSTS_SHST_CMPLT;
@@ -1974,16 +1994,10 @@ static void nvmet_pci_epf_init_bar(struct nvmet_pci_epf_ctrl *ctrl)
19741994
/* Clear Controller Memory Buffer Supported (CMBS). */
19751995
ctrl->cap &= ~(0x1ULL << 57);
19761996

1977-
/* Controller configuration. */
1978-
ctrl->cc = tctrl->cc & (~NVME_CC_ENABLE);
1979-
1980-
/* Controller status. */
1981-
ctrl->csts = ctrl->tctrl->csts;
1982-
19831997
nvmet_pci_epf_bar_write64(ctrl, NVME_REG_CAP, ctrl->cap);
19841998
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_VS, tctrl->subsys->ver);
1985-
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CSTS, ctrl->csts);
1986-
nvmet_pci_epf_bar_write32(ctrl, NVME_REG_CC, ctrl->cc);
1999+
2000+
nvmet_pci_epf_clear_ctrl_config(ctrl);
19872001
}
19882002

19892003
static int nvmet_pci_epf_create_ctrl(struct nvmet_pci_epf *nvme_epf,
@@ -2088,7 +2102,8 @@ static void nvmet_pci_epf_stop_ctrl(struct nvmet_pci_epf_ctrl *ctrl)
20882102
{
20892103
cancel_delayed_work_sync(&ctrl->poll_cc);
20902104

2091-
nvmet_pci_epf_disable_ctrl(ctrl);
2105+
nvmet_pci_epf_disable_ctrl(ctrl, false);
2106+
nvmet_pci_epf_clear_ctrl_config(ctrl);
20922107
}
20932108

20942109
static void nvmet_pci_epf_destroy_ctrl(struct nvmet_pci_epf_ctrl *ctrl)

0 commit comments

Comments
 (0)