From 87a3244f974a98b2a85835b37c86241fcd3bc471 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Fri, 8 Apr 2016 09:13:10 -0700 Subject: [PATCH] nvme: handle CC.EN = 0 && CSTS.RDY = 1 on startup This can happen if the controller is still resetting as the SPDK NVMe driver takes control. Change-Id: I263ae8f2e7b271e0448450557452a115c90c4fb6 Signed-off-by: Daniel Verkamp --- lib/nvme/nvme_ctrlr.c | 9 ++++ .../nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c | 41 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index b6b204fa2..3dd88a96a 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -860,6 +860,15 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr) nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0, ready_timeout_in_ms); return 0; } else { + if (csts.bits.rdy == 1) { + /* + * Controller is in the process of shutting down. + * We need to wait for RDY to become 0. + */ + nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0, ready_timeout_in_ms); + return 0; + } + /* * Controller is currently disabled. We can jump straight to enabling it. */ diff --git a/test/lib/nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c b/test/lib/nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c index f27da71e3..c459b76bf 100644 --- a/test/lib/nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c +++ b/test/lib/nvme/unit/nvme_ctrlr_c/nvme_ctrlr_ut.c @@ -425,6 +425,45 @@ test_nvme_ctrlr_init_en_0_rdy_0(void) nvme_ctrlr_destruct(&ctrlr); } +static void +test_nvme_ctrlr_init_en_0_rdy_1(void) +{ + struct spdk_nvme_ctrlr ctrlr = {}; + + memset(&g_ut_nvme_regs, 0, sizeof(g_ut_nvme_regs)); + + /* + * Initial state: CC.EN = 0, CSTS.RDY = 1 + */ + g_ut_nvme_regs.cc.bits.en = 0; + g_ut_nvme_regs.csts.bits.rdy = 1; + + SPDK_CU_ASSERT_FATAL(nvme_ctrlr_construct(&ctrlr, NULL) == 0); + ctrlr.cdata.nn = 1; + CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_INIT); + CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0); + CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0); + + /* + * Transition to CSTS.RDY = 0. + * init() should set CC.EN = 1. + */ + g_ut_nvme_regs.csts.bits.rdy = 0; + CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0); + CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_ENABLE_WAIT_FOR_READY_1); + CU_ASSERT(g_ut_nvme_regs.cc.bits.en == 1); + + /* + * Transition to CSTS.RDY = 1. + */ + g_ut_nvme_regs.csts.bits.rdy = 1; + CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0); + CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_READY); + + g_ut_nvme_regs.csts.bits.shst = SPDK_NVME_SHST_COMPLETE; + nvme_ctrlr_destruct(&ctrlr); +} + static void setup_qpairs(struct spdk_nvme_ctrlr *ctrlr, uint32_t num_io_queues) { @@ -608,6 +647,8 @@ int main(int argc, char **argv) test_nvme_ctrlr_init_en_1_rdy_1) == NULL || CU_add_test(suite, "test nvme_ctrlr init CC.EN = 0 CSTS.RDY = 0", test_nvme_ctrlr_init_en_0_rdy_0) == NULL + || CU_add_test(suite, "test nvme_ctrlr init CC.EN = 0 CSTS.RDY = 1", + test_nvme_ctrlr_init_en_0_rdy_1) == NULL || CU_add_test(suite, "alloc_io_qpair 1", test_alloc_io_qpair_1) == NULL || CU_add_test(suite, "alloc_io_qpair 2", test_alloc_io_qpair_2) == NULL || CU_add_test(suite, "test nvme_ctrlr function nvme_ctrlr_fail", test_nvme_ctrlr_fail) == NULL