1
0
Fork 0

Adding upstream version 2.7.1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-16 12:25:41 +01:00
parent 04338f02fe
commit d6e1a5d456
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
663 changed files with 15529 additions and 6994 deletions

View file

@ -646,7 +646,7 @@ static int glp_high_latency_show_bar(FILE *fdi, int print)
}
/*
* High latency log page definiton
* High latency log page definition
* Total 32 bytes
*/
struct log_page_high_latency {
@ -1197,3 +1197,646 @@ static int mb_set_lat_stats(int argc, char **argv,
dev_close(dev);
return err;
}
// Global definitions
static inline int K2C(int k) // KELVINS_2_CELSIUS
{
return (k - 273);
};
// Global ID definitions
enum {
// feature ids
FID_LATENCY_FEATURE = 0xd0,
// log ids
LID_SMART_LOG_ADD = 0xca,
LID_LATENCY_STATISTICS = 0xd0,
LID_HIGH_LATENCY_LOG = 0xd1,
LID_PERFORMANCE_STATISTICS = 0xd2,
};
// smart-log-add
struct smart_log_add_item {
uint32_t index;
char *attr;
};
struct __packed wear_level {
__le16 min;
__le16 max;
__le16 avg;
};
struct __packed smart_log_add_item_12 {
uint8_t id;
uint8_t rsvd[2];
uint8_t norm;
uint8_t rsvd1;
union {
struct wear_level wear_level; // 0xad
struct temp_since_born { // 0xe7
__le16 max;
__le16 min;
__le16 curr;
} temp_since_born;
struct power_consumption { // 0xe8
__le16 max;
__le16 min;
__le16 curr;
} power_consumption;
struct temp_since_power_on { // 0xaf
__le16 max;
__le16 min;
__le16 curr;
} temp_since_power_on;
uint8_t raw[6];
};
uint8_t rsvd2;
};
struct __packed smart_log_add_item_10 {
uint8_t id;
uint8_t norm;
union {
struct wear_level wear_level; // 0xad
uint8_t raw[6];
};
uint8_t rsvd[2];
};
struct smart_log_add {
union {
union {
struct smart_log_add_v0 {
struct smart_log_add_item_12 program_fail_count;
struct smart_log_add_item_12 erase_fail_count;
struct smart_log_add_item_12 wear_leveling_count;
struct smart_log_add_item_12 end_to_end_error_count;
struct smart_log_add_item_12 crc_error_count;
struct smart_log_add_item_12 timed_workload_media_wear;
struct smart_log_add_item_12 timed_workload_host_reads;
struct smart_log_add_item_12 timed_workload_timer;
struct smart_log_add_item_12 thermal_throttle_status;
struct smart_log_add_item_12 retry_buffer_overflow_counter;
struct smart_log_add_item_12 pll_lock_loss_count;
struct smart_log_add_item_12 nand_bytes_written;
struct smart_log_add_item_12 host_bytes_written;
struct smart_log_add_item_12 system_area_life_remaining;
struct smart_log_add_item_12 nand_bytes_read;
struct smart_log_add_item_12 temperature;
struct smart_log_add_item_12 power_consumption;
struct smart_log_add_item_12 power_on_temperature;
struct smart_log_add_item_12 power_loss_protection;
struct smart_log_add_item_12 read_fail_count;
struct smart_log_add_item_12 thermal_throttle_time;
struct smart_log_add_item_12 flash_error_media_count;
} v0;
struct smart_log_add_item_12 v0_raw[22];
};
union {
struct smart_log_add_v2 {
struct smart_log_add_item_12 program_fail_count;
struct smart_log_add_item_12 erase_fail_count;
struct smart_log_add_item_12 wear_leveling_count;
struct smart_log_add_item_12 end_to_end_error_count;
struct smart_log_add_item_12 crc_error_count;
struct smart_log_add_item_12 timed_workload_media_wear;
struct smart_log_add_item_12 timed_workload_host_reads;
struct smart_log_add_item_12 timed_workload_timer;
struct smart_log_add_item_12 thermal_throttle_status;
struct smart_log_add_item_12 lifetime_write_amplification;
struct smart_log_add_item_12 pll_lock_loss_count;
struct smart_log_add_item_12 nand_bytes_written;
struct smart_log_add_item_12 host_bytes_written;
struct smart_log_add_item_12 system_area_life_remaining;
struct smart_log_add_item_12 firmware_update_count;
struct smart_log_add_item_12 dram_cecc_count;
struct smart_log_add_item_12 dram_uecc_count;
struct smart_log_add_item_12 xor_pass_count;
struct smart_log_add_item_12 xor_fail_count;
struct smart_log_add_item_12 xor_invoked_count;
struct smart_log_add_item_12 inflight_read_io_cmd;
struct smart_log_add_item_12 flash_error_media_count;
struct smart_log_add_item_12 nand_bytes_read;
struct smart_log_add_item_12 temp_since_born;
struct smart_log_add_item_12 power_consumption;
struct smart_log_add_item_12 temp_since_bootup;
struct smart_log_add_item_12 thermal_throttle_time;
} v2;
struct smart_log_add_item_12 v2_raw[27];
};
union {
struct smart_log_add_v3 {
struct smart_log_add_item_10 program_fail_count;
struct smart_log_add_item_10 erase_fail_count;
struct smart_log_add_item_10 wear_leveling_count;
struct smart_log_add_item_10 ext_e2e_err_count;
struct smart_log_add_item_10 crc_err_count;
struct smart_log_add_item_10 nand_bytes_written;
struct smart_log_add_item_10 host_bytes_written;
struct smart_log_add_item_10 reallocated_sector_count;
struct smart_log_add_item_10 uncorrectable_sector_count;
struct smart_log_add_item_10 nand_uecc_detection;
struct smart_log_add_item_10 nand_xor_correction;
struct smart_log_add_item_10 gc_count;
struct smart_log_add_item_10 dram_uecc_detection_count;
struct smart_log_add_item_10 sram_uecc_detection_count;
struct smart_log_add_item_10 internal_raid_recovery_fail_count;
struct smart_log_add_item_10 inflight_cmds;
struct smart_log_add_item_10 internal_e2e_err_count;
struct smart_log_add_item_10 die_fail_count;
struct smart_log_add_item_10 wear_leveling_execution_count;
struct smart_log_add_item_10 read_disturb_count;
struct smart_log_add_item_10 data_retention_count;
struct smart_log_add_item_10 capacitor_health;
} v3;
struct smart_log_add_item_10 v3_raw[24];
};
uint8_t raw[512];
};
};
static void smart_log_add_v0_print(struct smart_log_add_item_12 *item, int item_count)
{
static const struct smart_log_add_item items[0xff] = {
[0xab] = {0, "program_fail_count" },
[0xac] = {1, "erase_fail_count" },
[0xad] = {2, "wear_leveling_count" },
[0xb8] = {3, "end_to_end_error_count" },
[0xc7] = {4, "crc_error_count" },
[0xe2] = {5, "timed_workload_media_wear" },
[0xe3] = {6, "timed_workload_host_reads" },
[0xe4] = {7, "timed_workload_timer" },
[0xea] = {8, "thermal_throttle_status" },
[0xf0] = {9, "retry_buffer_overflow_counter"},
[0xf3] = {10, "pll_lock_loss_count" },
[0xf4] = {11, "nand_bytes_written" },
[0xf5] = {12, "host_bytes_written" },
[0xf6] = {13, "system_area_life_remaining" },
[0xfa] = {14, "nand_bytes_read" },
[0xe7] = {15, "temperature" },
[0xe8] = {16, "power_consumption" },
[0xaf] = {17, "power_on_temperature" },
[0xec] = {18, "power_loss_protection" },
[0xf2] = {19, "read_fail_count" },
[0xeb] = {20, "thermal_throttle_time" },
[0xed] = {21, "flash_error_media_count" },
};
for (int i = 0; i < item_count; i++, item++) {
if (item->id == 0)
continue;
printf("%#-12" PRIx8 "%-36s%-12d", item->id, items[item->id].attr, item->norm);
switch (item->id) {
case 0xad:
printf("min: %d, max: %d, avg: %d\n",
le16_to_cpu(item->wear_level.min),
le16_to_cpu(item->wear_level.max),
le16_to_cpu(item->wear_level.avg));
break;
case 0xe7:
printf("max: %d °C (%d K), min: %d °C (%d K), curr: %d °C (%d K)\n",
K2C(le16_to_cpu(item->temp_since_born.max)),
le16_to_cpu(item->temp_since_born.max),
K2C(le16_to_cpu(item->temp_since_born.min)),
le16_to_cpu(item->temp_since_born.min),
K2C(le16_to_cpu(item->temp_since_born.curr)),
le16_to_cpu(item->temp_since_born.curr));
break;
case 0xe8:
printf("max: %d, min: %d, curr: %d\n",
le16_to_cpu(item->power_consumption.max),
le16_to_cpu(item->power_consumption.min),
le16_to_cpu(item->power_consumption.curr));
break;
case 0xaf:
printf("max: %d °C (%d K), min: %d °C (%d K), curr: %d °C (%d K)\n",
K2C(le16_to_cpu(item->temp_since_power_on.max)),
le16_to_cpu(item->temp_since_power_on.max),
K2C(le16_to_cpu(item->temp_since_power_on.min)),
le16_to_cpu(item->temp_since_power_on.min),
K2C(le16_to_cpu(item->temp_since_power_on.curr)),
le16_to_cpu(item->temp_since_power_on.curr));
break;
default:
printf("%" PRIu64 "\n", int48_to_long(item->raw));
break;
}
}
}
static void smart_log_add_v2_print(struct smart_log_add_item_12 *item, int item_count)
{
static const struct smart_log_add_item items[0xff] = {
[0xab] = {0, "program_fail_count" },
[0xac] = {1, "erase_fail_count" },
[0xad] = {2, "wear_leveling_count" },
[0xb8] = {3, "end_to_end_error_count" },
[0xc7] = {4, "crc_error_count" },
[0xe2] = {5, "timed_workload_media_wear" },
[0xe3] = {6, "timed_workload_host_reads" },
[0xe4] = {7, "timed_workload_timer" },
[0xea] = {8, "thermal_throttle_status" },
[0xf0] = {9, "lifetime_write_amplification"},
[0xf3] = {10, "pll_lock_loss_count" },
[0xf4] = {11, "nand_bytes_written" },
[0xf5] = {12, "host_bytes_written" },
[0xf6] = {13, "system_area_life_remaining" },
[0xf9] = {14, "firmware_update_count" },
[0xfa] = {15, "dram_cecc_count" },
[0xfb] = {16, "dram_uecc_count" },
[0xfc] = {17, "xor_pass_count" },
[0xfd] = {18, "xor_fail_count" },
[0xfe] = {19, "xor_invoked_count" },
[0xe5] = {20, "inflight_read_io_cmd" },
[0xe6] = {21, "flash_error_media_count" },
[0xf8] = {22, "nand_bytes_read" },
[0xe7] = {23, "temp_since_born" },
[0xe8] = {24, "power_consumption" },
[0xaf] = {25, "temp_since_bootup" },
[0xeb] = {26, "thermal_throttle_time" },
};
for (int i = 0; i < item_count; i++, item++) {
if (item->id == 0)
continue;
printf("%#-12" PRIx8 "%-36s%-12d", item->id, items[item->id].attr, item->norm);
switch (item->id) {
case 0xad:
printf("min: %d, max: %d, avg: %d\n",
le16_to_cpu(item->wear_level.min),
le16_to_cpu(item->wear_level.max),
le16_to_cpu(item->wear_level.avg));
break;
case 0xe7:
printf("max: %d °C (%d K), min: %d °C (%d K), curr: %d °C (%d K)\n",
K2C(le16_to_cpu(item->temp_since_born.max)),
le16_to_cpu(item->temp_since_born.max),
K2C(le16_to_cpu(item->temp_since_born.min)),
le16_to_cpu(item->temp_since_born.min),
K2C(le16_to_cpu(item->temp_since_born.curr)),
le16_to_cpu(item->temp_since_born.curr));
break;
case 0xe8:
printf("max: %d, min: %d, curr: %d\n",
le16_to_cpu(item->power_consumption.max),
le16_to_cpu(item->power_consumption.min),
le16_to_cpu(item->power_consumption.curr));
break;
case 0xaf:
printf("max: %d °C (%d K), min: %d °C (%d K), curr: %d °C (%d K)\n",
K2C(le16_to_cpu(item->temp_since_power_on.max)),
le16_to_cpu(item->temp_since_power_on.max),
K2C(le16_to_cpu(item->temp_since_power_on.min)),
le16_to_cpu(item->temp_since_power_on.min),
K2C(le16_to_cpu(item->temp_since_power_on.curr)),
le16_to_cpu(item->temp_since_power_on.curr));
break;
default:
printf("%" PRIu64 "\n", int48_to_long(item->raw));
break;
}
}
}
static void smart_log_add_v3_print(struct smart_log_add_item_10 *item, int item_count)
{
static const struct smart_log_add_item items[0xff] = {
[0xab] = {0, "program_fail_count" },
[0xac] = {1, "erase_fail_count" },
[0xad] = {2, "wear_leveling_count" },
[0xb8] = {3, "ext_e2e_err_count" },
[0xc7] = {4, "crc_err_count" },
[0xf4] = {5, "nand_bytes_written" },
[0xf5] = {6, "host_bytes_written" },
[0xd0] = {7, "reallocated_sector_count" },
[0xd1] = {8, "uncorrectable_sector_count" },
[0xd2] = {9, "nand_uecc_detection" },
[0xd3] = {10, "nand_xor_correction" },
[0xd4] = {12, "gc_count" }, // 11 is reserved
[0xd5] = {13, "dram_uecc_detection_count" },
[0xd6] = {14, "sram_uecc_detection_count" },
[0xd7] = {15, "internal_raid_recovery_fail_count"},
[0xd8] = {16, "inflight_cmds" },
[0xd9] = {17, "internal_e2e_err_count" },
[0xda] = {19, "die_fail_count" }, // 18 is reserved
[0xdb] = {20, "wear_leveling_execution_count" },
[0xdc] = {21, "read_disturb_count" },
[0xdd] = {22, "data_retention_count" },
[0xde] = {23, "capacitor_health" },
};
for (int i = 0; i < item_count; i++, item++) {
if (item->id == 0)
continue;
printf("%#-12" PRIx8 "%-36s%-12d", item->id, items[item->id].attr, item->norm);
switch (item->id) {
case 0xad:
printf("min: %d, max: %d, avg: %d\n",
le16_to_cpu(item->wear_level.min),
le16_to_cpu(item->wear_level.max),
le16_to_cpu(item->wear_level.avg));
break;
default:
printf("%" PRIu64 "\n", int48_to_long(item->raw));
break;
}
}
}
static void smart_log_add_print(struct smart_log_add *log, const char *devname)
{
uint8_t version = log->raw[511];
printf("Version: %u\n", version);
printf("\n");
printf("Additional Smart Log for NVMe device: %s\n", devname);
printf("\n");
printf("%-12s%-36s%-12s%s\n", "Id", "Key", "Normalized", "Raw");
switch (version) {
case 0:
return smart_log_add_v0_print(&log->v0_raw[0],
sizeof(struct smart_log_add_v0) / sizeof(struct smart_log_add_item_12));
case 2:
return smart_log_add_v2_print(&log->v2_raw[0],
sizeof(struct smart_log_add_v2) / sizeof(struct smart_log_add_item_12));
case 3:
return smart_log_add_v3_print(&log->v3_raw[0],
sizeof(struct smart_log_add_v3) / sizeof(struct smart_log_add_item_10));
case 1:
fprintf(stderr, "Version %d: N/A\n", version);
break;
default:
fprintf(stderr, "Version %d: Not supported yet\n", version);
break;
}
}
static int mb_get_smart_log_add(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
int err = 0;
// Get the configuration
struct config {
bool raw_binary;
};
struct config cfg = {0};
OPT_ARGS(opts) = {
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, "dump the whole log buffer in binary format"),
OPT_END()};
// Open device
struct nvme_dev *dev = NULL;
err = parse_and_open(&dev, argc, argv, cmd->help, opts);
if (err)
return err;
// Get log
struct smart_log_add log = {0};
err = nvme_get_log_simple(dev_fd(dev), LID_SMART_LOG_ADD, sizeof(struct smart_log_add), &log);
if (!err) {
if (!cfg.raw_binary)
smart_log_add_print(&log, dev->name);
else
d_raw((unsigned char *)&log, sizeof(struct smart_log_add));
} else if (err > 0) {
nvme_show_status(err);
} else {
nvme_show_error("%s: %s", cmd->name, nvme_strerror(errno));
}
// Close device
dev_close(dev);
return err;
}
// performance-monitor
struct latency_stats_bucket {
char *start_threshold;
char *end_threshold;
};
struct __packed latency_stats {
union {
struct latency_stats_v2_0 {
uint32_t minor_version;
uint32_t major_version;
uint32_t bucket_read_data[32];
uint32_t rsvd[32];
uint32_t bucket_write_data[32];
uint32_t rsvd1[32];
uint32_t bucket_trim_data[32];
uint32_t rsvd2[32];
uint8_t rsvd3[248];
} v2_0;
uint8_t raw[1024];
};
};
struct __packed high_latency_log {
union {
struct high_latency_log_v1 {
uint32_t version;
struct high_latency_log_entry {
uint64_t timestamp; // ms
uint32_t latency;
uint32_t qid;
uint32_t opcode : 8;
uint32_t fuse : 2;
uint32_t psdt : 2;
uint32_t cid : 16;
uint32_t rsvd : 4;
uint32_t nsid;
uint64_t slba;
uint32_t nlb : 16;
uint32_t dtype : 8;
uint32_t pinfo : 4;
uint32_t fua : 1;
uint32_t lr : 1;
uint32_t rsvd1 : 2;
uint8_t rsvd2[28];
} entries[1024];
} v1;
uint8_t raw[4 + 1024 * 64];
};
};
struct __packed performance_stats {
union {
struct performance_stats_v1 {
uint8_t version;
uint8_t rsvd[3];
struct performance_stats_timestamp {
uint8_t timestamp[6];
struct performance_stats_entry {
uint16_t read_iops; // K IOPS
uint16_t read_bandwidth; // MiB
uint32_t read_latency; // us
uint32_t read_latency_max; // us
uint16_t write_iops; // K IOPS
uint16_t write_bandwidth; // MiB
uint32_t write_latency; // us
uint32_t write_latency_max; // us
} entries[3600];
} timestamps[24];
} v1;
uint8_t raw[4 + 24 * (6 + 3600 * 24)];
};
};
static int mb_set_latency_feature(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
int err = 0;
// Get the configuration
struct config {
uint32_t perf_monitor;
uint32_t cmd_mask;
uint32_t read_threshold;
uint32_t write_threshold;
uint32_t de_allocate_trim_threshold;
};
struct config cfg = {0};
OPT_ARGS(opts) = {
OPT_UINT("sel-perf-log", 's', &cfg.perf_monitor,
"Select features to turn on, default: Disable\n"
" bit 0: latency statistics\n"
" bit 1: high latency log\n"
" bit 2: Performance stat"),
OPT_UINT("set-commands-mask", 'm', &cfg.cmd_mask,
"Set Enable, default: Disable\n"
" bit 0: Read commands\n"
" bit 1: high Write commands\n"
" bit 2: De-allocate/TRIM (this bit is not worked for Performance stat.)"),
OPT_UINT("set-read-threshold", 'r', &cfg.read_threshold,
"set read high latency log threshold, it's a 0-based value and unit is 10ms"),
OPT_UINT("set-write-threshold", 'w', &cfg.write_threshold,
"set write high latency log threshold, it's a 0-based value and unit is 10ms"),
OPT_UINT("set-trim-threshold", 't', &cfg.de_allocate_trim_threshold,
"set trim high latency log threshold, it's a 0-based value and unit is 10ms"),
OPT_END()};
// Open device
struct nvme_dev *dev = NULL;
err = parse_and_open(&dev, argc, argv, cmd->help, opts);
if (err)
return err;
// Set feature
uint32_t result = 0;
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = dev_fd(dev),
.fid = FID_LATENCY_FEATURE,
.nsid = 0,
.cdw11 = 0 | cfg.perf_monitor,
.cdw12 = 0 | cfg.cmd_mask,
.cdw13 = 0 |
(cfg.read_threshold & 0xff) |
((cfg.write_threshold & 0xff) << 8) |
((cfg.de_allocate_trim_threshold & 0xff) << 16),
.cdw15 = 0,
.save = 0,
.uuidx = 0,
.data = NULL,
.data_len = 0,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_set_features(&args);
if (!err)
printf("%s have done successfully. result = %#" PRIx32 ".\n", cmd->name, result);
else if (err > 0)
nvme_show_status(err);
else
nvme_show_error("%s: %s", cmd->name, nvme_strerror(errno));
// Close device
dev_close(dev);
return err;
}
static int mb_get_latency_feature(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
int err = 0;
// Get the configuration
OPT_ARGS(opts) = {
OPT_END()};
// Open device
struct nvme_dev *dev = NULL;
err = parse_and_open(&dev, argc, argv, cmd->help, opts);
if (err)
return err;
// Get feature
uint32_t result = 0;
err = nvme_get_features_simple(dev_fd(dev), FID_LATENCY_FEATURE, 0, &result);
if (!err) {
printf("%s have done successfully. result = %#" PRIx32 ".\n", cmd->name, result);
printf("latency statistics enable status = %d\n", (result & (0x01 << 0)) >> 0);
printf("high latency enable status = %d\n", (result & (0x01 << 1)) >> 1);
printf("performance stat enable status = %d\n", (result & (0x01 << 2)) >> 2);
printf("Monitor Read command = %d\n", (result & (0x01 << 4)) >> 4);
printf("Monitor Write command = %d\n", (result & (0x01 << 5)) >> 5);
printf("Monitor Trim command = %d\n", (result & (0x01 << 6)) >> 6);
printf("Threshold for Read = %dms\n", (((result & (0xff << 8)) >> 8) + 1) * 10);
printf("Threshold for Write = %dms\n", (((result & (0xff << 16)) >> 16) + 1) * 10);
printf("Threshold for Trim = %dms\n", (((result & (0xff << 24)) >> 24) + 1) * 10);
} else if (err > 0) {
nvme_show_status(err);
} else {
nvme_show_error("%s: %s", cmd->name, nvme_strerror(errno));
}
// Close device
dev_close(dev);
return err;
}