Commit 87a3244f authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

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: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent 20f92ad4
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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.
			 */
+41 −0
Original line number Diff line number Diff line
@@ -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