summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/nvmeadm/nvmeadm.c164
-rw-r--r--usr/src/cmd/nvmeadm/nvmeadm.h6
-rw-r--r--usr/src/cmd/nvmeadm/nvmeadm_print.c156
-rw-r--r--usr/src/uts/common/io/nvme/nvme.c22
-rw-r--r--usr/src/uts/common/sys/nvme.h27
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 {