diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index b5f23a3f2..f775a7838 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -81,6 +81,9 @@ static void nvme_ctrlr_set_state(struct spdk_nvme_ctrlr *ctrlr, enum nvme_ctrlr_ nvme_transport_ctrlr_get_reg_ ## sz ## _async(ctrlr, \ offsetof(struct spdk_nvme_registers, reg), cb_fn, cb_arg) +#define nvme_ctrlr_get_cap_async(ctrlr, cb_fn, cb_arg) \ + nvme_ctrlr_get_reg_async(ctrlr, cap, 8, cb_fn, cb_arg) + #define nvme_ctrlr_get_vs_async(ctrlr, cb_fn, cb_arg) \ nvme_ctrlr_get_reg_async(ctrlr, vs, 4, cb_fn, cb_arg) @@ -1244,6 +1247,8 @@ nvme_ctrlr_state_string(enum nvme_ctrlr_state state) return "read vs wait for vs"; case NVME_CTRLR_STATE_READ_CAP: return "read cap"; + case NVME_CTRLR_STATE_READ_CAP_WAIT_FOR_CAP: + return "read cap wait for cap"; case NVME_CTRLR_STATE_CHECK_EN: return "check en"; case NVME_CTRLR_STATE_DISABLE_WAIT_FOR_READY_1: @@ -3387,6 +3392,22 @@ nvme_ctrlr_process_init_vs_done(void *ctx, uint64_t value, const struct spdk_nvm nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_READ_CAP, NVME_TIMEOUT_INFINITE); } +static void +nvme_ctrlr_process_init_cap_done(void *ctx, uint64_t value, const struct spdk_nvme_cpl *cpl) +{ + struct spdk_nvme_ctrlr *ctrlr = ctx; + + if (spdk_nvme_cpl_is_error(cpl)) { + NVME_CTRLR_ERRLOG(ctrlr, "Failed to read the CAP register\n"); + nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_ERROR, NVME_TIMEOUT_INFINITE); + return; + } + + ctrlr->cap.raw = value; + nvme_ctrlr_init_cap(ctrlr); + nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_CHECK_EN, NVME_TIMEOUT_INFINITE); +} + /** * This function will be called repeatedly during initialization until the controller is ready. */ @@ -3483,8 +3504,8 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr) break; case NVME_CTRLR_STATE_READ_CAP: - nvme_ctrlr_init_cap(ctrlr); - nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_CHECK_EN, NVME_TIMEOUT_INFINITE); + nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_READ_CAP_WAIT_FOR_CAP, NVME_TIMEOUT_INFINITE); + rc = nvme_ctrlr_get_cap_async(ctrlr, nvme_ctrlr_process_init_cap_done, ctrlr); break; case NVME_CTRLR_STATE_CHECK_EN: @@ -3641,6 +3662,7 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr) return -1; case NVME_CTRLR_STATE_READ_VS_WAIT_FOR_VS: + case NVME_CTRLR_STATE_READ_CAP_WAIT_FOR_CAP: case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY: case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_IOCS_SPECIFIC: case NVME_CTRLR_STATE_WAIT_FOR_GET_ZNS_CMD_EFFECTS_LOG: @@ -3750,8 +3772,6 @@ nvme_ctrlr_construct(struct spdk_nvme_ctrlr *ctrlr) static void nvme_ctrlr_init_cap(struct spdk_nvme_ctrlr *ctrlr) { - nvme_ctrlr_get_cap(ctrlr, &ctrlr->cap); - if (ctrlr->cap.bits.ams & SPDK_NVME_CAP_AMS_WRR) { ctrlr->flags |= SPDK_NVME_CTRLR_WRR_SUPPORTED; } diff --git a/lib/nvme/nvme_internal.h b/lib/nvme/nvme_internal.h index 87d2b8d27..bf8711c21 100644 --- a/lib/nvme/nvme_internal.h +++ b/lib/nvme/nvme_internal.h @@ -573,6 +573,11 @@ enum nvme_ctrlr_state { */ NVME_CTRLR_STATE_READ_CAP, + /** + * Waiting for Capabilities (CAP) register to be read. + */ + NVME_CTRLR_STATE_READ_CAP_WAIT_FOR_CAP, + /** * Check EN to prepare for controller initialization. */