nvme: add new SET_EN_0 state for ctrlr initialization

This removes some code that was duplicated in the
CHECK_EN and DISABLE_WAIT_FOR_READY_1 states.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: Ie5d175540f71c692f7784c7ff22a48f34b9b7082
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8614
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
Jim Harris 2021-06-08 22:15:28 +00:00 committed by Tomasz Zawadzki
parent d953072d21
commit fc8d861892
3 changed files with 41 additions and 44 deletions

View File

@ -1237,6 +1237,8 @@ nvme_ctrlr_state_string(enum nvme_ctrlr_state state)
return "check en";
case NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_1:
return "disable and wait for CSTS.RDY = 1";
case NVME_CTRLR_STATE_SET_EN_0:
return "set CC.EN = 0";
case NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0:
return "disable and wait for CSTS.RDY = 0";
case NVME_CTRLR_STATE_ENABLE:
@ -3462,56 +3464,44 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr)
/* Begin the hardware initialization by making sure the controller is disabled. */
if (cc.bits.en) {
NVME_CTRLR_DEBUGLOG(ctrlr, "CC.EN = 1\n");
/*
* Controller is currently enabled. We need to disable it to cause a reset.
*
* If CC.EN = 1 && CSTS.RDY = 0, the controller is in the process of becoming ready.
* Wait for the ready bit to be 1 before disabling the controller.
*/
if (csts.bits.rdy == 0) {
NVME_CTRLR_DEBUGLOG(ctrlr, "CC.EN = 1 && CSTS.RDY = 0 - waiting for reset to complete\n");
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_1, ready_timeout_in_ms);
return 0;
}
/* CC.EN = 1 && CSTS.RDY == 1, so we can immediately disable the controller. */
NVME_CTRLR_DEBUGLOG(ctrlr, "Setting CC.EN = 0\n");
cc.bits.en = 0;
if (nvme_ctrlr_set_cc(ctrlr, &cc)) {
NVME_CTRLR_ERRLOG(ctrlr, "set_cc() failed\n");
return -EIO;
}
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0, ready_timeout_in_ms);
/*
* Wait 2.5 seconds before accessing PCI registers.
* Not using sleep() to avoid blocking other controller's initialization.
*/
if (ctrlr->quirks & NVME_QUIRK_DELAY_BEFORE_CHK_RDY) {
NVME_CTRLR_DEBUGLOG(ctrlr, "Applying quirk: delay 2.5 seconds before reading registers\n");
ctrlr->sleep_timeout_tsc = ticks + (2500 * spdk_get_ticks_hz() / 1000);
}
return 0;
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_1, ready_timeout_in_ms);
} else {
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0, ready_timeout_in_ms);
return 0;
}
break;
return 0;
case NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_1:
/*
* Controller is currently enabled. We need to disable it to cause a reset.
*
* If CC.EN = 1 && CSTS.RDY = 0, the controller is in the process of becoming ready.
* Wait for the ready bit to be 1 before disabling the controller.
*/
if (csts.bits.rdy == 1) {
NVME_CTRLR_DEBUGLOG(ctrlr, "CC.EN = 1 && CSTS.RDY = 1 - disabling controller\n");
/* CC.EN = 1 && CSTS.RDY = 1, so we can set CC.EN = 0 now. */
NVME_CTRLR_DEBUGLOG(ctrlr, "Setting CC.EN = 0\n");
cc.bits.en = 0;
if (nvme_ctrlr_set_cc(ctrlr, &cc)) {
NVME_CTRLR_ERRLOG(ctrlr, "set_cc() failed\n");
return -EIO;
}
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0, ready_timeout_in_ms);
return 0;
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_SET_EN_0, ready_timeout_in_ms);
} else {
NVME_CTRLR_DEBUGLOG(ctrlr, "CC.EN = 1 && CSTS.RDY = 0 - waiting for reset to complete\n");
}
break;
return 0;
case NVME_CTRLR_STATE_SET_EN_0:
NVME_CTRLR_DEBUGLOG(ctrlr, "Setting CC.EN = 0\n");
cc.bits.en = 0;
if (nvme_ctrlr_set_cc(ctrlr, &cc)) {
NVME_CTRLR_ERRLOG(ctrlr, "set_cc() failed\n");
return -EIO;
}
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0, ready_timeout_in_ms);
/*
* Wait 2.5 seconds before accessing PCI registers.
* Not using sleep() to avoid blocking other controller's initialization.
*/
if (ctrlr->quirks & NVME_QUIRK_DELAY_BEFORE_CHK_RDY) {
NVME_CTRLR_DEBUGLOG(ctrlr, "Applying quirk: delay 2.5 seconds before reading registers\n");
ctrlr->sleep_timeout_tsc = ticks + (2500 * spdk_get_ticks_hz() / 1000);
}
return 0;
case NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0:
if (csts.bits.rdy == 0) {

View File

@ -578,6 +578,11 @@ enum nvme_ctrlr_state {
*/
NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_1,
/**
* Disabling the controller by setting CC.EN to 0.
*/
NVME_CTRLR_STATE_SET_EN_0,
/**
* Waiting for CSTS.RDY to transition from 1 to 0 so that CC.EN may be set to 1.
*/

View File

@ -724,6 +724,8 @@ test_nvme_ctrlr_init_en_1_rdy_0(void)
*/
g_ut_nvme_regs.csts.bits.rdy = 1;
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_SET_EN_0);
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_0);
CU_ASSERT(g_ut_nvme_regs.cc.bits.en == 0);
@ -777,7 +779,7 @@ test_nvme_ctrlr_init_en_1_rdy_1(void)
ctrlr.cdata.nn = 1;
ctrlr.page_size = 0x1000;
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_INIT);
while (ctrlr.state != NVME_CTRLR_STATE_CHECK_EN) {
while (ctrlr.state != NVME_CTRLR_STATE_SET_EN_0) {
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
}
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);