aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Sukhoguzov <sap@eseipi.net>2024-10-30 11:04:49 +0000
committerWarner Losh <imp@FreeBSD.org>2026-01-09 20:32:59 +0000
commitf0d44ee06b6814224653324e09a948e15a177d1f (patch)
tree09eb33e2ae331a2984e697ae02631c64d3ee82fe
parenta24932dcec45ca68fa5ca2f49bbf0df539cfd710 (diff)
-rw-r--r--share/man/man4/nvme.412
-rw-r--r--sys/dev/nvme/nvme_ctrlr.c22
2 files changed, 26 insertions, 8 deletions
diff --git a/share/man/man4/nvme.4 b/share/man/man4/nvme.4
index d24ffc07ef9e..76960a7e06c8 100644
--- a/share/man/man4/nvme.4
+++ b/share/man/man4/nvme.4
@@ -136,6 +136,18 @@ hw.nvme.apst_enable=1
.Ed
.Pp
The default vendor-provided settings, if any, will be applied.
+To override this, set the following tunable:
+.Bd -literal -offset indent
+hw.nvme.apst_data
+.Ed
+.Pp
+The string must contain up to 32 encoded integers, e.g. "0x6418 0
+0 0x3e820".
+Each value corresponds to a specific available power state starting
+from the lowest, and defines the target state (bits 3..7) to
+transition to, as well as the idle time in milliseconds (bits 8..31)
+to wait before that transition.
+Bits 0..2 must be zero.
.Pp
The
.Xr nvd 4
diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index 2c13dac96342..26194ccbb8f8 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -786,7 +786,7 @@ nvme_ctrlr_configure_apst(struct nvme_controller *ctrlr)
{
struct nvme_completion_poll_status status;
uint64_t *data;
- int data_size;
+ int data_size, i, read_size;
bool enable, error = true;
if (TUNABLE_BOOL_FETCH("hw.nvme.apst_enable", &enable) == 0 ||
@@ -796,13 +796,19 @@ nvme_ctrlr_configure_apst(struct nvme_controller *ctrlr)
data_size = 32 * sizeof(*data);
data = malloc(data_size, M_NVME, M_WAITOK | M_ZERO);
- status.done = 0;
- nvme_ctrlr_cmd_get_feature(ctrlr,
- NVME_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION, 0,
- data, data_size, nvme_completion_poll_cb, &status);
- nvme_completion_poll(&status);
- if (nvme_completion_is_error(&status.cpl))
- goto out;
+ if (getenv_array("hw.nvme.apst_data", data, data_size,
+ &read_size, sizeof(*data), GETENV_UNSIGNED) != 0) {
+ for (i = 0; i < read_size / sizeof(*data); ++i)
+ data[i] = htole64(data[i]);
+ } else {
+ status.done = 0;
+ nvme_ctrlr_cmd_get_feature(ctrlr,
+ NVME_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION, 0,
+ data, data_size, nvme_completion_poll_cb, &status);
+ nvme_completion_poll(&status);
+ if (nvme_completion_is_error(&status.cpl))
+ goto out;
+ }
status.done = 0;
nvme_ctrlr_cmd_set_feature(ctrlr,