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: Cunyin Chang <cunyin.chang@intel.com>
This commit is contained in:
Cunyin Chang 2016-01-25 13:04:23 +08:00
parent cbcfe37a56
commit 16eee6e20e
5 changed files with 88 additions and 0 deletions

View File

@ -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.
*

View File

@ -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 */

View File

@ -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];
}

View File

@ -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;

View File

@ -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();