Commit 38d59d8b authored by Niklas Cassel's avatar Niklas Cassel Committed by Tomasz Zawadzki
Browse files

nvme: add function to check if controller supports zone append



Zone append is an optional command in the Zoned Namespace Command Set.
Add a convenience function to check if the controller supports the zone
append command.

The ratified NVMe TP 4056 added a CSI field (in cdw14) to the Get Log Page
command. However, since there already exist two public functions to get a
log page (spdk_nvme_ctrlr_cmd_get_log_page() and
spdk_nvme_ctrlr_cmd_get_log_page_ext()), avoid creating a third one for
now, since nvme_ctrlr_get_zns_cmd_and_effects_log() itself can leverage
one of the existing public functions.

Signed-off-by: default avatarNiklas Cassel <niklas.cassel@wdc.com>
Change-Id: I99516dbac8db6714488b4d6cabe64c27f46d6153
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5078


Community-CI: Broadcom CI
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
parent 35596d34
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -425,6 +425,7 @@ enum spdk_nvme_ctrlr_flags {
	SPDK_NVME_CTRLR_WRR_SUPPORTED			= 1 << 2, /**< Weighted Round Robin is supported */
	SPDK_NVME_CTRLR_COMPARE_AND_WRITE_SUPPORTED	= 1 << 3, /**< Compare and write fused operations supported */
	SPDK_NVME_CTRLR_SGL_REQUIRES_DWORD_ALIGNMENT	= 1 << 4, /**< Dword alignment is required for SGL */
	SPDK_NVME_CTRLR_ZONE_APPEND_SUPPORTED		= 1 << 5, /**< Zone Append is supported (within Zoned Namespaces) */
};

