Skip to content
Closed
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
19 changes: 19 additions & 0 deletions libnvme/src/nvme/cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -1520,6 +1520,25 @@ nvme_init_get_log_mgmt_addr_list(struct nvme_passthru_cmd *cmd,
log, len);
}

/**
* nvme_init_get_log_power_measurement() - Initialize passthru command for
* Power Measurement
* @cmd: Passthru command to use
* @log: User address to store the log page
* @len: The allocated length of the log page
*
* Initializes the passthru command buffer for the Get Log command with
* LID value %NVME_LOG_LID_POWER_MEASUREMENT
*/
static inline void
nvme_init_get_log_power_measurement(struct nvme_passthru_cmd *cmd,
struct nvme_power_meas_log *log, __u32 len)
{
nvme_init_get_log(cmd, NVME_NSID_ALL,
NVME_LOG_LID_POWER_MEASUREMENT, NVME_CSI_NVM,
log, len);
}

/**
* nvme_init_get_log_phy_rx_eom() - Initialize passthru command for
* Physical Interface Receiver Eye Opening Measurement
Expand Down
149 changes: 147 additions & 2 deletions libnvme/src/nvme/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -3773,7 +3773,26 @@
* reached. A value of %0h, indicates that this transition
* has never occurred or this field is not implemented.
* @thm_temp2_total_time: Total Time For Thermal Management Temperature 2
* @rsvd232: Reserved
* @op_lifetime_energy_consumed: Operational Lifetime Energy Consumed: Contains
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.

Using this long name here makes sense. This makes it consistent. Though I wonder if we should update (afterwards) to the short names, as we have done in cmds.h. Maybe not, this is one of these huge tasks for someone else :)

* the cumulative operational energy consumed by the NVM
* subsystem in watt-hours calculated from all interval
* power measurements collected from the time of
* manufacture to the point that this log page is read.
* This value is rounded up (e.g., two indicates the
* number of watt-hours consumed is greater than 1 and
* less than or equal to 2). This field shall not wrap
* once the value %FFFFFFFFFFFFFFFFh is reached. A value
* of %0h indicates that the cumulative operational energy

Check failure on line 3785 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 82 exceeds 80 columns
* consumed is not reported.
* @interval_power_measurement: Interval Power Measurement: Contains the average
* of power measurement samples over the most recent one
* second interval at the time of processing the Get Log
* Page command. The power in Watts is equal to the
* Interval Power Measurement Value (bits 15:0) multiplied

Check failure on line 3791 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 82 exceeds 80 columns
* by the scale indicated in the Interval Power Measurement

Check failure on line 3792 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 83 exceeds 80 columns
* Scale field (bits 17:16). A value of %0h indicates that

Check failure on line 3793 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 82 exceeds 80 columns
* the interval power measurement is not reported.
* @rsvd244: Reserved
*/
struct nvme_smart_log {
__u8 critical_warning;
Expand All @@ -3800,7 +3819,9 @@
__le32 thm_temp2_trans_count;
__le32 thm_temp1_total_time;
__le32 thm_temp2_total_time;
__u8 rsvd232[280];
__le64 op_lifetime_energy_consumed;
__le32 interval_power_measurement;
__u8 rsvd244[268];
};

/**
Expand Down Expand Up @@ -4669,6 +4690,23 @@
__u8 rsvd;
};

/**
* enum nvme_timestamp_attr - Timestamp Attribute field
* @NVME_TIMESTAMP_ATTR_SYNC_SHIFT: Shift amount to get the timestamp synch
* @NVME_TIMESTAMP_ATTR_TO_SHIFT: Shift amount to get the timestamp origin
* @NVME_TIMESTAMP_ATTR_SYNC_MASK: Mask to get the timestamp synch
* @NVME_TIMESTAMP_ATTR_TO_MASK: Mask to get the timestamp origin
*/
enum nvme_timestamp_attr {
NVME_TIMESTAMP_ATTR_SYNC_SHIFT = 0,
NVME_TIMESTAMP_ATTR_TO_SHIFT = 1,
NVME_TIMESTAMP_ATTR_SYNC_MASK = 0x1,
NVME_TIMESTAMP_ATTR_TO_MASK = 0x7,
};

