Commit 16eee6e2 authored by Cunyin Chang's avatar Cunyin Chang
Browse files

spdk: Add new API to check if given feature supported.



1 Add new API nvme_ctrlr_is_feature_supported().
2 Add unit test for new API.

Change-Id: Ia6d8710755c3b13984fca9d56700efe043be1402
Signed-off-by: default avatarCunyin Chang <cunyin.chang@intel.com>
parent cbcfe37a
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -116,6 +116,15 @@ uint32_t nvme_ctrlr_get_num_ns(struct nvme_controller *ctrlr);
 */
bool nvme_ctrlr_is_log_page_supported(struct nvme_controller *ctrlr, uint8_t log_page);

/**
 * \brief Determine if a particular feature is supported by the given NVMe controller.
 *
 * This function is thread safe and can be called at any point after nvme_attach().
 *
 * \sa nvme_ctrlr_cmd_get_feature()
 */
bool nvme_ctrlr_is_feature_supported(struct nvme_controller *ctrlr, uint8_t feature_code);

/**
 * Signature for callback function invoked when a command is completed.
 *
+2 −0
Original line number Diff line number Diff line
@@ -449,6 +449,8 @@ enum nvme_feature {
	NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION = 0x09,
	NVME_FEAT_WRITE_ATOMICITY		= 0x0A,
	NVME_FEAT_ASYNC_EVENT_CONFIGURATION	= 0x0B,
	NVME_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION	= 0x0C,
	NVME_FEAT_HOST_MEM_BUFFER		= 0x0D,
	/* 0x0C-0x7F - reserved */
	NVME_FEAT_SOFTWARE_PROGRESS_MARKER	= 0x80,
	/* 0x81-0xBF - command set specific */
+50 −0
Original line number Diff line number Diff line
@@ -113,6 +113,47 @@ nvme_ctrlr_set_supported_log_pages(struct nvme_controller *ctrlr)
	}
}

static void
nvme_ctrlr_set_intel_supported_features(struct nvme_controller *ctrlr)
{
	ctrlr->feature_supported[NVME_INTEL_FEAT_MAX_LBA] = true;
	ctrlr->feature_supported[NVME_INTEL_FEAT_NATIVE_MAX_LBA] = true;
	ctrlr->feature_supported[NVME_INTEL_FEAT_POWER_GOVERNOR_SETTING] = true;
	ctrlr->feature_supported[NVME_INTEL_FEAT_SMBUS_ADDRESS] = true;
	ctrlr->feature_supported[NVME_INTEL_FEAT_LED_PATTERN] = true;
	ctrlr->feature_supported[NVME_INTEL_FEAT_RESET_TIMED_WORKLOAD_COUNTERS] = true;
	ctrlr->feature_supported[NVME_INTEL_FEAT_LATENCY_TRACKING] = true;
}

static void
nvme_ctrlr_set_supported_features(struct nvme_controller *ctrlr)
{
	memset(ctrlr->feature_supported, 0, sizeof(ctrlr->feature_supported));
	/* Mandatory features */
	ctrlr->feature_supported[NVME_FEAT_ARBITRATION] = true;
	ctrlr->feature_supported[NVME_FEAT_POWER_MANAGEMENT] = true;
	ctrlr->feature_supported[NVME_FEAT_TEMPERATURE_THRESHOLD] = true;
	ctrlr->feature_supported[NVME_FEAT_ERROR_RECOVERY] = true;
	ctrlr->feature_supported[NVME_FEAT_NUMBER_OF_QUEUES] = true;
	ctrlr->feature_supported[NVME_FEAT_INTERRUPT_COALESCING] = true;
	ctrlr->feature_supported[NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION] = true;
	ctrlr->feature_supported[NVME_FEAT_WRITE_ATOMICITY] = true;
	ctrlr->feature_supported[NVME_FEAT_ASYNC_EVENT_CONFIGURATION] = true;
	/* Optional features */
	if (ctrlr->cdata.vwc.present) {
		ctrlr->feature_supported[NVME_FEAT_VOLATILE_WRITE_CACHE] = true;
	}
	if (ctrlr->cdata.apsta.supported) {
		ctrlr->feature_supported[NVME_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION] = true;
	}
	if (ctrlr->cdata.hmpre) {
		ctrlr->feature_supported[NVME_FEAT_HOST_MEM_BUFFER] = true;
	}
	if (ctrlr->cdata.vid == PCI_VENDOR_ID_INTEL) {
		nvme_ctrlr_set_intel_supported_features(ctrlr);
	}
}

