Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libnvme/src/nvme/cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ int nvme_get_feature_length(int fid, __u32 cdw11, enum nvme_data_tfr dir,
case NVME_FEAT_FID_RESV_PERSIST:
case NVME_FEAT_FID_WRITE_PROTECT:
case NVME_FEAT_FID_POWER_LIMIT:
case NVME_FEAT_FID_POWER_MEASUREMENT:
*len = 0;
break;
case NVME_FEAT_FID_ENH_CTRL_METADATA:
Expand Down
30 changes: 28 additions & 2 deletions libnvme/src/nvme/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,16 @@ enum nvme_power_measurement_type {
NVME_PMT_VS_MAX = 0xf,
};

/**
* enum nvme_power_measurement_action - Power measurement actions.
* @NVME_PMA_STOP: Stop power measurement
* @NVME_PMA_START: Start power measurement
*/
enum nvme_power_measurement_action {
NVME_PMA_STOP = 0x0,
NVME_PMA_START = 0x1,
};

/**
* nvme_psd_power_scale() - power scale occupies the upper 3 bits
* @ps: power scale value
Expand Down Expand Up @@ -8835,7 +8845,7 @@ enum nvme_cmd_get_log_lid {
* @NVME_FEAT_FID_CONF_DEV_PERSONALITY: Configurable Device Personality
* @NVME_FEAT_FID_POWER_LIMIT: Power Limit
* @NVME_FEAT_FID_POWER_THRESH: Power Threshold
* @NVME_FEAT_FID_POEWR_MEASUREMENT: Power Measurement
* @NVME_FEAT_FID_POWER_MEASUREMENT: Power Measurement
* @NVME_FEAT_FID_EMB_MGMT_CTRL_ADDR: Embedded Management Controller Address
* @NVME_FEAT_FID_HOST_MGMT_AGENT_ADDR: Host Management Agent Address
* @NVME_FEAT_FID_ENH_CTRL_METADATA: Enhanced Controller Metadata
Expand Down Expand Up @@ -8885,7 +8895,7 @@ enum nvme_features_id {
NVME_FEAT_FID_CONF_DEV_PERSONALITY = 0x22,
NVME_FEAT_FID_POWER_LIMIT = 0x23,
NVME_FEAT_FID_POWER_THRESH = 0x24,
NVME_FEAT_FID_POEWR_MEASUREMENT = 0x25,
NVME_FEAT_FID_POWER_MEASUREMENT = 0x25,
NVME_FEAT_FID_EMB_MGMT_CTRL_ADDR = 0x78,
NVME_FEAT_FID_HOST_MGMT_AGENT_ADDR = 0x79,
NVME_FEAT_FID_ENH_CTRL_METADATA = 0x7d,
Expand Down Expand Up @@ -9065,6 +9075,12 @@ enum nvme_features_id {
* @NVME_FEAT_POWER_THRESH_PMTS_MASK:
* @NVME_FEAT_POWER_THRESH_EPT_SHIFT:
* @NVME_FEAT_POWER_THRESH_EPT_MASK:
* @NVME_FEAT_POWER_MEAS_ACT_SHIFT:
* @NVME_FEAT_POWER_MEAS_ACT_MASK:
* @NVME_FEAT_POWER_MEAS_PMTS_SHIFT:
* @NVME_FEAT_POWER_MEAS_PMTS_MASK:
* @NVME_FEAT_POWER_MEAS_SMT_SHIFT:
* @NVME_FEAT_POWER_MEAS_SMT_MASK:
**/
enum nvme_feat {
NVME_FEAT_ARBITRATION_BURST_SHIFT = 0,
Expand Down Expand Up @@ -9231,6 +9247,12 @@ enum nvme_feat {
NVME_FEAT_POWER_THRESH_PMTS_MASK = 0xf,
NVME_FEAT_POWER_THRESH_EPT_SHIFT = 31,
NVME_FEAT_POWER_THRESH_EPT_MASK = 0x1,
NVME_FEAT_POWER_MEAS_ACT_SHIFT = 0,
NVME_FEAT_POWER_MEAS_ACT_MASK = 0xf,
NVME_FEAT_POWER_MEAS_PMTS_SHIFT = 4,
NVME_FEAT_POWER_MEAS_PMTS_MASK = 0xf,
NVME_FEAT_POWER_MEAS_SMT_SHIFT = 16,
NVME_FEAT_POWER_MEAS_SMT_MASK = 0xffff,
};

/**
Expand Down Expand Up @@ -10514,6 +10536,10 @@ static inline void nvme_feature_decode_arbitration(__u32 value, __u8 *ab,
#define NVME_FEAT_POWER_THRESH_PMTS(v) NVME_GET(v, FEAT_POWER_THRESH_PMTS)
#define NVME_FEAT_POWER_THRESH_EPT(v) NVME_GET(v, FEAT_POWER_THRESH_EPT)

#define NVME_FEAT_POWER_MEAS_ACT(v) NVME_GET(v, FEAT_POWER_MEAS_ACT)
#define NVME_FEAT_POWER_MEAS_PMTS(v) NVME_GET(v, FEAT_POWER_MEAS_PMTS)
#define NVME_FEAT_POWER_MEAS_SMT(v) NVME_GET(v, FEAT_POWER_MEAS_SMT)

static inline void
nvme_feature_decode_power_mgmt(__u32 value, __u8 *ps, __u8 *wh)
{
Expand Down
35 changes: 30 additions & 5 deletions nvme-print-json.c
Original file line number Diff line number Diff line change
Expand Up @@ -4133,10 +4133,12 @@ static void json_feature_show_fields_power_limit(struct json_object *r,
static void json_feature_show_fields_power_thresh(struct json_object *r,
unsigned int result)
{
__u8 field = NVME_FEAT_POWER_THRESH_EPT(result);

__u8 field;
__u16 ptv;
_cleanup_free_ char *k = NULL;

field = NVME_FEAT_POWER_THRESH_EPT(result);

obj_add_str(r, "Enable Power Threshold (EPT)",
field ? "Enabled" : "Disabled");

Expand All @@ -4148,13 +4150,33 @@ static void json_feature_show_fields_power_thresh(struct json_object *r,
obj_add_str(r, "Power Threshold Scale (PTS)",
nvme_feature_power_limit_scale_to_string(field));

field = NVME_FEAT_POWER_THRESH_PTV(result);
obj_add_uint(r, "Power Threshold Value (PTV)", field);
ptv = NVME_FEAT_POWER_THRESH_PTV(result);

obj_add_uint(r, "Power Threshold Value (PTV)", ptv);

k = get_power_and_scale(field, NVME_FEAT_POWER_THRESH_PTS(result));
k = get_power_and_scale(ptv, NVME_FEAT_POWER_THRESH_PTS(result));
obj_add_str(r, "Power Threshold", k);
}

static void json_feature_show_fields_power_meas(struct json_object *r,
unsigned int result)
{
__u8 field;
__u16 smt;

field = NVME_FEAT_POWER_MEAS_ACT(result);
obj_add_str(r, "Action (ACT)",
nvme_power_measurement_action_to_string(field));

field = NVME_FEAT_POWER_MEAS_PMTS(result);
obj_add_str(r, "Power Measurement Type Select (PMTS)",
nvme_power_measurement_type_to_string(field));

smt = NVME_FEAT_POWER_MEAS_SMT(result);

obj_add_uint(r, "Stop Measurement Time (SMT)", smt);
}

static void json_feature_show(enum nvme_features_id fid, int sel, unsigned int result)
{
struct json_object *r;
Expand Down Expand Up @@ -4300,6 +4322,9 @@ static void json_feature_show_fields(enum nvme_features_id fid, unsigned int res
case NVME_FEAT_FID_POWER_THRESH:
json_feature_show_fields_power_thresh(r, result);
break;
case NVME_FEAT_FID_POWER_MEASUREMENT:
json_feature_show_fields_power_meas(r, result);
break;
default:
break;
}
Expand Down
10 changes: 10 additions & 0 deletions nvme-print-stdout.c
Original file line number Diff line number Diff line change
Expand Up @@ -5427,6 +5427,16 @@ static void stdout_feature_show_fields(enum nvme_features_id fid,
field);
printf("\n");
break;
case NVME_FEAT_FID_POWER_MEASUREMENT:
field = NVME_FEAT_POWER_MEAS_ACT(result);
printf("\tAction (ACT): %u - %s\n", field,
nvme_power_measurement_action_to_string(field));
field = NVME_FEAT_POWER_MEAS_PMTS(result);
printf("\tPower Measurement Type Select (PMTS): %u - %s\n",
field, nvme_power_measurement_type_to_string(field));
printf("\tStop Measurement Time (SMT): %u\n",
NVME_FEAT_POWER_MEAS_SMT(result));
break;
default:
break;
}
Expand Down
17 changes: 16 additions & 1 deletion nvme-print.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ const char *nvme_feature_to_string(enum nvme_features_id feature)
case NVME_FEAT_FID_CONF_DEV_PERSONALITY:return "Configurable Device Personality";
case NVME_FEAT_FID_POWER_LIMIT: return "Power Limit";
case NVME_FEAT_FID_POWER_THRESH: return "Power Threshold";
case NVME_FEAT_FID_POEWR_MEASUREMENT: return "Power Measurement";
case NVME_FEAT_FID_POWER_MEASUREMENT: return "Power Measurement";
case NVME_FEAT_FID_EMB_MGMT_CTRL_ADDR: return "Embedded Management Controller Address";
case NVME_FEAT_FID_HOST_MGMT_AGENT_ADDR:return "Host Management Agent Address";
case NVME_FEAT_FID_ENH_CTRL_METADATA: return "Enhanced Controller Metadata";
Expand Down Expand Up @@ -1526,6 +1526,21 @@ const char *nvme_power_measurement_type_to_string(__u8 pmt)
return "Reserved";
}


const char *nvme_power_measurement_action_to_string(__u8 act)
{
switch (act) {
case 0:
return "Stop";
case 1:
return "Start";
default:
break;
}

return "Reserved";
}

void nvme_feature_show(enum nvme_features_id fid, int sel, unsigned int result)
{
nvme_print(show_feature, NORMAL, fid, sel, result);
Expand Down
1 change: 1 addition & 0 deletions nvme-print.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ const char *nvme_pls_mode_to_string(__u8 mode);
const char *nvme_bpwps_to_string(__u8 bpwps);
const char *nvme_feature_power_limit_scale_to_string(__u8 pls);
const char *nvme_power_measurement_type_to_string(__u8 pmt);
const char *nvme_power_measurement_action_to_string(__u8 act);

void nvme_dev_full_path(nvme_ns_t n, char *path, size_t len);
void nvme_generic_full_path(nvme_ns_t n, char *path, size_t len);
Expand Down
76 changes: 76 additions & 0 deletions plugins/feat/feat-nvme.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ static const char *arbitration_feat = "arbitration feature";
static const char *volatile_wc_feat = "volatile write cache feature";
static const char *power_limit_feat = "power limit feature";
static const char *power_thresh_feat = "power threshold feature";
static const char *power_meas_feat = "power measurement feature";

static int feat_get(struct nvme_transport_handle *hdl, const __u8 fid,
__u32 cdw11, __u8 sel, __u8 uidx, const char *feat)
Expand Down Expand Up @@ -753,3 +754,78 @@ static int feat_power_thresh(int argc, char **argv, struct command *acmd,

return err;
}

static int power_meas_set(struct nvme_transport_handle *hdl, const __u8 fid,
__u8 action, __u8 pmts, __u16 smt, __u8 uidx, bool sv)
{
__u32 cdw11 = NVME_SET(action, FEAT_POWER_MEAS_ACT) |
NVME_SET(pmts, FEAT_POWER_MEAS_PMTS) |
NVME_SET(smt, FEAT_POWER_MEAS_SMT);
__u64 result;
int err;

err = nvme_set_features(hdl, 0, fid, sv, cdw11, 0, 0, uidx, 0, NULL, 0,
&result);

nvme_show_init();

if (err > 0) {
nvme_show_status(err);
} else if (err < 0) {
nvme_show_perror("Set %s", power_meas_feat);
} else {
nvme_show_result("Set %s: 0x%04x (%s)", power_meas_feat, cdw11,
sv ? "Save" : "Not save");
nvme_feature_show_fields(fid, cdw11, NULL);
}
Copy link
Copy Markdown
Collaborator

@igaw igaw Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we recenetly changed how print error. instead of this snippet, it's possible to use something like this:

	err = nvme_identify_ctrl(hdl, ctrl);
	if (err) {
		nvme_show_err("identify controller", err);
		return err;
	}

	nvme_show_id_ctrl(ctrl, flags, vs);

looks like feat-nvme.c needs this update too...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do this change in a different patch though.

@ikegami-t do want to update feat-nvme.c accordingly? Just asking because you have been working most of the time on this file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure will do it later. Thank you.


nvme_show_finish();

return err;
}

static int feat_power_meas(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
const char *action = "action [0-1]: stop|start";
const char *pmts = "power measurement type select";
const char *smt = "stop measurement time";
const __u8 fid = NVME_FEAT_FID_POWER_MEASUREMENT;

_cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL;

_cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl =
NULL;
int err;

struct config {
__u8 act;
__u8 pmts;
__u16 smt;
__u8 uidx;
__u8 sel;
};

struct config cfg = { 0 };

FEAT_ARGS(opts,
OPT_BYTE("act", 0, &cfg.act, action),
OPT_BYTE("pmts", 0, &cfg.pmts, pmts),
OPT_SHRT("smt", 0, &cfg.smt, smt),
OPT_BYTE("uuid-index", 'u', &cfg.uidx, uuid_index));

err = parse_and_open(&ctx, &hdl, argc, argv, POWER_MEAS_DESC, opts);
if (err)
return err;

if (argconfig_parse_seen(opts, "act") ||
argconfig_parse_seen(opts, "pmts") ||
argconfig_parse_seen(opts, "smt"))
err = power_meas_set(hdl, fid, cfg.act, cfg.pmts, cfg.smt,
cfg.uidx,
argconfig_parse_seen(opts, "save"));
else
err = feat_get(hdl, fid, 0, cfg.sel, 0, power_meas_feat);

return err;
}
2 changes: 2 additions & 0 deletions plugins/feat/feat-nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define VOLATILE_WC_DESC "Get and set volatile write cache feature"
#define POWER_LIMIT_DESC "Get and set power limit feature"
#define POWER_THRESH_DESC "Get and set power threshold feature"
#define POWER_MEAS_DESC "Get and set power measurement feature"

#define FEAT_ARGS(n, ...) \
NVME_ARGS(n, ##__VA_ARGS__, OPT_FLAG("save", 's', NULL, save), \
Expand All @@ -35,6 +36,7 @@ PLUGIN(NAME("feat", "NVMe feature extensions", FEAT_PLUGIN_VERSION),
ENTRY("volatile-wc", VOLATILE_WC_DESC, feat_volatile_wc)
ENTRY("power-limit", POWER_LIMIT_DESC, feat_power_limit)
ENTRY("power-thresh", POWER_THRESH_DESC, feat_power_thresh)
ENTRY("power-meas", POWER_MEAS_DESC, feat_power_meas)
)
);
#endif /* !FEAT_NVME || CMD_HEADER_MULTI_READ */
Expand Down