#define NVME_TIMESTAMP_ATTR_SYNC(attr) NVME_GET(attr, TIMESTAMP_ATTR_SYNC)
#define NVME_TIMESTAMP_ATTR_TO(attr) NVME_GET(attr, TIMESTAMP_ATTR_TO)

/**
* struct nvme_time_stamp_change_event - Timestamp Change Event
* @previous_timestamp: Previous Timestamp
Expand Down Expand Up @@ -6102,6 +6140,113 @@
struct nvme_fdp_ruh_status_desc ruhss[];
};

/**
* enum nvme_pma - Power Measurement Attributes (PMA) field
* @NVME_PMA_PME_SHIFT: Shift amount to get the power measurement enable
* @NVME_PMA_NCPDF_SHIFT: Shift amount to get the non-contiguous power data flag

Check failure on line 6146 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 86 exceeds 80 columns
* @NVME_PMA_EPF_SHIFT: Shift amount to get the estimated power flag
* @NVME_PMA_MIPWRTS_SHIFT: Shift amount to get the maximum interval power timestamp support

Check failure on line 6148 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 96 exceeds 80 columns
* @NVME_PMA_PHDO_SHIFT: Shift amount to get the power histogram descriptor overflow

Check failure on line 6149 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 91 exceeds 80 columns
* @NVME_PMA_PMT_SHIFT: Shift amount to get the power measurement type
* @NVME_PMA_PME_MASK: Mask to get the power measurement enable
* @NVME_PMA_NCPDF_MASK: Mask to get the non-contiguous power data flag
* @NVME_PMA_EPF_MASK: Mask to get the estimated power flag
* @NVME_PMA_MIPWRTS_MASK: Mask to get the maximum interval power timestamp support

Check failure on line 6154 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 88 exceeds 80 columns
* @NVME_PMA_PHDO_MASK: Mask to get the power histogram descriptor overflow

Check failure on line 6155 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 83 exceeds 80 columns
* @NVME_PMA_PMT_MASK: Mask to get the power measurement type
*/
enum nvme_pma {
NVME_PMA_PME_SHIFT = 0,
NVME_PMA_NCPDF_SHIFT = 1,
NVME_PMA_EPF_SHIFT = 2,
NVME_PMA_MIPWRTS_SHIFT = 3,
NVME_PMA_PHDO_SHIFT = 4,
NVME_PMA_PMT_SHIFT = 12,
NVME_PMA_PME_MASK = 0x1,
NVME_PMA_NCPDF_MASK = 0x1,
NVME_PMA_EPF_MASK = 0x1,
NVME_PMA_MIPWRTS_MASK = 0x1,
NVME_PMA_PHDO_MASK = 0x1,
NVME_PMA_PMT_MASK = 0xf,
};

/**
* struct nvme_power_histogram_desc - Power Histogram Descriptor
* @phbc: Power Histogram Bin Count. Does not wrap after %FFFFFFFFh.
* Cleared to %0h if PMC is %0h.
* @phblt: Power Histogram Bin Lower Threshold. Bits 17:16 are PWRS
* (see &enum nvme_psd_ps), bits 15:0 are PWRV.
*/
struct nvme_power_histogram_desc {
__le32 phbc;
__le32 phblt;
};