static int
nvme_ctrlr_construct_admin_qpair(struct nvme_controller *ctrlr)
{
@@ -693,6 +734,7 @@ nvme_ctrlr_start(struct nvme_controller *ctrlr)
	}

	nvme_ctrlr_set_supported_log_pages(ctrlr);
	nvme_ctrlr_set_supported_features(ctrlr);
	return 0;
}

@@ -863,3 +905,11 @@ nvme_ctrlr_is_log_page_supported(struct nvme_controller *ctrlr, uint8_t log_page
	SPDK_STATIC_ASSERT(sizeof(ctrlr->log_page_supported) == 256, "log_page_supported size mismatch");
	return ctrlr->log_page_supported[log_page];
}

bool
nvme_ctrlr_is_feature_supported(struct nvme_controller *ctrlr, uint8_t feature_code)
{
	/* No bounds check necessary, since feature_code is uint8_t and feature_supported has 256 entries */
	SPDK_STATIC_ASSERT(sizeof(ctrlr->feature_supported) == 256, "feature_supported size mismatch");
	return ctrlr->feature_supported[feature_code];
}
+3 −0
Original line number Diff line number Diff line
@@ -299,6 +299,9 @@ struct nvme_controller {
	/** All the log pages supported */
	bool				log_page_supported[256];

	/** All the features supported */
	bool				feature_supported[256];

	/* Opaque handle to associated PCI device. */
	void				*devhandle;

+24 −0
Original line number Diff line number Diff line
@@ -225,6 +225,28 @@ test_nvme_ctrlr_construct_intel_support_log_page_list(void)
	CU_ASSERT(res == false);
}

static void
test_nvme_ctrlr_set_supported_features(void)
{
	bool	res;
	struct nvme_controller			ctrlr = {};

	/* set a invalid vendor id */
	ctrlr.cdata.vid = 0xFFFF;
	nvme_ctrlr_set_supported_features(&ctrlr);
	res = nvme_ctrlr_is_feature_supported(&ctrlr, NVME_FEAT_ARBITRATION);
	CU_ASSERT(res == true);
	res = nvme_ctrlr_is_feature_supported(&ctrlr, NVME_INTEL_FEAT_MAX_LBA);
	CU_ASSERT(res == false);

	ctrlr.cdata.vid = PCI_VENDOR_ID_INTEL;
	nvme_ctrlr_set_supported_features(&ctrlr);
	res = nvme_ctrlr_is_feature_supported(&ctrlr, NVME_FEAT_ARBITRATION);
	CU_ASSERT(res == true);
	res = nvme_ctrlr_is_feature_supported(&ctrlr, NVME_INTEL_FEAT_MAX_LBA);
	CU_ASSERT(res == true);
}

int main(int argc, char **argv)
{
	CU_pSuite	suite = NULL;
@@ -244,6 +266,8 @@ int main(int argc, char **argv)
		CU_add_test(suite, "test nvme_ctrlr function nvme_ctrlr_fail", test_nvme_ctrlr_fail) == NULL
		|| CU_add_test(suite, "test nvme ctrlr function nvme_ctrlr_construct_intel_support_log_page_list",
			       test_nvme_ctrlr_construct_intel_support_log_page_list) == NULL
		|| CU_add_test(suite, "test nvme ctrlr function nvme_ctrlr_set_supported_features",
			       test_nvme_ctrlr_set_supported_features) == NULL
	) {
		CU_cleanup_registry();
		return CU_get_error();