NVME_LBART_ATTRIB_HIDE = 1 << 1,
};
+struct nvme_plm_config {
+ __u16 enable_event;
+ __u8 rsvd2[30];
+ __u64 dtwin_reads_thresh;
+ __u64 dtwin_writes_thresh;
+ __u64 dtwin_time_thresh;
+ __u8 rsvd56[456];
+};
+
struct nvme_reservation_status {
__le32 gen;
__u8 rtype;
NVME_FEAT_HOST_MEM_BUF = 0x0d,
NVME_FEAT_TIMESTAMP = 0x0e,
NVME_FEAT_KATO = 0x0f,
+ NVME_FEAT_PLM_CONFIG = 0x13,
+ NVME_FEAT_PLM_WINDOW = 0x14,
NVME_FEAT_SW_PROGRESS = 0x80,
NVME_FEAT_HOST_ID = 0x81,
NVME_FEAT_RESV_MASK = 0x82,
}
}
- err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value, cfg.save,
- cfg.data_len, buf, &result);
+ err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value,
+ 0, cfg.save, cfg.data_len, buf, &result);
if (err < 0) {
perror("set-feature");
goto free;
}
int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11,
- __u32 data_len, void *data, __u32 *result)
+ __u32 cdw12, __u32 data_len, void *data, __u32 *result)
{
struct nvme_admin_cmd cmd = {
.opcode = opcode,
.nsid = nsid,
.cdw10 = cdw10,
.cdw11 = cdw11,
+ .cdw11 = cdw12,
.addr = (__u64)(uintptr_t) data,
.data_len = data_len,
};
return err;
}
-int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, bool save,
- __u32 data_len, void *data, __u32 *result)
+int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, __u32 cdw12,
+ bool save, __u32 data_len, void *data, __u32 *result)
{
__u32 cdw10 = fid | (save ? 1 << 31 : 0);
return nvme_feature(fd, nvme_admin_set_features, nsid, cdw10, value,
- data_len, data, result);
+ cdw12, data_len, data, result);
}
int nvme_property(int fd, __u8 fctype, __le32 off, __le64 *value, __u8 attrib)
__u32 cdw10 = fid | sel << 8;
return nvme_feature(fd, nvme_admin_get_features, nsid, cdw10, cdw11,
- data_len, data, result);
+ 0, data_len, data, result);
}
int nvme_format(int fd, __u32 nsid, __u8 lbaf, __u8 ses, __u8 pi,
int nvme_sanitize_log(int fd, struct nvme_sanitize_log_page *sanitize_log);
int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10,
- __u32 cdw11, __u32 data_len, void *data, __u32 *result);
-int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value,
+ __u32 cdw11, __u32 cdw12, __u32 data_len, void *data,
+ __u32 *result);
+int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, __u32 cdw12,
bool save, __u32 data_len, void *data, __u32 *result);
int nvme_get_feature(int fd, __u32 nsid, __u8 fid, __u8 sel,
__u32 cdw11, __u32 data_len, void *data, __u32 *result);
case NVME_FEAT_AUTO_PST: return "Autonomous Power State Transition";
case NVME_FEAT_HOST_MEM_BUF: return "Host Memory Buffer";
case NVME_FEAT_KATO: return "Keep Alive Timer";
+ case NVME_FEAT_PLM_CONFIG: return "Predicatable Latency Mode Config";
+ case NVME_FEAT_PLM_WINDOW: return "Predicatable Latency Mode Window";
case NVME_FEAT_SW_PROGRESS: return "Software Progress";
case NVME_FEAT_HOST_ID: return "Host Identifier";
case NVME_FEAT_RESV_MASK: return "Reservation Notification Mask";
return;
}
+static char *nvme_plm_window(__u32 plm)
+{
+ switch (plm & 0x7) {
+ case 1:
+ return "Deterministic Window (DTWIN)";
+ case 2:
+ return "Non-deterministic Window (NDWIN)";
+ default:
+ return "Reserved";
+ }
+}
+
+static void show_plm_config(struct nvme_plm_config *plmcfg)
+{
+ printf("\tEnable Event :%04x\n", le16_to_cpu(plmcfg->enable_event));
+ printf("\tDTWIN Reads Threshold :%"PRIu64"\n", (uint64_t)le64_to_cpu(plmcfg->dtwin_reads_thresh));
+ printf("\tDTWIN Writes Threshold:%"PRIu64"\n", (uint64_t)le64_to_cpu(plmcfg->dtwin_writes_thresh));
+ printf("\tDTWIN Time Threshold :%"PRIu64"\n", (uint64_t)le64_to_cpu(plmcfg->dtwin_time_thresh));
+}
+
void nvme_feature_show_fields(__u32 fid, unsigned int result, unsigned char *buf)
{
__u8 field;
case NVME_FEAT_SW_PROGRESS:
printf("\tPre-boot Software Load Count (PBSLC): %u\n", result & 0x000000ff);
break;
+ case NVME_FEAT_PLM_CONFIG:
+ printf("\tPredictable Latency Window Enabled: %s\n", result & 0x1 ? "True":"False");
+ show_plm_config((struct nvme_plm_config *)buf);
+ break;
+ case NVME_FEAT_PLM_WINDOW:
+ printf("\tWindow Select: %s", nvme_plm_window(result));
+ break;
case NVME_FEAT_HOST_ID:
ull = buf[7]; ull <<= 8; ull |= buf[6]; ull <<= 8; ull |= buf[5]; ull <<= 8;
ull |= buf[4]; ull <<= 8; ull |= buf[3]; ull <<= 8; ull |= buf[2]; ull <<= 8;
if (cfg.cdw11 & 0x1)
cfg.data_len = 16;
break;
+ case NVME_FEAT_PLM_CONFIG:
+ cfg.data_len = 512;
+ break;
}
if (cfg.sel == 3)
"Use get-feature to determine which Features are supported by "\
"the controller and are saveable/changeable.";
const char *namespace_id = "desired namespace";
- const char *feature_id = "hex feature name (required)";
+ const char *feature_id = "feature identifier (required)";
const char *data_len = "buffer length if data required";
const char *data = "optional file for feature data (default stdin)";
const char *value = "new value of feature (required)";
+ const char *cdw12 = "feature cdw12, if used";
const char *save = "specifies that the controller shall save the attribute";
int err;
__u32 result;
__u32 namespace_id;
__u32 feature_id;
__u32 value;
+ __u32 cdw12;
__u32 data_len;
int save;
};
{"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id},
{"feature-id", 'f', "NUM", CFG_POSITIVE, &cfg.feature_id, required_argument, feature_id},
{"value", 'v', "NUM", CFG_POSITIVE, &cfg.value, required_argument, value},
+ {"cdw12", 'c', "NUM", CFG_POSITIVE, &cfg.cdw12, required_argument, cdw12},
{"data-len", 'l', "NUM", CFG_POSITIVE, &cfg.data_len, required_argument, data_len},
{"data", 'd', "FILE", CFG_STRING, &cfg.file, required_argument, data},
{"save", 's', "", CFG_NONE, &cfg.save, no_argument, save},
}
}
- err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value, cfg.save,
- cfg.data_len, buf, &result);
+ err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value,
+ cfg.cdw12, cfg.save, cfg.data_len, buf, &result);
if (err < 0) {
perror("set-feature");
} else if (!err) {