summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Fomichev2020-12-08 21:03:58 +0100
committerKlaus Jensen2021-02-08 18:55:48 +0100
commitba69f224817437b5280f4c8ef511d09f17ab1305 (patch)
tree02ac926e221582024affbfff566d12dfe7ac09c6
parenthw/block/nvme: fix bad clearing of CAP (diff)
downloadqemu-ba69f224817437b5280f4c8ef511d09f17ab1305.tar.gz
qemu-ba69f224817437b5280f4c8ef511d09f17ab1305.tar.xz
qemu-ba69f224817437b5280f4c8ef511d09f17ab1305.zip
hw/block/nvme: Process controller reset and shutdown differently
Controller reset ans subsystem shutdown are handled very much the same in the current code, but some of the steps should be different in these two cases. Introduce two new functions, nvme_reset_ctrl() and nvme_shutdown_ctrl(), to separate some portions of the code from nvme_clear_ctrl(). The steps that are made different between reset and shutdown are that BAR.CC is not reset to zero upon the shutdown and namespace data is flushed to backing storage as a part of shutdown handling, but not upon reset. Suggested-by: Klaus Jensen <k.jensen@samsung.com> Signed-off-by: Dmitry Fomichev <dmitry.fomichev@wdc.com> Reviewed-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
-rw-r--r--hw/block/nvme-ns.c2
-rw-r--r--hw/block/nvme-ns.h2
-rw-r--r--hw/block/nvme.c24
3 files changed, 20 insertions, 8 deletions
diff --git a/hw/block/nvme-ns.c b/hw/block/nvme-ns.c
index 37f95951a6..a0de53e718 100644
--- a/hw/block/nvme-ns.c
+++ b/hw/block/nvme-ns.c
@@ -129,7 +129,7 @@ void nvme_ns_drain(NvmeNamespace *ns)
blk_drain(ns->blkconf.blk);
}
-void nvme_ns_flush(NvmeNamespace *ns)
+void nvme_ns_shutdown(NvmeNamespace *ns)
{
blk_flush(ns->blkconf.blk);
}
diff --git a/hw/block/nvme-ns.h b/hw/block/nvme-ns.h
index 44bf6271b7..ed3d7e65d5 100644
--- a/hw/block/nvme-ns.h
+++ b/hw/block/nvme-ns.h
@@ -73,6 +73,6 @@ typedef struct NvmeCtrl NvmeCtrl;
int nvme_ns_setup(NvmeCtrl *n, NvmeNamespace *ns, Error **errp);
void nvme_ns_drain(NvmeNamespace *ns);
-void nvme_ns_flush(NvmeNamespace *ns);
+void nvme_ns_shutdown(NvmeNamespace *ns);
#endif /* NVME_NS_H */
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index de52487aaf..f54c5c6ea4 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2295,6 +2295,20 @@ static void nvme_clear_ctrl(NvmeCtrl *n)
n->aer_queued = 0;
n->outstanding_aers = 0;
n->qs_created = false;
+}
+
+static void nvme_ctrl_reset(NvmeCtrl *n)
+{
+ nvme_clear_ctrl(n);
+ n->bar.cc = 0;
+}
+
+static void nvme_ctrl_shutdown(NvmeCtrl *n)
+{
+ NvmeNamespace *ns;
+ int i;
+
+ nvme_clear_ctrl(n);
for (i = 1; i <= n->num_namespaces; i++) {
ns = nvme_ns(n, i);
@@ -2302,10 +2316,8 @@ static void nvme_clear_ctrl(NvmeCtrl *n)
continue;
}
- nvme_ns_flush(ns);
+ nvme_ns_shutdown(ns);
}
-
- n->bar.cc = 0;
}
static int nvme_start_ctrl(NvmeCtrl *n)
@@ -2472,12 +2484,12 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
}
} else if (!NVME_CC_EN(data) && NVME_CC_EN(n->bar.cc)) {
trace_pci_nvme_mmio_stopped();
- nvme_clear_ctrl(n);
+ nvme_ctrl_reset(n);
n->bar.csts &= ~NVME_CSTS_READY;
}
if (NVME_CC_SHN(data) && !(NVME_CC_SHN(n->bar.cc))) {
trace_pci_nvme_mmio_shutdown_set();
- nvme_clear_ctrl(n);
+ nvme_ctrl_shutdown(n);
n->bar.cc = data;
n->bar.csts |= NVME_CSTS_SHST_COMPLETE;
} else if (!NVME_CC_SHN(data) && NVME_CC_SHN(n->bar.cc)) {
@@ -3088,7 +3100,7 @@ static void nvme_exit(PCIDevice *pci_dev)
{
NvmeCtrl *n = NVME(pci_dev);
- nvme_clear_ctrl(n);
+ nvme_ctrl_shutdown(n);
g_free(n->cq);
g_free(n->sq);
g_free(n->aer_reqs);