diff --git a/examples/nvme/identify/identify.c b/examples/nvme/identify/identify.c index 09bea410d..74d2e3681 100644 --- a/examples/nvme/identify/identify.c +++ b/examples/nvme/identify/identify.c @@ -177,7 +177,7 @@ get_zns_zone_report_completion(void *cb_arg, const struct spdk_nvme_cpl *cpl) } static int -get_feature(struct spdk_nvme_ctrlr *ctrlr, uint8_t fid, uint32_t nsid) +get_feature(struct spdk_nvme_ctrlr *ctrlr, uint8_t fid, uint32_t cdw11, uint32_t nsid) { struct spdk_nvme_cmd cmd = {}; struct feature *feature = &features[fid]; @@ -186,6 +186,7 @@ get_feature(struct spdk_nvme_ctrlr *ctrlr, uint8_t fid, uint32_t nsid) cmd.opc = SPDK_NVME_OPC_GET_FEATURES; cmd.cdw10_bits.get_features.fid = fid; + cmd.cdw11 = cdw11; cmd.nsid = nsid; return spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, &cmd, NULL, 0, get_feature_completion, feature); @@ -196,6 +197,7 @@ get_features(struct spdk_nvme_ctrlr *ctrlr, uint8_t *features_to_get, size_t num uint32_t nsid) { size_t i; + uint32_t cdw11; /* Submit only one GET FEATURES at a time. There is a known issue #1799 * with Google Cloud Platform NVMe SSDs that do not handle overlapped @@ -203,11 +205,25 @@ get_features(struct spdk_nvme_ctrlr *ctrlr, uint8_t *features_to_get, size_t num */ outstanding_commands = 0; for (i = 0; i < num_features; i++) { + cdw11 = 0; if (!spdk_nvme_ctrlr_is_ocssd_supported(ctrlr) && features_to_get[i] == SPDK_OCSSD_FEAT_MEDIA_FEEDBACK) { continue; } - if (get_feature(ctrlr, features_to_get[i], nsid) == 0) { + if (features_to_get[i] == SPDK_NVME_FEAT_FDP) { + const struct spdk_nvme_ctrlr_data *cdata = spdk_nvme_ctrlr_get_data(ctrlr); + struct spdk_nvme_ns *ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid); + const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns); + + if (!cdata->ctratt.fdps) { + continue; + } else { + cdw11 = nsdata->endgid; + /* Endurance group scope */ + nsid = 0; + } + } + if (get_feature(ctrlr, features_to_get[i], cdw11, nsid) == 0) { outstanding_commands++; } else { printf("get_feature(0x%02X) failed to submit command\n", features_to_get[i]); @@ -239,6 +255,7 @@ get_ns_features(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid) { uint8_t features_to_get[] = { SPDK_NVME_FEAT_ERROR_RECOVERY, + SPDK_NVME_FEAT_FDP, }; get_features(ctrlr, features_to_get, SPDK_COUNTOF(features_to_get), nsid); @@ -1118,6 +1135,20 @@ print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns) } printf("\n"); + if (cdata->ctratt.fdps) { + union spdk_nvme_feat_fdp_cdw12 fdp_res; + + if (features[SPDK_NVME_FEAT_FDP].valid) { + fdp_res.raw = features[SPDK_NVME_FEAT_FDP].result; + + printf("Get Feature FDP:\n"); + printf("================\n"); + printf(" Enabled: %s\n", + fdp_res.bits.fdpe ? "Yes" : "No"); + printf(" FDP configuration index: %u\n\n", fdp_res.bits.fdpci); + } + } + if (spdk_nvme_ctrlr_is_ocssd_supported(ctrlr)) { get_ocssd_geometry(ns, &geometry_data); print_ocssd_geometry(&geometry_data); diff --git a/include/spdk/nvme_spec.h b/include/spdk/nvme_spec.h index ec9efeeaa..f2d138eef 100644 --- a/include/spdk/nvme_spec.h +++ b/include/spdk/nvme_spec.h @@ -1025,6 +1025,63 @@ union spdk_nvme_feat_reservation_persistence { }; SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_feat_reservation_persistence) == 4, "Incorrect size"); +/** + * Data used by Set Features/Get Features \ref SPDK_NVME_FEAT_FDP + */ +union spdk_nvme_feat_fdp_cdw11 { + uint32_t raw; + struct { + /* Endurance Group Identifier */ + uint32_t endgid : 16; + uint32_t reserved : 16; + } bits; +}; +SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_feat_fdp_cdw11) == 4, "Incorrect size"); + +/** + * Data used by Set Features/Get Features \ref SPDK_NVME_FEAT_FDP + */ +union spdk_nvme_feat_fdp_cdw12 { + uint32_t raw; + struct { + /* Flexible Data Placement Enable */ + uint32_t fdpe : 1; + uint32_t reserved1 : 7; + /* Flexible Data Placement Configuration Index */ + uint32_t fdpci : 8; + uint32_t reserved2 : 16; + } bits; +}; +SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_feat_fdp_cdw12) == 4, "Incorrect size"); + +/** + * Data used by Set Features/Get Features \ref SPDK_NVME_FEAT_FDP_EVENTS + */ +union spdk_nvme_feat_fdp_events_cdw11 { + uint32_t raw; + struct { + /* Placement Handle associated with RUH */ + uint32_t phndl : 16; + /* Number of FDP event types in data buffer */ + uint32_t noet : 8; + uint32_t reserved : 8; + } bits; +}; +SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_feat_fdp_events_cdw11) == 4, "Incorrect size"); + +/** + * Data used by Set Feature \ref SPDK_NVME_FEAT_FDP_EVENTS + */ +union spdk_nvme_feat_fdp_events_cdw12 { + uint32_t raw; + struct { + /* FDP Event Enable */ + uint32_t fdpee : 1; + uint32_t reserved1 : 31; + } bits; +}; +SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_feat_fdp_events_cdw12) == 4, "Incorrect size"); + union spdk_nvme_cmd_cdw10 { uint32_t raw; struct { @@ -1213,6 +1270,8 @@ union spdk_nvme_cmd_cdw11 { union spdk_nvme_feat_host_identifier feat_host_identifier; union spdk_nvme_feat_reservation_notification_mask feat_rsv_notification_mask; union spdk_nvme_feat_reservation_persistence feat_rsv_persistence; + union spdk_nvme_feat_fdp_cdw11 feat_fdp_cdw11; + union spdk_nvme_feat_fdp_events_cdw11 feat_fdp_events_cdw11; struct { /* Attribute – Integral Dataset for Read */ @@ -1249,6 +1308,9 @@ union spdk_nvme_cmd_cdw12 { /* Limited Retry */ uint32_t lr : 1; } copy; + + union spdk_nvme_feat_fdp_cdw12 feat_fdp_cdw12; + union spdk_nvme_feat_fdp_events_cdw12 feat_fdp_events_cdw12; }; SPDK_STATIC_ASSERT(sizeof(union spdk_nvme_cmd_cdw12) == 4, "Incorrect size"); @@ -1664,6 +1726,25 @@ struct __attribute__((packed)) spdk_nvme_host_behavior { }; SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_host_behavior) == 512, "Incorrect size"); +/** + * Supported FDP event descriptor + */ +struct spdk_nvme_fdp_event_desc { + /* FDP Event type */ + uint8_t fdp_etype; + + /* FDP event type attributes */ + union { + uint8_t raw; + struct { + /* FDP event enabled */ + uint8_t fdp_ee : 1; + uint8_t reserved : 7; + } bits; + } fdpeta; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_fdp_event_desc) == 2, "Incorrect size"); + enum spdk_nvme_feat { /* 0x00 - reserved */ @@ -1711,8 +1792,22 @@ enum spdk_nvme_feat { SPDK_NVME_FEAT_ENDURANCE_GROUP_EVENT = 0x18, SPDK_NVME_FEAT_IO_COMMAND_SET_PROFILE = 0x19, SPDK_NVME_FEAT_SPINUP_CONTROL = 0x1A, - /* 0x1B-0x77 - reserved */ + /* 0x1B-0x1C - reserved */ + /** + * cdw11 layout defined by \ref spdk_nvme_feat_fdp_cdw11 + * cdw12 layout defined by \ref spdk_nvme_feat_fdp_cdw12 + */ + SPDK_NVME_FEAT_FDP = 0x1D, + + /** + * cdw11 layout defined by \ref spdk_nvme_feat_fdp_events_cdw11 + * cdw12 layout defined by \ref spdk_nvme_feat_fdp_events_cdw12 + * data layout defined by \ref spdk_nvme_fdp_event_desc + */ + SPDK_NVME_FEAT_FDP_EVENTS = 0x1E, + + /* 0x1F-0x77 - reserved */ /* 0x78-0x7C - NVMe-MI features */ SPDK_NVME_FEAT_ENHANCED_CONTROLLER_METADATA = 0x7D, SPDK_NVME_FEAT_CONTROLLER_METADATA = 0x7E,