/**
+71 −1
Original line number Diff line number Diff line
@@ -1160,6 +1160,10 @@ nvme_ctrlr_state_string(enum nvme_ctrlr_state state)
		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_GET_ZNS_CMD_EFFECTS_LOG:
		return "get zns cmd and effects log page";
	case NVME_CTRLR_STATE_WAIT_FOR_GET_ZNS_CMD_EFFECTS_LOG:
		return "wait for get zns cmd and effects log page";
	case NVME_CTRLR_STATE_SET_NUM_QUEUES:
		return "set number of queues";
	case NVME_CTRLR_STATE_WAIT_FOR_SET_NUM_QUEUES:
@@ -1592,6 +1596,64 @@ nvme_ctrlr_identify(struct spdk_nvme_ctrlr *ctrlr)
	return 0;
}

static void
nvme_ctrlr_get_zns_cmd_and_effects_log_done(void *arg, const struct spdk_nvme_cpl *cpl)
{
	struct spdk_nvme_cmds_and_effect_log_page *log_page;
	struct spdk_nvme_ctrlr *ctrlr = arg;

	if (spdk_nvme_cpl_is_error(cpl)) {
		SPDK_ERRLOG("nvme_ctrlr_get_zns_cmd_and_effects_log failed!\n");
		spdk_free(ctrlr->tmp_ptr);
		ctrlr->tmp_ptr = NULL;
		nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_ERROR, NVME_TIMEOUT_INFINITE);
		return;
	}

	log_page = ctrlr->tmp_ptr;

	if (log_page->io_cmds_supported[SPDK_NVME_OPC_ZONE_APPEND].csupp) {
		ctrlr->flags |= SPDK_NVME_CTRLR_ZONE_APPEND_SUPPORTED;
	}
	spdk_free(ctrlr->tmp_ptr);
	ctrlr->tmp_ptr = NULL;

	nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_SET_NUM_QUEUES, ctrlr->opts.admin_timeout_ms);
}

static int
nvme_ctrlr_get_zns_cmd_and_effects_log(struct spdk_nvme_ctrlr *ctrlr)
{
	int rc;

	assert(!ctrlr->tmp_ptr);
	ctrlr->tmp_ptr = spdk_zmalloc(sizeof(struct spdk_nvme_cmds_and_effect_log_page), 64, NULL,
				      SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_SHARE | SPDK_MALLOC_DMA);
	if (!ctrlr->tmp_ptr) {
		rc = -ENOMEM;
		goto error;
	}

	nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_WAIT_FOR_GET_ZNS_CMD_EFFECTS_LOG,
			     ctrlr->opts.admin_timeout_ms);

	rc = spdk_nvme_ctrlr_cmd_get_log_page_ext(ctrlr, SPDK_NVME_LOG_COMMAND_EFFECTS_LOG,
			0, ctrlr->tmp_ptr, sizeof(struct spdk_nvme_cmds_and_effect_log_page),
			0, 0, 0, SPDK_NVME_CSI_ZNS << 24,
			nvme_ctrlr_get_zns_cmd_and_effects_log_done, ctrlr);
	if (rc != 0) {
		goto error;
	}

	return 0;

error:
	nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_ERROR, NVME_TIMEOUT_INFINITE);
	spdk_free(ctrlr->tmp_ptr);
	ctrlr->tmp_ptr = NULL;
	return rc;
}

static void
nvme_ctrlr_identify_zns_specific_done(void *arg, const struct spdk_nvme_cpl *cpl)
{
@@ -1600,9 +1662,12 @@ nvme_ctrlr_identify_zns_specific_done(void *arg, const struct spdk_nvme_cpl *cpl
	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);
		return;
	}

	nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_SET_NUM_QUEUES,
	nvme_ctrlr_set_state(ctrlr, NVME_CTRLR_STATE_GET_ZNS_CMD_EFFECTS_LOG,
			     ctrlr->opts.admin_timeout_ms);
}

@@ -3053,6 +3118,10 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr)
		rc = nvme_ctrlr_identify_iocs_specific(ctrlr);
		break;

	case NVME_CTRLR_STATE_GET_ZNS_CMD_EFFECTS_LOG:
		rc = nvme_ctrlr_get_zns_cmd_and_effects_log(ctrlr);
		break;

	case NVME_CTRLR_STATE_SET_NUM_QUEUES:
		nvme_ctrlr_update_nvmf_ioccsz(ctrlr);
		rc = nvme_ctrlr_set_num_queues(ctrlr);
@@ -3118,6 +3187,7 @@ nvme_ctrlr_process_init(struct spdk_nvme_ctrlr *ctrlr)

	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:
	case NVME_CTRLR_STATE_WAIT_FOR_SET_NUM_QUEUES:
	case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_ACTIVE_NS:
	case NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_NS:
+13 −0
Original line number Diff line number Diff line
@@ -548,6 +548,16 @@ enum nvme_ctrlr_state {
	 */
	NVME_CTRLR_STATE_WAIT_FOR_IDENTIFY_IOCS_SPECIFIC,

	/**
	 * Get Commands Supported and Effects log page for the Zoned Namespace Command Set.
	 */
	NVME_CTRLR_STATE_GET_ZNS_CMD_EFFECTS_LOG,

	/**
	 * Waiting for the Get Log Page command to be completed.
	 */
	NVME_CTRLR_STATE_WAIT_FOR_GET_ZNS_CMD_EFFECTS_LOG,

	/**
	 * Set Number of Queues of the controller.
	 */
@@ -835,6 +845,9 @@ struct spdk_nvme_ctrlr {

	struct spdk_nvme_ana_page	*ana_log_page;
	uint32_t			ana_log_page_size;

	/* scratchpad pointer that can be used to send data between two NVME_CTRLR_STATEs */
	void				*tmp_ptr;
};

struct spdk_nvme_probe_ctx {
+10 −0
Original line number Diff line number Diff line
@@ -257,6 +257,16 @@ spdk_nvme_ctrlr_cmd_get_log_page(struct spdk_nvme_ctrlr *ctrlr, uint8_t log_page
	return 0;
}

int
spdk_nvme_ctrlr_cmd_get_log_page_ext(struct spdk_nvme_ctrlr *ctrlr, uint8_t log_page,
				     uint32_t nsid, void *payload, uint32_t payload_size,
				     uint64_t offset, uint32_t cdw10, uint32_t cdw11,
				     uint32_t cdw14, spdk_nvme_cmd_cb cb_fn, void *cb_arg)
{
	fake_cpl_sc(cb_fn, cb_arg);
	return 0;
}

int
nvme_qpair_submit_request(struct spdk_nvme_qpair *qpair, struct nvme_request *req)
{