nvme: add new state to get Identify IOCS Specific Controller data structs
Add a new state in the SPDK NVMe state machine in order to fetch I/O Command Set Specific Controller data structures. Right now there is only support for the Zoned Namespace Command Set Specific Identify Controller data structure. The NVM Command Set Specific Identify Controller data structure is all zeroes right now, reserved for future use. The Key Value Command Set Identify Controller data structure is also all zeroes right now, reserved for future use. The new NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC state is added after the NVME_CTRLR_STATE_IDENTIFY state. That way, if support for the Zoned Namespace Command Set is enabled during probing, we will fetch the Zoned Namespace Command Set Specific Identify Controller data structure, regardless if any Zoned Namespaces are attached or not, and no additional steps will be needed once a Zoned Namespace is attached. Since we only have one command set to fetch, avoid creating NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC substates, although that will probably be needed when support for another command set is added. Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com> Change-Id: I95535b09b03b7ef2ee9a11eebdbd28aad66d65ba Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4367 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
parent
a7ddda8166
commit
64563ada5d
@ -90,6 +90,13 @@ nvme_ctrlr_get_cmbsz(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_cmbsz_regist
|
||||
&cmbsz->raw);
|
||||
}
|
||||
|
||||
bool
|
||||
nvme_ctrlr_multi_iocs_enabled(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
return ctrlr->cap.bits.css & SPDK_NVME_CAP_CSS_IOCS &&
|
||||
ctrlr->opts.command_set == SPDK_NVME_CC_CSS_IOCS;
|
||||
}
|
||||
|
||||
/* When the field in spdk_nvme_ctrlr_opts are changed and you change this function, please
|
||||
* also update the nvme_ctrl_opts_init function in nvme_ctrlr.c
|
||||
*/
|
||||
@ -1109,6 +1116,10 @@ nvme_ctrlr_state_string(enum nvme_ctrlr_state state)
|
||||
return "identify controller";
|
||||
case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY:
|
||||
return "wait for identify controller";
|
||||
case NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC:
|
||||
return "identify controller iocs specific";
|
||||
case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_IOCS_SPECIFIC:
|
||||
return "wait for identify controller iocs specific";
|
||||
case NVME_CTRLR_STATE_SET_NUM_QUEUES:
|
||||
return "set number of queues";
|
||||
case NVME_CTRLR_STATE_WAIT_FOR_SET_NUM_QUEUES:
|
||||
@ -1190,6 +1201,19 @@ inf:
|
||||
ctrlr->state_timeout_tsc = NVME_TIMEOUT_INFINITE;
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_ctrlr_free_zns_specific_data(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
spdk_free(ctrlr->cdata_zns);
|
||||
ctrlr->cdata_zns = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_ctrlr_free_iocs_specific_data(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
nvme_ctrlr_free_zns_specific_data(ctrlr);
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_ctrlr_free_doorbell_buffer(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
@ -1346,6 +1370,9 @@ spdk_nvme_ctrlr_reset(struct spdk_nvme_ctrlr *ctrlr)
|
||||
/* Doorbell buffer config is invalid during reset */
|
||||
nvme_ctrlr_free_doorbell_buffer(ctrlr);
|
||||
|
||||
/* I/O Command Set Specific Identify Controller data is invalidated during reset */
|
||||
nvme_ctrlr_free_iocs_specific_data(ctrlr);
|
||||
|
||||
/* Set the state back to INIT to cause a full hardware reset. */
|
||||
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_INIT, NVME_TIMEOUT_INFINITE);
|
||||
|
||||
@ -1494,7 +1521,7 @@ nvme_ctrlr_identify_done(void *arg, const struct spdk_nvme_cpl *cpl)
|
||||
ctrlr->flags |= SPDK_NVME_CTRLR_COMPARE_AND_WRITE_SUPPORTED;
|
||||
}
|
||||
|
||||
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_SET_NUM_QUEUES,
|
||||
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC,
|
||||
ctrlr->opts.admin_timeout_ms);
|
||||
}
|
||||
|
||||
@ -1517,6 +1544,75 @@ nvme_ctrlr_identify(struct spdk_nvme_ctrlr *ctrlr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_ctrlr_identify_zns_specific_done(void *arg, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct spdk_nvme_ctrlr *ctrlr = (struct spdk_nvme_ctrlr *)arg;
|
||||
|
||||
if (spdk_nvme_cpl_is_error(cpl)) {
|
||||
/* no need to print an error, the controller simply does not support ZNS */
|
||||
nvme_ctrlr_free_zns_specific_data(ctrlr);
|
||||
}
|
||||
|
||||
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_SET_NUM_QUEUES,
|
||||
ctrlr->opts.admin_timeout_ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will try to fetch the I/O Command Specific Controller data structure for
|
||||
* each I/O Command Set supported by SPDK.
|
||||
*
|
||||
* If an I/O Command Set is not supported by the controller, "Invalid Field in Command"
|
||||
* will be returned. Since we are fetching in a exploratively way, getting an error back
|
||||
* from the controller should not be treated as fatal.
|
||||
*
|
||||
* I/O Command Sets not supported by SPDK will be skipped (e.g. Key Value Command Set).
|
||||
*
|
||||
* I/O Command Sets without a IOCS specific data structure (i.e. a zero-filled IOCS specific
|
||||
* data structure) will be skipped (e.g. NVM Command Set, Key Value Command Set).
|
||||
*/
|
||||
static int
|
||||
nvme_ctrlr_identify_iocs_specific(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!nvme_ctrlr_multi_iocs_enabled(ctrlr)) {
|
||||
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_SET_NUM_QUEUES,
|
||||
ctrlr->opts.admin_timeout_ms);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since SPDK currently only needs to fetch a single Command Set, keep the code here,
|
||||
* instead of creating multiple NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC substates,
|
||||
* which would require additional functions and complexity for no good reason.
|
||||
*/
|
||||
assert(!ctrlr->cdata_zns);
|
||||
ctrlr->cdata_zns = spdk_zmalloc(sizeof(*ctrlr->cdata_zns), 64, NULL, SPDK_ENV_SOCKET_ID_ANY,
|
||||
SPDK_MALLOC_SHARE | SPDK_MALLOC_DMA);
|
||||
if (!ctrlr->cdata_zns) {
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_IOCS_SPECIFIC,
|
||||
ctrlr->opts.admin_timeout_ms);
|
||||
|
||||
rc = nvme_ctrlr_cmd_identify(ctrlr, SPDK_NVME_IDENTIFY_CTRLR_IOCS, 0, 0, SPDK_NVME_CSI_ZNS,
|
||||
ctrlr->cdata_zns, sizeof(*ctrlr->cdata_zns),
|
||||
nvme_ctrlr_identify_zns_specific_done, ctrlr);
|
||||
if (rc != 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_ERROR, NVME_TIMEOUT_INFINITE);
|
||||
nvme_ctrlr_free_zns_specific_data(ctrlr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
enum nvme_active_ns_state {
|
||||
NVME_ACTIVE_NS_STATE_IDLE,
|
||||
NVME_ACTIVE_NS_STATE_PROCESSING,
|
||||
@ -2783,6 +2879,14 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr)
|
||||
spdk_nvme_qpair_process_completions(ctrlr->adminq, 0);
|
||||
break;
|
||||
|
||||
case NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC:
|
||||
rc = nvme_ctrlr_identify_iocs_specific(ctrlr);
|
||||
break;
|
||||
|
||||
case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_IOCS_SPECIFIC:
|
||||
spdk_nvme_qpair_process_completions(ctrlr->adminq, 0);
|
||||
break;
|
||||
|
||||
case NVME_CTRLR_STATE_SET_NUM_QUEUES:
|
||||
nvme_ctrlr_update_nvmf_ioccsz(ctrlr);
|
||||
rc = nvme_ctrlr_set_num_queues(ctrlr);
|
||||
@ -3005,6 +3109,7 @@ nvme_ctrlr_destruct(struct spdk_nvme_ctrlr *ctrlr)
|
||||
}
|
||||
|
||||
nvme_ctrlr_free_doorbell_buffer(ctrlr);
|
||||
nvme_ctrlr_free_iocs_specific_data(ctrlr);
|
||||
|
||||
if (ctrlr->opts.no_shn_notification) {
|
||||
SPDK_INFOLOG(SPDK_LOG_NVME, "Disable SSD: %s without shutdown notification\n",
|
||||
|
@ -535,6 +535,16 @@ enum nvme_ctrlr_state {
|
||||
*/
|
||||
NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY,
|
||||
|
||||
/**
|
||||
* Get Identify I/O Command Set Specific Controller data structure.
|
||||
*/
|
||||
NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC,
|
||||
|
||||
/**
|
||||
* Waiting for Identify I/O Command Set Specific Controller command to be completed.
|
||||
*/
|
||||
NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_IOCS_SPECIFIC,
|
||||
|
||||
/**
|
||||
* Set Number of Queues of the controller.
|
||||
*/
|
||||
@ -761,6 +771,11 @@ struct spdk_nvme_ctrlr {
|
||||
*/
|
||||
struct spdk_nvme_ctrlr_data cdata;
|
||||
|
||||
/**
|
||||
* Zoned Namespace Command Set Specific Identify Controller data.
|
||||
*/
|
||||
struct spdk_nvme_zns_ctrlr_data *cdata_zns;
|
||||
|
||||
/**
|
||||
* Keep track of active namespaces
|
||||
*/
|
||||
@ -943,6 +958,7 @@ int nvme_ctrlr_submit_admin_request(struct spdk_nvme_ctrlr *ctrlr,
|
||||
int nvme_ctrlr_get_cap(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_cap_register *cap);
|
||||
int nvme_ctrlr_get_vs(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_vs_register *vs);
|
||||
int nvme_ctrlr_get_cmbsz(struct spdk_nvme_ctrlr *ctrlr, union spdk_nvme_cmbsz_register *cmbsz);
|
||||
bool nvme_ctrlr_multi_iocs_enabled(struct spdk_nvme_ctrlr *ctrlr);
|
||||
void nvme_ctrlr_init_cap(struct spdk_nvme_ctrlr *ctrlr, const union spdk_nvme_cap_register *cap,
|
||||
const union spdk_nvme_vs_register *vs);
|
||||
void nvme_ctrlr_disconnect_qpair(struct spdk_nvme_qpair *qpair);
|
||||
|
@ -1986,6 +1986,8 @@ test_nvme_ctrlr_init_set_nvmf_ioccsz(void)
|
||||
|
||||
ctrlr.state = NVME_CTRLR_STATE_IDENTIFY;
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_SET_NUM_QUEUES);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_CONSTRUCT_NS);
|
||||
@ -2000,6 +2002,8 @@ test_nvme_ctrlr_init_set_nvmf_ioccsz(void)
|
||||
|
||||
ctrlr.state = NVME_CTRLR_STATE_IDENTIFY;
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_SET_NUM_QUEUES);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_CONSTRUCT_NS);
|
||||
@ -2016,6 +2020,8 @@ test_nvme_ctrlr_init_set_nvmf_ioccsz(void)
|
||||
|
||||
ctrlr.state = NVME_CTRLR_STATE_IDENTIFY;
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_SET_NUM_QUEUES);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_CONSTRUCT_NS);
|
||||
@ -2032,6 +2038,8 @@ test_nvme_ctrlr_init_set_nvmf_ioccsz(void)
|
||||
|
||||
ctrlr.state = NVME_CTRLR_STATE_IDENTIFY;
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_SET_NUM_QUEUES);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_CONSTRUCT_NS);
|
||||
@ -2048,6 +2056,8 @@ test_nvme_ctrlr_init_set_nvmf_ioccsz(void)
|
||||
|
||||
ctrlr.state = NVME_CTRLR_STATE_IDENTIFY;
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_SET_NUM_QUEUES);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0);
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_CONSTRUCT_NS);
|
||||
@ -2064,6 +2074,8 @@ test_nvme_ctrlr_init_set_num_queues(void)
|
||||
DECLARE_AND_CONSTRUCT_CTRLR();
|
||||
|
||||
ctrlr.state = NVME_CTRLR_STATE_IDENTIFY;
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0); /* -> SET_IDENTIFY_IOCS_SPECIFIC */
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_IDENTIFY_IOCS_SPECIFIC);
|
||||
CU_ASSERT(nvme_ctrlr_process_init(&ctrlr) == 0); /* -> SET_NUM_QUEUES */
|
||||
CU_ASSERT(ctrlr.state == NVME_CTRLR_STATE_SET_NUM_QUEUES);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user