/**
* struct nvme_power_meas_log - Power Measurement Log Page (Log Identifier 25h)
* @ver: Version. Shall be cleared to %0h.
* @pmgn: Power Measurement Generation Number. Incremented each time a
* Set Features command with Action = %1h (Start Power Measurements)

Check failure on line 6189 in libnvme/src/nvme/types.h

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: line length of 81 exceeds 80 columns
* is successfully completed. Rolls over from %FFh to %0h.
* @pma: Power Measurement Attributes. See &enum nvme_pma.
* @sze: Size. Indicates the size of this log page in bytes.
* @pmc: Power Measurement Count. Number of interval power measurements
* collected. Does not wrap after %FFFFFFFFh. Cleared to %0h when
* Start Power Measurements succeeds or if no measurement has occurred.
* @nphd: Number of Power Histogram Descriptors in this log page.
* @smtr: Stop Measurement Time Remaining. Time remaining in minutes until
* controller stops collecting interval power measurements.
* %0h means not specified.
* @smts: Stop Measurement Timestamp. Timestamp of when interval power
* measurements stopped being collected. See &struct nvme_timestamp.
* @phds: Power Histogram Descriptor Size. Size in bytes of each descriptor.
* @phbs: Power Histogram Bin Size. Size in milliwatts of each bin.
* Shall be set to 250 milliwatts.
* @nphds: Number of Power Histogram Descriptors Supported. Maximum number
* of descriptors that can be reported. If %0h, NPHD shall be
* cleared to %0h and no descriptors are reported.
* @vss: Vendor Specific Size. Size in bytes of the Vendor Specific field.
* @phdoc: Power Histogram Descriptor Overflow Count. Number of interval
* power measurements greater than the maximum power indicated by
* the last Power Histogram Descriptor. Does not wrap after %FFFFFFFFh.
* @rsvd36: Reserved.
* @aipwr: Average Interval Power. Bits 31:18 are reserved. Bits 17:16
* contain the Power Scale (PWRS); see &enum nvme_psd_ps. Bits 15:0
* contain the Power Value (PWRV).
* @mipwr: Maximum Interval Power. Bits 31:18 are reserved. Bits 17:16
* contain the Power Scale (PWRS); see &enum nvme_psd_ps. Bits 15:0
* contain the Power Value (PWRV).
* @mipwrt: Maximum Interval Power Timestamp. Timestamp of when the maximum
* interval power was collected. See &struct nvme_timestamp.
* @ipwrpe: Interval Power Percent Error. Maximum percent error (0-100%).
* Values 101-254 reserved. 255 indicates not reported.
* @rsvd57: Reserved.
* @descs: Power Histogram Descriptors (&struct nvme_power_histogram_desc).
*/
struct nvme_power_meas_log {
__u8 ver;
__u8 pmgn;
__le16 pma;
__le32 sze;
__le32 pmc;
__le16 nphd;
__le16 smtr;
struct nvme_timestamp smts;
__le16 phds;
__le16 phbs;
__le16 nphds;
__le16 vss;
__le32 phdoc;
__u8 rsvd36[4];
__le32 aipwr;
__le32 mipwr;
struct nvme_timestamp mipwrt;
__u8 ipwrpe;
__u8 rsvd57[7];
struct nvme_power_histogram_desc descs[];
};


/**
* struct nvme_lba_status_desc - LBA Status Descriptor Entry
* @dslba: Descriptor Starting LBA
Expand Down
1 change: 1 addition & 0 deletions nvme-builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ COMMAND_LIST(
ENTRY("host-discovery-log", "Retrieve Host Discovery Log, show it", get_host_discovery_log)
ENTRY("ave-discovery-log", "Retrieve AVE Discovery Log, show it", get_ave_discovery_log)
ENTRY("pull-model-ddc-req-log", "Retrieve Pull Model DDC Request Log, show it", get_pull_model_ddc_req_log)
ENTRY("power-measurement-log", "Retrieve Power Measurement Log, show it", get_power_measurement_log)
ENTRY("set-feature", "Set a feature and show the resulting value", set_feature)
ENTRY("set-property", "Set a property and show the resulting value", set_property)
ENTRY("get-property", "Get a property and show the resulting value", get_property)
Expand Down
27 changes: 27 additions & 0 deletions nvme-cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,33 @@ nvme_get_log_mgmt_addr_list(struct nvme_transport_handle *hdl,
return nvme_get_log(hdl, &cmd, false, len);
}

/**
* nvme_get_log_power_measurement() - Retrieve the Power Measurement Log Page
* @hdl: Transport handle for the controller.
* @log: Pointer to the buffer (@struct nvme_power_meas_log) where
* the log page data will be stored.
* @len: Length of the buffer provided in @log.
*
* Submits the Get Log Page command specifically for the Power Measurement Log.
*
* It automatically sets the Log Identifier (LID) to
* NVME_LOG_LID_POWER_MEASUREMENT, Retain Asynchronous Event (RAE) to false,
* and uses NVME_NSID_ALL.
*
* Return: 0 on success, the NVMe command status on error, or a negative
* errno otherwise.
*/
static inline int
nvme_get_log_power_measurement(struct nvme_transport_handle *hdl,
struct nvme_power_meas_log *log, __u32 len)
{
struct nvme_passthru_cmd cmd;

nvme_init_get_log_power_measurement(&cmd, log, len);

return nvme_get_log(hdl, &cmd, false, NVME_LOG_PAGE_PDU_SIZE);
}

