From ae86baeba2be4d5b92dfc3d21ef7551b09d65d83 Mon Sep 17 00:00:00 2001 From: Seth Howell Date: Fri, 31 Jan 2020 16:10:28 -0700 Subject: [PATCH] nvmf: implement controller reset for fabrics. According to the spec, if the CC.EN bit is transitioned from 1 to 0, then all of the I/O qpairs shall be disconnected and the csts.rdy bit shall be set to zero. Change-Id: I871170e79e08a9fab8286f9c135c7b3316f58ace Signed-off-by: Seth Howell Signed-off-by: Ben Walker Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/423 Tested-by: SPDK CI Jenkins Reviewed-by: Changpeng Liu Reviewed-by: Seth Howell Reviewed-by: Jacek Kalwas Reviewed-by: Aleksey Marchuk Reviewed-by: Jim Harris --- lib/nvmf/ctrlr.c | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/lib/nvmf/ctrlr.c b/lib/nvmf/ctrlr.c index 08507e740..1a8113b4f 100644 --- a/lib/nvmf/ctrlr.c +++ b/lib/nvmf/ctrlr.c @@ -110,8 +110,8 @@ spdk_nvmf_ctrlr_disconnect_qpairs_done(struct spdk_io_channel_iter *i, int statu } } -static void -spdk_nvmf_ctrlr_disconnect_qpairs_on_pg(struct spdk_io_channel_iter *i) +static int +_spdk_nvmf_ctrlr_disconnect_qpairs_on_pg(struct spdk_io_channel_iter *i, bool include_admin) { int rc = 0; struct spdk_nvmf_ctrlr *ctrlr; @@ -124,17 +124,28 @@ spdk_nvmf_ctrlr_disconnect_qpairs_on_pg(struct spdk_io_channel_iter *i) group = spdk_io_channel_get_ctx(ch); TAILQ_FOREACH_SAFE(qpair, &group->qpairs, link, temp_qpair) { - if (qpair->ctrlr == ctrlr) { + if (qpair->ctrlr == ctrlr && (include_admin || !spdk_nvmf_qpair_is_admin_queue(qpair))) { rc = spdk_nvmf_qpair_disconnect(qpair, NULL, NULL); if (rc) { SPDK_ERRLOG("Qpair disconnect failed\n"); - goto next_channel; + return rc; } } } -next_channel: - spdk_for_each_channel_continue(i, rc); + return rc; +} + +static void +spdk_nvmf_ctrlr_disconnect_qpairs_on_pg(struct spdk_io_channel_iter *i) +{ + spdk_for_each_channel_continue(i, _spdk_nvmf_ctrlr_disconnect_qpairs_on_pg(i, true)); +} + +static void +spdk_nvmf_ctrlr_disconnect_io_qpairs_on_pg(struct spdk_io_channel_iter *i) +{ + spdk_for_each_channel_continue(i, _spdk_nvmf_ctrlr_disconnect_qpairs_on_pg(i, false)); } static int @@ -644,6 +655,22 @@ spdk_nvmf_ctrlr_cmd_connect(struct spdk_nvmf_request *req) return _spdk_nvmf_ctrlr_connect(req); } +static void +spdk_nvmf_ctrlr_cc_reset_done(struct spdk_io_channel_iter *i, int status) +{ + struct spdk_nvmf_ctrlr *ctrlr = spdk_io_channel_iter_get_ctx(i); + + if (status < 0) { + SPDK_ERRLOG("Fail to disconnect io ctrlr qpairs\n"); + assert(false); + } + + /* Only a subset of the registers are cleared out on a reset */ + ctrlr->vcprop.cc.raw = 0; + ctrlr->vcprop.csts.raw = 0; + +} + const struct spdk_nvmf_registers * spdk_nvmf_ctrlr_get_regs(struct spdk_nvmf_ctrlr *ctrlr) { @@ -690,8 +717,11 @@ nvmf_prop_set_cc(struct spdk_nvmf_ctrlr *ctrlr, uint32_t value) ctrlr->vcprop.cc.bits.en = 1; ctrlr->vcprop.csts.bits.rdy = 1; } else { - SPDK_ERRLOG("CC.EN transition from 1 to 0 (reset) not implemented!\n"); - return false; + ctrlr->vcprop.cc.bits.en = 0; + spdk_for_each_channel(ctrlr->subsys->tgt, + spdk_nvmf_ctrlr_disconnect_io_qpairs_on_pg, + ctrlr, + spdk_nvmf_ctrlr_cc_reset_done); } diff.bits.en = 0; }