diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/nvmeadm/nvmeadm.c | 164 | ||||
-rw-r--r-- | usr/src/cmd/nvmeadm/nvmeadm.h | 6 | ||||
-rw-r--r-- | usr/src/cmd/nvmeadm/nvmeadm_print.c | 156 | ||||
-rw-r--r-- | usr/src/uts/common/io/nvme/nvme.c | 22 | ||||
-rw-r--r-- | usr/src/uts/common/sys/nvme.h | 27 |
5 files changed, 338 insertions, 37 deletions
diff --git a/usr/src/cmd/nvmeadm/nvmeadm.c b/usr/src/cmd/nvmeadm/nvmeadm.c index f53475db5b..294ef29a0a 100644 --- a/usr/src/cmd/nvmeadm/nvmeadm.c +++ b/usr/src/cmd/nvmeadm/nvmeadm.c @@ -13,6 +13,7 @@ * Copyright 2016 Nexenta Systems, Inc. * Copyright 2017 Joyent, Inc. * Copyright 2019 Western Digital Corporation. + * Copyright 2020 Oxide Computer Company */ /* @@ -75,7 +76,7 @@ struct nvme_feature { uint8_t f_feature; size_t f_bufsize; uint_t f_getflags; - int (*f_get)(int, const nvme_feature_t *, nvme_identify_ctrl_t *); + int (*f_get)(int, const nvme_feature_t *, const nvme_process_arg_t *); void (*f_print)(uint64_t, void *, size_t, nvme_identify_ctrl_t *); }; @@ -106,9 +107,11 @@ static int do_get_logpage_health(int, const nvme_process_arg_t *); static int do_get_logpage_fwslot(int, const nvme_process_arg_t *); static int do_get_logpage(int, const nvme_process_arg_t *); static int do_get_feat_common(int, const nvme_feature_t *, - nvme_identify_ctrl_t *); + const nvme_process_arg_t *); static int do_get_feat_intr_vect(int, const nvme_feature_t *, - nvme_identify_ctrl_t *); + const nvme_process_arg_t *); +static int do_get_feat_temp_thresh(int, const nvme_feature_t *, + const nvme_process_arg_t *); static int do_get_features(int, const nvme_process_arg_t *); static int do_format(int, const nvme_process_arg_t *); static int do_secure_erase(int, const nvme_process_arg_t *); @@ -217,7 +220,7 @@ static const nvme_feature_t features[] = { do_get_feat_common, nvme_print_feat_lba_range }, { "Temperature Threshold", "", NVME_FEAT_TEMPERATURE, 0, NVMEADM_CTRL, - do_get_feat_common, nvme_print_feat_temperature }, + do_get_feat_temp_thresh, nvme_print_feat_temperature }, { "Error Recovery", "", NVME_FEAT_ERROR, 0, NVMEADM_CTRL, do_get_feat_common, nvme_print_feat_error }, @@ -694,7 +697,7 @@ do_get_logpage_health(int fd, const nvme_process_arg_t *npa) return (-1); (void) printf("%s: ", npa->npa_name); - nvme_print_health_log(hlog, npa->npa_idctl); + nvme_print_health_log(hlog, npa->npa_idctl, npa->npa_version); free(hlog); @@ -777,7 +780,7 @@ usage_get_features(const char *c_name) static int do_get_feat_common(int fd, const nvme_feature_t *feat, - nvme_identify_ctrl_t *idctl) + const nvme_process_arg_t *npa) { void *buf = NULL; size_t bufsize = feat->f_bufsize; @@ -788,15 +791,154 @@ do_get_feat_common(int fd, const nvme_feature_t *feat, return (EINVAL); nvme_print(2, feat->f_name, -1, NULL); - feat->f_print(res, buf, bufsize, idctl); + feat->f_print(res, buf, bufsize, npa->npa_idctl); free(buf); return (0); } static int +do_get_feat_temp_thresh_one(int fd, const nvme_feature_t *feat, + const char *label, uint16_t tmpsel, uint16_t thsel, + const nvme_process_arg_t *npa) +{ + uint64_t res; + void *buf = NULL; + size_t bufsize = feat->f_bufsize; + nvme_temp_threshold_t tt; + + tt.r = 0; + tt.b.tt_tmpsel = tmpsel; + tt.b.tt_thsel = thsel; + + if (!nvme_get_feature(fd, feat->f_feature, tt.r, &res, &bufsize, + &buf)) { + return (EINVAL); + } + + feat->f_print(res, (void *)label, 0, npa->npa_idctl); + free(buf); + return (0); +} + +/* + * In NVMe 1.2, the specification allowed for up to 8 sensors to be on the + * device and changed the main device to have a composite temperature sensor. As + * a result, there is a set of thresholds for each sensor. In addition, they + * added both an over-temperature and under-temperature threshold. Since most + * devices don't actually implement all the sensors, we get the health page and + * see which sensors have a non-zero value to determine how to proceed. + */ +static int +do_get_feat_temp_thresh(int fd, const nvme_feature_t *feat, + const nvme_process_arg_t *npa) +{ + int ret; + size_t bufsize = sizeof (nvme_health_log_t); + nvme_health_log_t *hlog; + + nvme_print(2, feat->f_name, -1, NULL); + if ((ret = do_get_feat_temp_thresh_one(fd, feat, + "Composite Over Temp. Threshold", 0, NVME_TEMP_THRESH_OVER, + npa)) != 0) { + return (ret); + } + + if (!NVME_VERSION_ATLEAST(npa->npa_version, 1, 2)) { + return (0); + } + + if ((ret = do_get_feat_temp_thresh_one(fd, feat, + "Composite Under Temp. Threshold", 0, NVME_TEMP_THRESH_UNDER, + npa)) != 0) { + return (ret); + } + + hlog = nvme_get_logpage(fd, NVME_LOGPAGE_HEALTH, &bufsize); + if (hlog == NULL) { + warnx("failed to get health log page, unable to get " + "thresholds for additional sensors"); + return (0); + } + + if (hlog->hl_temp_sensor_1 != 0) { + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 1 Over Temp. Threshold", 1, + NVME_TEMP_THRESH_OVER, npa); + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 1 Under Temp. Threshold", 1, + NVME_TEMP_THRESH_UNDER, npa); + } + + if (hlog->hl_temp_sensor_2 != 0) { + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 2 Over Temp. Threshold", 2, + NVME_TEMP_THRESH_OVER, npa); + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 2 Under Temp. Threshold", 2, + NVME_TEMP_THRESH_UNDER, npa); + } + + if (hlog->hl_temp_sensor_3 != 0) { + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 3 Over Temp. Threshold", 3, + NVME_TEMP_THRESH_OVER, npa); + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 3 Under Temp. Threshold", 3, + NVME_TEMP_THRESH_UNDER, npa); + } + + if (hlog->hl_temp_sensor_4 != 0) { + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 4 Over Temp. Threshold", 4, + NVME_TEMP_THRESH_OVER, npa); + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 4 Under Temp. Threshold", 4, + NVME_TEMP_THRESH_UNDER, npa); + } + + if (hlog->hl_temp_sensor_5 != 0) { + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 5 Over Temp. Threshold", 5, + NVME_TEMP_THRESH_OVER, npa); + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 5 Under Temp. Threshold", 5, + NVME_TEMP_THRESH_UNDER, npa); + } + + if (hlog->hl_temp_sensor_6 != 0) { + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 6 Over Temp. Threshold", 6, + NVME_TEMP_THRESH_OVER, npa); + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 6 Under Temp. Threshold", 6, + NVME_TEMP_THRESH_UNDER, npa); + } + + if (hlog->hl_temp_sensor_7 != 0) { + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 7 Over Temp. Threshold", 7, + NVME_TEMP_THRESH_OVER, npa); + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 7 Under Temp. Threshold", 7, + NVME_TEMP_THRESH_UNDER, npa); + } + + if (hlog->hl_temp_sensor_8 != 0) { + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 8 Over Temp. Threshold", 8, + NVME_TEMP_THRESH_OVER, npa); + (void) do_get_feat_temp_thresh_one(fd, feat, + "Temp. Sensor 8 Under Temp. Threshold", 8, + NVME_TEMP_THRESH_UNDER, npa); + } + free(hlog); + return (0); +} + +static int do_get_feat_intr_vect(int fd, const nvme_feature_t *feat, - nvme_identify_ctrl_t *idctl) + const nvme_process_arg_t *npa) { uint64_t res; uint64_t arg; @@ -814,7 +956,7 @@ do_get_feat_intr_vect(int fd, const nvme_feature_t *feat, == B_FALSE) return (EINVAL); - feat->f_print(res, NULL, 0, idctl); + feat->f_print(res, NULL, 0, npa->npa_idctl); } return (0); @@ -842,7 +984,7 @@ do_get_features(int fd, const nvme_process_arg_t *npa) (feat->f_getflags & NVMEADM_CTRL) == 0)) continue; - (void) feat->f_get(fd, feat, npa->npa_idctl); + (void) feat->f_get(fd, feat, npa); } return (0); @@ -887,7 +1029,7 @@ do_get_features(int fd, const nvme_process_arg_t *npa) header_printed = B_TRUE; } - if (feat->f_get(fd, feat, npa->npa_idctl) != 0) { + if (feat->f_get(fd, feat, npa) != 0) { warnx("unsupported feature: %s", feat->f_name); continue; } diff --git a/usr/src/cmd/nvmeadm/nvmeadm.h b/usr/src/cmd/nvmeadm/nvmeadm.h index a542f98be7..57d237ce57 100644 --- a/usr/src/cmd/nvmeadm/nvmeadm.h +++ b/usr/src/cmd/nvmeadm/nvmeadm.h @@ -12,6 +12,7 @@ /* * Copyright 2016 Nexenta Systems, Inc. * Copyright 2019 Western Digital Corporation + * Copyright 2020 Oxide Computer Company */ #ifndef _NVMEADM_H @@ -29,14 +30,15 @@ extern int verbose; extern int debug; /* printing functions */ -extern void nvme_print(int, char *, int, const char *, ...); +extern void nvme_print(int, const char *, int, const char *, ...); extern void nvme_print_ctrl_summary(nvme_identify_ctrl_t *, nvme_version_t *); extern void nvme_print_nsid_summary(nvme_identify_nsid_t *); extern void nvme_print_identify_ctrl(nvme_identify_ctrl_t *, nvme_capabilities_t *, nvme_version_t *); extern void nvme_print_identify_nsid(nvme_identify_nsid_t *, nvme_version_t *); extern void nvme_print_error_log(int, nvme_error_log_entry_t *); -extern void nvme_print_health_log(nvme_health_log_t *, nvme_identify_ctrl_t *); +extern void nvme_print_health_log(nvme_health_log_t *, nvme_identify_ctrl_t *, + nvme_version_t *); extern void nvme_print_fwslot_log(nvme_fwslot_log_t *); extern void nvme_print_feat_arbitration(uint64_t, void *, size_t, diff --git a/usr/src/cmd/nvmeadm/nvmeadm_print.c b/usr/src/cmd/nvmeadm/nvmeadm_print.c index 0eb81a4e91..b43836326f 100644 --- a/usr/src/cmd/nvmeadm/nvmeadm_print.c +++ b/usr/src/cmd/nvmeadm/nvmeadm_print.c @@ -12,6 +12,7 @@ /* * Copyright 2016 Nexenta Systems, Inc. * Copyright 2019 Western Digital Corporation + * Copyright 2020 Oxide Computer Company */ /* @@ -32,11 +33,15 @@ static int nvme_strlen(const char *, int); -static void nvme_print_str(int, char *, int, const char *, int); -static void nvme_print_double(int, char *, double, int, char *); -static void nvme_print_uint64(int, char *, uint64_t, const char *, char *); -static void nvme_print_uint128(int, char *, nvme_uint128_t, char *, int, int); -static void nvme_print_bit(int, char *, int, char *, char *); +static void nvme_print_str(int, const char *, int, const char *, int); +static void nvme_print_double(int, const char *, double, int, const char *); +static void nvme_print_int64(int, const char *, uint64_t, const char *, + const char *); +static void nvme_print_uint64(int, const char *, uint64_t, const char *, + const char *); +static void nvme_print_uint128(int, const char *, nvme_uint128_t, const char *, + int, int); +static void nvme_print_bit(int, const char *, int, const char *, const char *); #define ARRAYSIZE(x) (sizeof (x) / sizeof (*(x))) @@ -163,7 +168,7 @@ static const char *lba_range_types[] = { #define NVME_PRINT_ALIGN 43 void -nvme_print(int indent, char *name, int index, const char *fmt, ...) +nvme_print(int indent, const char *name, int index, const char *fmt, ...) { int align = NVME_PRINT_ALIGN - (indent + strlen(name) + 1); va_list ap; @@ -209,7 +214,8 @@ nvme_strlen(const char *str, int len) * nvme_print_str -- print a string up to the specified length */ static void -nvme_print_str(int indent, char *name, int index, const char *value, int len) +nvme_print_str(int indent, const char *name, int index, const char *value, + int len) { if (len == 0) len = strlen(value); @@ -222,7 +228,8 @@ nvme_print_str(int indent, char *name, int index, const char *value, int len) * optional unit */ static void -nvme_print_double(int indent, char *name, double value, int places, char *unit) +nvme_print_double(int indent, const char *name, double value, int places, + const char *unit) { if (unit == NULL) unit = ""; @@ -231,12 +238,12 @@ nvme_print_double(int indent, char *name, double value, int places, char *unit) } /* - * nvme_print_uint64 -- print uint64_t with optional unit in decimal or another + * nvme_print_int64 -- print int64_t with optional unit in decimal or another * format specified */ static void -nvme_print_uint64(int indent, char *name, uint64_t value, const char *fmt, - char *unit) +nvme_print_int64(int indent, const char *name, uint64_t value, const char *fmt, + const char *unit) { char *tmp_fmt; @@ -247,6 +254,43 @@ nvme_print_uint64(int indent, char *name, uint64_t value, const char *fmt, fmt = "%"PRId64; if (asprintf(&tmp_fmt, "%s%%s", fmt) < 0) + err(-1, "nvme_print_int64()"); + + nvme_print(indent, name, -1, tmp_fmt, value, unit); + + free(tmp_fmt); +} + +/* + * nvme_print_temp -- The NVMe specification passes most temperature values as + * uint16_t values that are encoded in kelvin. This converts them in one place + * to Celsius. + */ +static void +nvme_print_temp(int indent, const char *name, uint16_t value) +{ + int64_t temp = (int64_t)value; + temp -= 273; + nvme_print_int64(indent, name, temp, NULL, "C"); +} + +/* + * nvme_print_uint64 -- print uint64_t with optional unit in decimal or another + * format specified + */ +static void +nvme_print_uint64(int indent, const char *name, uint64_t value, const char *fmt, + const char *unit) +{ + char *tmp_fmt; + + if (unit == NULL) + unit = ""; + + if (fmt == NULL) + fmt = "%"PRIu64; + + if (asprintf(&tmp_fmt, "%s%%s", fmt) < 0) err(-1, "nvme_print_uint64()"); nvme_print(indent, name, -1, tmp_fmt, value, unit); @@ -259,8 +303,8 @@ nvme_print_uint64(int indent, char *name, uint64_t value, const char *fmt, * binary and/or decimal shifting */ static void -nvme_print_uint128(int indent, char *name, nvme_uint128_t value, char *unit, - int scale_bits, int scale_tens) +nvme_print_uint128(int indent, const char *name, nvme_uint128_t value, + const char *unit, int scale_bits, int scale_tens) { const char hex[] = "0123456789abcdef"; uint8_t o[(128 + scale_bits) / 3]; @@ -360,7 +404,8 @@ nvme_print_uint128(int indent, char *name, nvme_uint128_t value, char *unit, * nvme_print_bit -- print a bit with optional names for both states */ static void -nvme_print_bit(int indent, char *name, int value, char *s_true, char *s_false) +nvme_print_bit(int indent, const char *name, int value, const char *s_true, + const char *s_false) { if (s_true == NULL) s_true = "supported"; @@ -784,7 +829,8 @@ nvme_print_error_log(int nlog, nvme_error_log_entry_t *elog) * of the log if verbose is set. */ void -nvme_print_health_log(nvme_health_log_t *hlog, nvme_identify_ctrl_t *idctl) +nvme_print_health_log(nvme_health_log_t *hlog, nvme_identify_ctrl_t *idctl, + nvme_version_t *vers) { nvme_print(0, "SMART/Health Information", -1, NULL); nvme_print(2, "Critical Warnings", -1, NULL); @@ -800,8 +846,7 @@ nvme_print_health_log(nvme_health_log_t *hlog, nvme_identify_ctrl_t *idctl) nvme_print_bit(4, "Volatile Memory Backup", hlog->hl_crit_warn.cw_volatile, "failed", "OK"); - nvme_print_uint64(2, "Temperature", - hlog->hl_temp - 273, NULL, "C"); + nvme_print_temp(2, "Temperature", hlog->hl_temp); nvme_print_uint64(2, "Available Spare Capacity", hlog->hl_avail_spare, NULL, "%"); @@ -817,7 +862,7 @@ nvme_print_health_log(nvme_health_log_t *hlog, nvme_identify_ctrl_t *idctl) /* * The following two fields are in 1000 512 byte units. Convert that to - * GB by doing binary shifts (9 left and 30 right) and muliply by 10^3. + * GB by doing binary shifts (9 left and 30 right) and multiply by 10^3. */ nvme_print_uint128(2, "Data Read", hlog->hl_data_read, "GB", 30 - 9, 3); @@ -840,6 +885,76 @@ nvme_print_health_log(nvme_health_log_t *hlog, nvme_identify_ctrl_t *idctl) hlog->hl_media_errors, NULL, 0, 0); nvme_print_uint128(2, "Errors Logged", hlog->hl_errors_logged, NULL, 0, 0); + + if (!NVME_VERSION_ATLEAST(vers, 1, 2)) { + return; + } + + if (idctl->ap_wctemp != 0) { + nvme_print_uint64(2, "Warning Composite Temperature Time", + hlog->hl_warn_temp_time, NULL, "min"); + } + + if (idctl->ap_cctemp != 0) { + nvme_print_uint64(2, "Critical Composite Temperature Time", + hlog->hl_crit_temp_time, NULL, "min"); + } + + if (hlog->hl_temp_sensor_1 != 0) { + nvme_print_temp(2, "Temperature Sensor 1", + hlog->hl_temp_sensor_1); + } + + if (hlog->hl_temp_sensor_2 != 0) { + nvme_print_temp(2, "Temperature Sensor 2", + hlog->hl_temp_sensor_2); + } + + if (hlog->hl_temp_sensor_3 != 0) { + nvme_print_temp(2, "Temperature Sensor 3", + hlog->hl_temp_sensor_3); + } + + if (hlog->hl_temp_sensor_4 != 0) { + nvme_print_temp(2, "Temperature Sensor 4", + hlog->hl_temp_sensor_4); + } + + if (hlog->hl_temp_sensor_5 != 0) { + nvme_print_temp(2, "Temperature Sensor 5", + hlog->hl_temp_sensor_5); + } + + if (hlog->hl_temp_sensor_6 != 0) { + nvme_print_temp(2, "Temperature Sensor 6", + hlog->hl_temp_sensor_6); + } + + if (hlog->hl_temp_sensor_7 != 0) { + nvme_print_temp(2, "Temperature Sensor 7", + hlog->hl_temp_sensor_7); + } + + if (hlog->hl_temp_sensor_8 != 0) { + nvme_print_temp(2, "Temperature Sensor 8", + hlog->hl_temp_sensor_8); + } + + if (!NVME_VERSION_ATLEAST(vers, 1, 3)) { + return; + } + + nvme_print_uint64(2, "Thermal Management Temp 1 Transition Count", + hlog->hl_tmtemp_1_tc, NULL, NULL); + + nvme_print_uint64(2, "Thermal Management Temp 2 Transition Count", + hlog->hl_tmtemp_2_tc, NULL, NULL); + + nvme_print_uint64(2, "Time for Thermal Management Temp 1", + hlog->hl_tmtemp_1_time, NULL, "sec"); + + nvme_print_uint64(2, "Time for Thermal Management Temp 2", + hlog->hl_tmtemp_2_time, NULL, "sec"); } /* @@ -970,14 +1085,13 @@ void nvme_print_feat_temperature(uint64_t res, void *b, size_t s, nvme_identify_ctrl_t *id) { - _NOTE(ARGUNUSED(b)); _NOTE(ARGUNUSED(s)); _NOTE(ARGUNUSED(id)); nvme_temp_threshold_t tt; + char *label = b; tt.r = (uint32_t)res; - nvme_print_uint64(4, "Temperature Threshold", tt.b.tt_tmpth - 273, - NULL, "C"); + nvme_print_temp(4, label, tt.b.tt_tmpth); } void diff --git a/usr/src/uts/common/io/nvme/nvme.c b/usr/src/uts/common/io/nvme/nvme.c index ae7f88c217..4a73f9f337 100644 --- a/usr/src/uts/common/io/nvme/nvme.c +++ b/usr/src/uts/common/io/nvme/nvme.c @@ -4249,7 +4249,6 @@ nvme_ioctl_get_features(nvme_t *nvme, int nsid, nvme_ioctl_t *nioc, switch (feature) { case NVME_FEAT_ARBITRATION: case NVME_FEAT_POWER_MGMT: - case NVME_FEAT_TEMPERATURE: case NVME_FEAT_ERROR: case NVME_FEAT_NQUEUES: case NVME_FEAT_INTR_COAL: @@ -4260,6 +4259,27 @@ nvme_ioctl_get_features(nvme_t *nvme, int nsid, nvme_ioctl_t *nioc, return (EINVAL); break; + case NVME_FEAT_TEMPERATURE: + if (nsid != 0) + return (EINVAL); + res = nioc->n_arg & 0xffffffffUL; + if (NVME_VERSION_ATLEAST(&nvme->n_version, 1, 2)) { + nvme_temp_threshold_t tt; + + tt.r = res; + if (tt.b.tt_thsel != NVME_TEMP_THRESH_OVER && + tt.b.tt_thsel != NVME_TEMP_THRESH_UNDER) { + return (EINVAL); + } + + if (tt.b.tt_tmpsel > NVME_TEMP_THRESH_MAX_SENSOR) { + return (EINVAL); + } + } else if (res != 0) { + return (EINVAL); + } + break; + case NVME_FEAT_INTR_VECT: if (nsid != 0) return (EINVAL); diff --git a/usr/src/uts/common/sys/nvme.h b/usr/src/uts/common/sys/nvme.h index 9a0d926dc5..1d54b05f21 100644 --- a/usr/src/uts/common/sys/nvme.h +++ b/usr/src/uts/common/sys/nvme.h @@ -436,7 +436,23 @@ typedef struct { nvme_uint128_t hl_unsafe_shutdn; /* Unsafe Shutdowns */ nvme_uint128_t hl_media_errors; /* Media Errors */ nvme_uint128_t hl_errors_logged; /* Number of errors logged */ - uint8_t hl_rsvd2[512 - 192]; + /* Added in NVMe 1.2 */ + uint32_t hl_warn_temp_time; /* Warning Composite Temp Time */ + uint32_t hl_crit_temp_time; /* Critical Composite Temp Time */ + uint16_t hl_temp_sensor_1; /* Temperature Sensor 1 */ + uint16_t hl_temp_sensor_2; /* Temperature Sensor 2 */ + uint16_t hl_temp_sensor_3; /* Temperature Sensor 3 */ + uint16_t hl_temp_sensor_4; /* Temperature Sensor 4 */ + uint16_t hl_temp_sensor_5; /* Temperature Sensor 5 */ + uint16_t hl_temp_sensor_6; /* Temperature Sensor 6 */ + uint16_t hl_temp_sensor_7; /* Temperature Sensor 7 */ + uint16_t hl_temp_sensor_8; /* Temperature Sensor 8 */ + /* Added in NVMe 1.3 */ + uint32_t hl_tmtemp_1_tc; /* Thermal Mgmt Temp 1 Transition # */ + uint32_t hl_tmtemp_2_tc; /* Thermal Mgmt Temp 1 Transition # */ + uint32_t hl_tmtemp_1_time; /* Time in Thermal Mgmt Temp 1 */ + uint32_t hl_tmtemp_2_time; /* Time in Thermal Mgmt Temp 2 */ + uint8_t hl_rsvd2[512 - 232]; } nvme_health_log_t; /* @@ -551,11 +567,18 @@ typedef struct { typedef union { struct { uint16_t tt_tmpth; /* Temperature Threshold */ - uint16_t tt_rsvd; + uint16_t tt_tmpsel:4; /* Temperature Select */ + uint16_t tt_thsel:2; /* Temperature Type */ + uint16_t tt_resv:10; } b; uint32_t r; } nvme_temp_threshold_t; +#define NVME_TEMP_THRESH_MAX_SENSOR 8 +#define NVME_TEMP_THRESH_ALL 0xf +#define NVME_TEMP_THRESH_OVER 0x00 +#define NVME_TEMP_THRESH_UNDER 0x01 + /* Error Recovery Feature */ typedef union { struct { |