/**
* nvme_get_log_phy_rx_eom() - Retrieve the Physical Interface Receiver Eye
* Opening Measurement Log Page
Expand Down
6 changes: 6 additions & 0 deletions nvme-print-binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,11 @@ static void binary_pull_model_ddc_req_log(struct nvme_pull_model_ddc_req_log *lo
d_raw((unsigned char *)log, le32_to_cpu(log->tpdrpl));
}

static void binary_power_meas_log(struct nvme_power_meas_log *log, __u32 size)
{
d_raw((unsigned char *)log, size);
}

static struct print_ops binary_print_ops = {
/* libnvme types.h print functions */
.ana_log = binary_ana_log,
Expand Down Expand Up @@ -421,6 +426,7 @@ static struct print_ops binary_print_ops = {
.host_discovery_log = binary_host_discovery_log,
.ave_discovery_log = binary_ave_discovery_log,
.pull_model_ddc_req_log = binary_pull_model_ddc_req_log,
.power_meas_log = binary_power_meas_log,

/* libnvme tree print functions */
.list_item = NULL,
Expand Down
80 changes: 63 additions & 17 deletions nvme-print-json.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,8 @@ static void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid,
obj_add_uint(r, "thm_temp2_trans_count", le32_to_cpu(smart->thm_temp2_trans_count));
obj_add_uint(r, "thm_temp1_total_time", le32_to_cpu(smart->thm_temp1_total_time));
obj_add_uint(r, "thm_temp2_total_time", le32_to_cpu(smart->thm_temp2_total_time));
obj_add_uint64(r, "op_lifetime_energy_consumed", le64_to_cpu(smart->op_lifetime_energy_consumed));
obj_add_uint(r, "interval_power_measurement", le32_to_cpu(smart->interval_power_measurement));

json_print(r);
}
Expand Down Expand Up @@ -3768,24 +3770,10 @@ static void json_feature_show_fields_host_mem_buf(struct json_object *r, unsigne

static void json_timestamp(struct json_object *r, struct nvme_timestamp *ts)
{
char buffer[BUF_LEN];
time_t timestamp = int48_to_long(ts->timestamp) / 1000;
struct tm *tm = localtime(&timestamp);

obj_add_uint64(r, "timestamp", int48_to_long(ts->timestamp));

if (!strftime(buffer, sizeof(buffer), "%c %Z", tm))
sprintf(buffer, "%s", "-");

obj_add_str(r, "timestamp string", buffer);

obj_add_str(r, "timestamp origin", ts->attr & 2 ?
"The Timestamp field was initialized with a Timestamp value using a Set Features command." :
"The Timestamp field was initialized to 0h by a Controller Level Reset.");

obj_add_str(r, "synch", ts->attr & 1 ?
"The controller may have stopped counting during vendor specific intervals after the Timestamp value was initialized." :
"The controller counted time in milliseconds continuously since the Timestamp value was initialized.");
obj_add_str(r, "timestamp string", nvme_format_timestamp(ts->timestamp));
obj_add_str(r, "timestamp origin", nvme_format_timestamp_origin(ts->attr));
obj_add_str(r, "synch", nvme_format_timestamp_sync(ts->attr));
}

static void json_feature_show_fields_timestamp(struct json_object *r, unsigned char *buf)
Expand Down Expand Up @@ -5716,6 +5704,63 @@ static void json_pull_model_ddc_req_log(struct nvme_pull_model_ddc_req_log *log)
obj_d(r, "osp", (unsigned char *)log->osp, osp_len, 16, 1);
}

