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 <daniel.verkamp@intel.com>
This commit is contained in:
Daniel Verkamp 2016-04-08 09:13:10 -07:00
parent 20f92ad45a
commit 87a3244f97
2 changed files with 50 additions and 0 deletions

View File

@ -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); nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0, ready_timeout_in_ms);
return 0; return 0;
} else { } 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. * Controller is currently disabled. We can jump straight to enabling it.
*/ */

View File

@ -425,6 +425,45 @@ test_nvme_ctrlr_init_en_0_rdy_0(void)
nvme_ctrlr_destruct(&ctrlr); 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 static void
setup_qpairs(struct spdk_nvme_ctrlr *ctrlr, uint32_t num_io_queues) 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 test_nvme_ctrlr_init_en_1_rdy_1) == NULL
|| CU_add_test(suite, "test nvme_ctrlr init CC.EN = 0 CSTS.RDY = 0", || CU_add_test(suite, "test nvme_ctrlr init CC.EN = 0 CSTS.RDY = 0",
test_nvme_ctrlr_init_en_0_rdy_0) == NULL 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 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, "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 || CU_add_test(suite, "test nvme_ctrlr function nvme_ctrlr_fail", test_nvme_ctrlr_fail) == NULL