static void json_power_meas_log(struct nvme_power_meas_log *log, __u32 size UNUSED)
{
struct json_object *r = json_create_object();
struct json_object *descs;
struct json_object *smts_obj;
struct json_object *mipwrt_obj;
__u16 nphd = le16_to_cpu(log->nphd);
__u16 pma = le16_to_cpu(log->pma);
__u8 pmt = NVME_GET(pma, PMA_PMT);
__u16 i;

obj_add_uint(r, "ver", log->ver);
obj_add_uint(r, "pmgn", log->pmgn);
obj_add_uint(r, "pma", pma);
obj_add_uint(r, "pme", NVME_GET(pma, PMA_PME));
obj_add_uint(r, "ncpdf", NVME_GET(pma, PMA_NCPDF));
obj_add_uint(r, "epf", NVME_GET(pma, PMA_EPF));
obj_add_uint(r, "mipwrts", NVME_GET(pma, PMA_MIPWRTS));
obj_add_uint(r, "phdo", NVME_GET(pma, PMA_PHDO));
obj_add_uint(r, "pmt", pmt);
obj_add_str(r, "pmt_str", nvme_power_measurement_type_to_string(pmt));
obj_add_uint(r, "sze", le32_to_cpu(log->sze));
obj_add_uint(r, "pmc", le32_to_cpu(log->pmc));
obj_add_uint(r, "nphd", nphd);
obj_add_uint(r, "smtr", le16_to_cpu(log->smtr));

smts_obj = json_create_object();
json_timestamp(smts_obj, &log->smts);
obj_add_obj(r, "smts", smts_obj);

obj_add_uint(r, "phds", le16_to_cpu(log->phds));
obj_add_uint(r, "phbs", le16_to_cpu(log->phbs));
obj_add_uint(r, "nphds", le16_to_cpu(log->nphds));
obj_add_uint(r, "vss", le16_to_cpu(log->vss));
obj_add_uint(r, "phdoc", le32_to_cpu(log->phdoc));
obj_add_uint(r, "aipwr", le32_to_cpu(log->aipwr));
obj_add_uint(r, "mipwr", le32_to_cpu(log->mipwr));

mipwrt_obj = json_create_object();
json_timestamp(mipwrt_obj, &log->mipwrt);
obj_add_obj(r, "mipwrt", mipwrt_obj);

obj_add_uint(r, "ipwrpe", log->ipwrpe);

descs = json_create_array();
for (i = 0; i < nphd; i++) {
struct json_object *desc = json_create_object();

obj_add_uint(desc, "phbc", le32_to_cpu(log->descs[i].phbc));
obj_add_uint(desc, "phblt", le32_to_cpu(log->descs[i].phblt));
json_object_array_add(descs, desc);
}
obj_add_obj(r, "descs", descs);

json_print(r);
}

static struct print_ops json_print_ops = {
/* libnvme types.h print functions */
.ana_log = json_ana_log,
Expand Down Expand Up @@ -5791,6 +5836,7 @@ static struct print_ops json_print_ops = {
.host_discovery_log = json_host_discovery_log,
.ave_discovery_log = json_ave_discovery_log,
.pull_model_ddc_req_log = json_pull_model_ddc_req_log,
.power_meas_log = json_power_meas_log,

/* libnvme tree print functions */
.list_item = json_list_item,
Expand Down
Loading
Loading