Adding upstream version 2.7.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
83f51a6dde
commit
e08cb5ae68
663 changed files with 15529 additions and 6994 deletions
|
@ -56,7 +56,7 @@ static int fdp_configs(int argc, char **argv, struct command *cmd,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = flags = validate_output_format(cfg.output_format);
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -137,7 +137,7 @@ static int fdp_usage(int argc, char **argv, struct command *cmd, struct plugin *
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = flags = validate_output_format(cfg.output_format);
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -208,7 +208,7 @@ static int fdp_stats(int argc, char **argv, struct command *cmd, struct plugin *
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = flags = validate_output_format(cfg.output_format);
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -269,7 +269,7 @@ static int fdp_events(int argc, char **argv, struct command *cmd, struct plugin
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = flags = validate_output_format(cfg.output_format);
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -328,7 +328,7 @@ static int fdp_status(int argc, char **argv, struct command *cmd, struct plugin
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = flags = validate_output_format(cfg.output_format);
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (flags < 0)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -296,7 +296,7 @@ static int huawei_list(int argc, char **argv, struct command *command,
|
|||
struct huawei_list_item *list_items;
|
||||
unsigned int i, n, ret;
|
||||
unsigned int huawei_num = 0;
|
||||
int fmt;
|
||||
enum nvme_print_flags fmt;
|
||||
const char *desc = "Retrieve basic information for the given huawei device";
|
||||
struct config {
|
||||
char *output_format;
|
||||
|
@ -315,9 +315,9 @@ static int huawei_list(int argc, char **argv, struct command *command,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
fmt = validate_output_format(cfg.output_format);
|
||||
if (fmt != JSON && fmt != NORMAL)
|
||||
return -EINVAL;
|
||||
ret = validate_output_format(cfg.output_format, &fmt);
|
||||
if (ret < 0 || (fmt != JSON && fmt != NORMAL))
|
||||
return ret;
|
||||
|
||||
n = scandir("/dev", &devices, nvme_namespace_filter, alphasort);
|
||||
if (n <= 0)
|
||||
|
|
|
@ -1086,7 +1086,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
|
|||
};
|
||||
err = nvme_get_features(&args);
|
||||
if (err) {
|
||||
fprintf(stderr, "Quering thresholds failed. ");
|
||||
fprintf(stderr, "Querying thresholds failed. ");
|
||||
nvme_show_status(err);
|
||||
goto close_dev;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@ PLUGIN(NAME("memblaze", "Memblaze vendor specific extensions", NVME_VERSION),
|
|||
ENTRY("lat-log", "Set Memblaze High Latency Log", mb_set_high_latency_log)
|
||||
ENTRY("lat-log-print", "Output Memblaze High Latency Log", mb_high_latency_log_print)
|
||||
ENTRY("clear-error-log", "Clear error log", memblaze_clear_error_log)
|
||||
ENTRY("smart-log-add-x", "Retrieve Memblaze SMART Log, show it", mb_get_smart_log_add)
|
||||
ENTRY("lat-set-feature-x", "Set Enable/Disable for Latency Monitor feature", mb_set_latency_feature)
|
||||
ENTRY("lat-get-feature-x", "Get Enabled/Disabled of Latency Monitor feature", mb_get_latency_feature)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#define RAISIN_SI_VD_THERMAL_THROTTLE_TIME_ID 0xEB
|
||||
#define RAISIN_SI_VD_FLASH_MEDIA_ERROR_ID 0xED
|
||||
|
||||
/* Raisin Addtional smart internal ID */
|
||||
/* Raisin Additional smart internal ID */
|
||||
typedef enum
|
||||
{
|
||||
/* smart attr following intel */
|
||||
|
@ -154,7 +154,7 @@ struct nvme_p4_smart_log
|
|||
/**
|
||||
* change 512 to 4096.
|
||||
* because micron's getlogpage request,the size of many commands have changed to 4k.
|
||||
* request size > user malloc size,casuing parameters that are closed in momery are dirty.
|
||||
* request size > user malloc size,casuing parameters that are closed in memery are dirty.
|
||||
*/
|
||||
__u8 resv[SMART_INFO_NEW_SIZE - sizeof(struct nvme_p4_smart_log_item) * NR_SMART_ITEMS];
|
||||
};
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <limits.h>
|
||||
#include "linux/types.h"
|
||||
#include "nvme-print.h"
|
||||
#include "util/cleanup.h"
|
||||
|
||||
#define CREATE_CMD
|
||||
#include "micron-nvme.h"
|
||||
|
@ -1767,10 +1768,10 @@ static void GetGenericLogs(int fd, const char *dir)
|
|||
struct nvme_firmware_slot fw_log;
|
||||
struct nvme_cmd_effects_log effects;
|
||||
struct nvme_persistent_event_log pevent_log;
|
||||
_cleanup_huge_ struct nvme_mem_huge mh = { 0, };
|
||||
void *pevent_log_info = NULL;
|
||||
__u32 log_len = 0;
|
||||
int err = 0;
|
||||
bool huge = false;
|
||||
|
||||
/* get self test log */
|
||||
if (!nvme_get_log_device_self_test(fd, &self_test_log))
|
||||
|
@ -1799,17 +1800,17 @@ static void GetGenericLogs(int fd, const char *dir)
|
|||
}
|
||||
|
||||
log_len = le64_to_cpu(pevent_log.tll);
|
||||
pevent_log_info = nvme_alloc_huge(log_len, &huge);
|
||||
pevent_log_info = nvme_alloc_huge(log_len, &mh);
|
||||
if (!pevent_log_info) {
|
||||
perror("could not alloc buffer for persistent event log page (ignored)!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
err = nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_READ,
|
||||
log_len, pevent_log_info);
|
||||
if (!err)
|
||||
WriteData((__u8 *)pevent_log_info, log_len, dir,
|
||||
"persistent_event_log.bin", "persistent event log");
|
||||
nvme_free_huge(pevent_log_info, huge);
|
||||
}
|
||||
|
||||
static void GetNSIDDInfo(int fd, const char *dir, int nsid)
|
||||
|
@ -2221,7 +2222,7 @@ static int display_fw_activate_entry(int entry_count, struct fw_activation_histo
|
|||
else
|
||||
sprintf(ptr, "| pass");
|
||||
|
||||
/* replace all null charecters with spaces */
|
||||
/* replace all null characters with spaces */
|
||||
ptr = formatted_entry;
|
||||
while (index < entry_size) {
|
||||
if (ptr[index] == '\0')
|
||||
|
@ -2289,7 +2290,7 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* check if we have atleast one entry to print */
|
||||
/* check if we have at least one entry to print */
|
||||
struct micron_fw_activation_history_table *table =
|
||||
(struct micron_fw_activation_history_table *)logC2;
|
||||
|
||||
|
@ -2696,7 +2697,7 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c
|
|||
|
||||
/* check for models that support 0xC0 log */
|
||||
if (eModel != M51CX) {
|
||||
printf("Unsupported drive model for vs-smart-add-log commmand\n");
|
||||
printf("Unsupported drive model for vs-smart-add-log command\n");
|
||||
err = -1;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -543,7 +543,7 @@ int show_nbft(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = flags = validate_output_format(format);
|
||||
ret = validate_output_format(format, &flags);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
sources += [
|
||||
'plugins/ocp/ocp-utils.c',
|
||||
'plugins/ocp/ocp-nvme.c',
|
||||
'plugins/ocp/ocp-clear-fw-update-history.c',
|
||||
'plugins/ocp/ocp-clear-features.c',
|
||||
'plugins/ocp/ocp-smart-extended-log.c',
|
||||
'plugins/ocp/ocp-fw-activation-history.c',
|
||||
]
|
||||
|
|
93
plugins/ocp/ocp-clear-features.c
Normal file
93
plugins/ocp/ocp-clear-features.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Authors: haro.panosyan@solidigm.com
|
||||
* leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "ocp-utils.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
static const __u8 OCP_FID_CLEAR_FW_ACTIVATION_HISTORY = 0xC1;
|
||||
static const __u8 OCP_FID_CLEAR_PCIE_CORRECTABLE_ERROR_COUNTERS = 0xC3;
|
||||
|
||||
static int ocp_clear_feature(int argc, char **argv, const char *desc, const __u8 fid)
|
||||
{
|
||||
__u32 result = 0;
|
||||
__u32 clear = 1 << 31;
|
||||
struct nvme_dev *dev;
|
||||
int uuid_index = 0;
|
||||
bool uuid = true;
|
||||
int err;
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FLAG("no-uuid", 'n', NULL,
|
||||
"Skip UUID index search (UUID index not required for OCP 1.0)"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (opts[0].seen)
|
||||
uuid = false;
|
||||
|
||||
if (uuid) {
|
||||
/* OCP 2.0 requires UUID index support */
|
||||
err = ocp_get_uuid_index(dev, &uuid_index);
|
||||
if (err || !uuid_index) {
|
||||
fprintf(stderr, "ERROR: No OCP UUID index found\n");
|
||||
goto close_dev;
|
||||
}
|
||||
}
|
||||
|
||||
struct nvme_set_features_args args = {
|
||||
.result = &result,
|
||||
.data = NULL,
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.nsid = 0,
|
||||
.cdw11 = clear,
|
||||
.cdw12 = 0,
|
||||
.cdw13 = 0,
|
||||
.cdw15 = 0,
|
||||
.data_len = 0,
|
||||
.save = 0,
|
||||
.uuidx = uuid_index,
|
||||
.fid = fid,
|
||||
};
|
||||
|
||||
err = nvme_set_features(&args);
|
||||
|
||||
if (err == 0)
|
||||
printf("Success : %s\n", desc);
|
||||
else if (err > 0)
|
||||
nvme_show_status(err);
|
||||
else
|
||||
printf("Fail : %s\n", desc);
|
||||
close_dev:
|
||||
/* Redundant close() to make static code analysis happy */
|
||||
close(dev->direct.fd);
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "OCP Clear Firmware Update History";
|
||||
|
||||
return ocp_clear_feature(argc, argv, desc, OCP_FID_CLEAR_FW_ACTIVATION_HISTORY);
|
||||
}
|
||||
|
||||
int ocp_clear_pcie_correctable_errors(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "OCP Clear PCIe Correctable Error Counters";
|
||||
|
||||
return ocp_clear_feature(argc, argv, desc,
|
||||
OCP_FID_CLEAR_PCIE_CORRECTABLE_ERROR_COUNTERS);
|
||||
}
|
12
plugins/ocp/ocp-clear-features.h
Normal file
12
plugins/ocp/ocp-clear-features.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Authors: haro.panosyan@solidigm.com
|
||||
* leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, struct plugin *plugin);
|
||||
|
||||
int ocp_clear_pcie_correctable_errors(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin);
|
|
@ -1,20 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Authors: haro.panosyan@solidigm.com
|
||||
* leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include "ocp-utils.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
static const __u8 OCP_FID_CLEAR_FW_ACTIVATION_HISTORY = 0xC1;
|
||||
|
||||
int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "OCP Clear Firmware Update History";
|
||||
|
||||
return ocp_clear_feature(argc, argv, desc, OCP_FID_CLEAR_FW_ACTIVATION_HISTORY);
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Authors: haro.panosyan@solidigm.com
|
||||
* leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
int ocp_clear_fw_update_history(int argc, char **argv,
|
||||
struct command *cmd, struct plugin *plugin);
|
|
@ -207,16 +207,18 @@ int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd,
|
|||
}
|
||||
|
||||
if (!err) {
|
||||
const enum nvme_print_flags print_flag = validate_output_format(format);
|
||||
enum nvme_print_flags print_flag;
|
||||
|
||||
err = validate_output_format(format, &print_flag);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Error: Invalid output format.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (print_flag == JSON)
|
||||
ocp_fw_activation_history_json(&fw_history);
|
||||
else if (print_flag == NORMAL)
|
||||
ocp_fw_activation_history_normal(&fw_history);
|
||||
else {
|
||||
fprintf(stderr, "Error: Invalid output format.\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,12 +21,15 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION),
|
|||
ENTRY("internal-log", "Retrieve and save internal device telemetry log", ocp_telemetry_log)
|
||||
ENTRY("clear-fw-activate-history", "Clear firmware update history log", clear_fw_update_history)
|
||||
ENTRY("eol-plp-failure-mode", "Define EOL or PLP circuitry failure mode.", eol_plp_failure_mode)
|
||||
ENTRY("clear-pcie-correctable-error-counters", "Clear PCIe correctable error counters", clear_pcie_corectable_error_counters)
|
||||
ENTRY("clear-pcie-correctable-errors", "Clear PCIe correctable error counters", clear_pcie_correctable_error_counters)
|
||||
ENTRY("fw-activate-history", "Get firmware activation history log", fw_activation_history_log)
|
||||
ENTRY("unsupported-reqs-log", "Get Unsupported Requirements Log Page", ocp_unsupported_requirements_log)
|
||||
ENTRY("error-recovery-log", "Retrieve Error Recovery Log Page", ocp_error_recovery_log)
|
||||
ENTRY("device-capability-log", "Get Device capabilities Requirements Log Page", ocp_device_capabilities_log)
|
||||
ENTRY("set-dssd-power-state-feature", "Get Device capabilities Requirements Log Page", set_dssd_power_state_feature)
|
||||
ENTRY("set-plp-health-check-interval", "Set PLP Health Check Interval", set_plp_health_check_interval)
|
||||
ENTRY("get-plp-health-check-interval", "Get PLP Health Check Interval", get_plp_health_check_interval)
|
||||
ENTRY("telemetry-string-log", "Retrieve Telemetry string Log Page", ocp_telemetry_str_log_format)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -252,15 +252,15 @@ static void ocp_print_C0_log_json(void *data)
|
|||
|
||||
static int get_c0_log_page(int fd, char *format)
|
||||
{
|
||||
enum nvme_print_flags fmt;
|
||||
__u8 *data;
|
||||
int i;
|
||||
int ret = 0;
|
||||
int fmt = -1;
|
||||
int ret;
|
||||
|
||||
fmt = validate_output_format(format);
|
||||
if (fmt < 0) {
|
||||
ret = validate_output_format(format, &fmt);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "ERROR : OCP : invalid output format\n");
|
||||
return fmt;
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = malloc(sizeof(__u8) * C0_SMART_CLOUD_ATTR_LEN);
|
||||
|
@ -307,6 +307,8 @@ static int get_c0_log_page(int fd, char *format)
|
|||
case JSON:
|
||||
ocp_print_C0_log_json(data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "ERROR : OCP : Unable to read C0 data from buffer\n");
|
||||
|
|
|
@ -30,66 +30,3 @@ int ocp_get_uuid_index(struct nvme_dev *dev, int *index)
|
|||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int ocp_clear_feature(int argc, char **argv, const char *desc, const __u8 fid)
|
||||
{
|
||||
__u32 result = 0;
|
||||
__u32 clear = 1 << 31;
|
||||
struct nvme_dev *dev;
|
||||
int uuid_index = 0;
|
||||
bool uuid = true;
|
||||
int err;
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FLAG("no-uuid", 'n', NULL,
|
||||
"Skip UUID index search (UUID index not required for OCP 1.0)"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (opts[0].seen)
|
||||
uuid = false;
|
||||
|
||||
if (uuid) {
|
||||
/* OCP 2.0 requires UUID index support */
|
||||
err = ocp_get_uuid_index(dev, &uuid_index);
|
||||
if (err || !uuid_index) {
|
||||
fprintf(stderr, "ERROR: No OCP UUID index found\n");
|
||||
goto close_dev;
|
||||
}
|
||||
}
|
||||
|
||||
struct nvme_set_features_args args = {
|
||||
.result = &result,
|
||||
.data = NULL,
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.nsid = 0,
|
||||
.cdw11 = clear,
|
||||
.cdw12 = 0,
|
||||
.cdw13 = 0,
|
||||
.cdw15 = 0,
|
||||
.data_len = 0,
|
||||
.save = 0,
|
||||
.uuidx = uuid_index,
|
||||
.fid = fid,
|
||||
};
|
||||
|
||||
err = nvme_set_features(&args);
|
||||
|
||||
if (err == 0)
|
||||
printf("Success : %s\n", desc);
|
||||
else if (err > 0)
|
||||
nvme_show_status(err);
|
||||
else
|
||||
printf("Fail : %s\n", desc);
|
||||
close_dev:
|
||||
/* Redundant close() to make static code analysis happy */
|
||||
close(dev->direct.fd);
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -10,11 +10,9 @@
|
|||
/**
|
||||
* ocp_get_uuid_index() - Get OCP UUID index
|
||||
* @dev: nvme device
|
||||
* @index: integer ponter to here to save the index
|
||||
* @index: integer pointer to here to save the index
|
||||
* @result: The command completion result from CQE dword0
|
||||
*
|
||||
* Return: Zero if nvme device has UUID list log page, or result of get uuid list otherwise.
|
||||
*/
|
||||
int ocp_get_uuid_index(struct nvme_dev *dev, int *index);
|
||||
|
||||
int ocp_clear_feature(int argc, char **argv, const char *desc, const __u8 fid);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "linux/types.h"
|
||||
#include "nvme-wrap.h"
|
||||
#include "nvme-print.h"
|
||||
#include "util/cleanup.h"
|
||||
|
||||
#define CREATE_CMD
|
||||
#include "sfx-nvme.h"
|
||||
|
@ -881,7 +882,7 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
|
|||
if (trg_in_4k < provisoned_cap_4k ||
|
||||
trg_in_4k > ((__u64)provisoned_cap_4k * 4)) {
|
||||
fprintf(stderr,
|
||||
"WARNING: Only support 1.0~4.0 x provisoned capacity!\n");
|
||||
"WARNING: Only support 1.0~4.0 x provisioned capacity!\n");
|
||||
if (trg_in_4k < provisoned_cap_4k)
|
||||
fprintf(stderr,
|
||||
"WARNING: The target capacity is less than 1.0 x provisioned capacity!\n");
|
||||
|
@ -924,7 +925,7 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
|
|||
*
|
||||
* @param str, prompt string
|
||||
*
|
||||
* @return 0, cancled; 1 confirmed
|
||||
* @return 0, canceled; 1 confirmed
|
||||
*/
|
||||
static int sfx_confirm_change(const char *str)
|
||||
{
|
||||
|
@ -936,7 +937,7 @@ static int sfx_confirm_change(const char *str)
|
|||
fprintf(stderr, "Confirm Y/y, Others cancel:\n");
|
||||
confirm = (unsigned char)fgetc(stdin);
|
||||
if (confirm != 'y' && confirm != 'Y') {
|
||||
fprintf(stderr, "Cancled.\n");
|
||||
fprintf(stderr, "Canceled.\n");
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr, "Sending operation ...\n");
|
||||
|
@ -1349,12 +1350,12 @@ static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 stor
|
|||
{
|
||||
struct nvme_persistent_event_log *pevent;
|
||||
void *pevent_log_info;
|
||||
_cleanup_huge_ struct nvme_mem_huge mh = { 0, };
|
||||
__u8 lsp_base;
|
||||
__u32 offset = 0;
|
||||
__u32 length = 0;
|
||||
__u32 log_len;
|
||||
__u32 single_len;
|
||||
bool huge;
|
||||
int err = 0;
|
||||
FILE *fd = NULL;
|
||||
struct nvme_get_log_args args = {
|
||||
|
@ -1410,7 +1411,7 @@ static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 stor
|
|||
if (log_len % 4)
|
||||
log_len = (log_len / 4 + 1) * 4;
|
||||
|
||||
pevent_log_info = nvme_alloc_huge(single_len, &huge);
|
||||
pevent_log_info = nvme_alloc_huge(single_len, &mh);
|
||||
if (!pevent_log_info) {
|
||||
err = -ENOMEM;
|
||||
goto free_pevent;
|
||||
|
@ -1420,7 +1421,7 @@ static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 stor
|
|||
if (!fd) {
|
||||
fprintf(stderr, "Failed to open %s file to write\n", file);
|
||||
err = ENOENT;
|
||||
goto free;
|
||||
goto free_pevent;
|
||||
}
|
||||
|
||||
args.lsp = lsp_base + NVME_PEVENT_LOG_READ;
|
||||
|
@ -1453,8 +1454,8 @@ static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 stor
|
|||
printf("\nDump-evtlog: Success\n");
|
||||
|
||||
if (parse) {
|
||||
nvme_free_huge(pevent_log_info, huge);
|
||||
pevent_log_info = nvme_alloc_huge(log_len, &huge);
|
||||
nvme_free_huge(&mh);
|
||||
pevent_log_info = nvme_alloc_huge(log_len, &mh);
|
||||
if (!pevent_log_info) {
|
||||
fprintf(stderr, "Failed to alloc enough memory 0x%x to parse evtlog\n", log_len);
|
||||
err = -ENOMEM;
|
||||
|
@ -1466,7 +1467,7 @@ static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 stor
|
|||
if (!fd) {
|
||||
fprintf(stderr, "Failed to open %s file to read\n", file);
|
||||
err = ENOENT;
|
||||
goto free;
|
||||
goto free_pevent;
|
||||
}
|
||||
if (fread(pevent_log_info, 1, log_len, fd) != log_len) {
|
||||
fprintf(stderr, "Failed to read evtlog to buffer\n");
|
||||
|
@ -1478,8 +1479,6 @@ static int nvme_dump_evtlog(struct nvme_dev *dev, __u32 namespace_id, __u32 stor
|
|||
|
||||
close_fd:
|
||||
fclose(fd);
|
||||
free:
|
||||
nvme_free_huge(pevent_log_info, huge);
|
||||
free_pevent:
|
||||
free(pevent);
|
||||
ret:
|
||||
|
|
|
@ -926,7 +926,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
|
|||
/**
|
||||
* Here we should identify if the drive is a Panthor or Jaguar.
|
||||
* Here we need to extract the model no from ctrl-id abd use it
|
||||
* to deternine drive family.
|
||||
* to determine drive family.
|
||||
*/
|
||||
|
||||
err = nvme_identify_ctrl(dev_fd(dev), &ctrl);
|
||||
|
@ -1299,7 +1299,7 @@ static void print_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwAct
|
|||
char buf[80];
|
||||
|
||||
if (fwActivHis.numValidFwActHisEnt > 0) {
|
||||
printf("\n\nSeagate FW Activation Histry :\n");
|
||||
printf("\n\nSeagate FW Activation History :\n");
|
||||
printf("%-9s %-21s %-7s %-13s %-9s %-5s %-15s %-9s\n", "Counter ", " Timestamp ", " PCC ", "Previous FW ", "New FW ", "Slot", "Commit Action", "Result");
|
||||
|
||||
for (i = 0; i < fwActivHis.numValidFwActHisEnt; i++) {
|
||||
|
@ -1406,7 +1406,7 @@ static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd
|
|||
}
|
||||
|
||||
if (strcmp(cfg.output_format, "json"))
|
||||
printf("Seagate FW Activation Histry Information :\n");
|
||||
printf("Seagate FW Activation History Information :\n");
|
||||
|
||||
err = nvme_get_log_simple(dev_fd(dev), 0xC2, sizeof(fwActivHis), &fwActivHis);
|
||||
if (!err) {
|
||||
|
|
|
@ -8,6 +8,9 @@ sources += [
|
|||
'plugins/solidigm/solidigm-telemetry.c',
|
||||
'plugins/solidigm/solidigm-internal-logs.c',
|
||||
'plugins/solidigm/solidigm-market-log.c',
|
||||
'plugins/solidigm/solidigm-temp-stats.c',
|
||||
'plugins/solidigm/solidigm-get-drive-info.c',
|
||||
'plugins/solidigm/solidigm-ocp-version.c',
|
||||
]
|
||||
subdir('solidigm-telemetry')
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ static void vu_gc_log_show(struct garbage_control_collection_log *payload, const
|
|||
int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Get and parse Solidigm vendor specific garbage collection event log.";
|
||||
enum nvme_print_flags flags;
|
||||
struct nvme_dev *dev;
|
||||
int err;
|
||||
__u8 uuid_index;
|
||||
|
@ -89,9 +90,8 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
enum nvme_print_flags flags = validate_output_format(cfg.output_format);
|
||||
|
||||
if (flags == -EINVAL) {
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (err) {
|
||||
fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format);
|
||||
dev_close(dev);
|
||||
return -EINVAL;
|
||||
|
|
79
plugins/solidigm/solidigm-get-drive-info.c
Normal file
79
plugins/solidigm/solidigm-get-drive-info.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Authors: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "nvme-print.h"
|
||||
#include "nvme-wrap.h"
|
||||
#include "common.h"
|
||||
|
||||
int sldgm_get_drive_info(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
|
||||
const char *desc = "Get drive HW information";
|
||||
const char *FTL_unit_size_str = "FTL_unit_size";
|
||||
char *output_format = "normal";
|
||||
enum nvme_print_flags flags;
|
||||
nvme_root_t r;
|
||||
nvme_ctrl_t c;
|
||||
nvme_ns_t n;
|
||||
struct nvme_id_ns ns = { 0 };
|
||||
__u8 flbaf_inUse;
|
||||
__u16 lba_size;
|
||||
__u16 ftl_unit_size;
|
||||
int err;
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FMT("output-format", 'o', &output_format, "normal|json"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = validate_output_format(output_format, &flags);
|
||||
if ((err < 0) || !(flags == NORMAL || flags == JSON)) {
|
||||
nvme_show_error("Invalid output format");
|
||||
return err;
|
||||
}
|
||||
|
||||
r = nvme_scan(NULL);
|
||||
c = nvme_scan_ctrl(r, dev->name);
|
||||
n = c ? nvme_ctrl_first_ns(c) : nvme_scan_namespace(dev->name);
|
||||
if (!n) {
|
||||
nvme_show_error("solidigm-vs-drive-info: drive missing namespace");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = nvme_ns_identify(n, &ns);
|
||||
if (err) {
|
||||
nvme_show_error("identify namespace: %s", nvme_strerror(errno));
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!(ns.nsfeat & 0x10)) {
|
||||
nvme_show_error("solidigm-vs-drive-info: performance options not available");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &flbaf_inUse);
|
||||
lba_size = 1 << ns.lbaf[flbaf_inUse].ds;
|
||||
ftl_unit_size = (le16_to_cpu(ns.npwg) + 1) * lba_size / 1024;
|
||||
|
||||
if (flags == JSON) {
|
||||
struct json_object *root = json_create_object();
|
||||
|
||||
json_object_add_value_int(root, FTL_unit_size_str, ftl_unit_size);
|
||||
json_print_object(root, NULL);
|
||||
printf("\n");
|
||||
json_free_object(root);
|
||||
} else {
|
||||
printf("%s: %d\n", FTL_unit_size_str, ftl_unit_size);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
8
plugins/solidigm/solidigm-get-drive-info.h
Normal file
8
plugins/solidigm/solidigm-get-drive-info.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
int sldgm_get_drive_info(int argc, char **argv, struct command *cmd, struct plugin *plugin);
|
|
@ -19,6 +19,7 @@
|
|||
#include "libnvme.h"
|
||||
#include "plugin.h"
|
||||
#include "nvme-print.h"
|
||||
#include "solidigm-util.h"
|
||||
|
||||
#define DWORD_SIZE 4
|
||||
|
||||
|
@ -427,7 +428,8 @@ static int dump_telemetry(struct nvme_dev *dev, struct config cfg, enum telemetr
|
|||
int err = 0, output;
|
||||
__u8 *buffer = NULL;
|
||||
size_t bytes_remaining = 0;
|
||||
int data_area = NVME_TELEMETRY_DA_3;
|
||||
enum nvme_telemetry_da da;
|
||||
size_t max_data_tx;
|
||||
char file_path[PATH_MAX];
|
||||
char *log_name;
|
||||
|
||||
|
@ -444,6 +446,12 @@ static int dump_telemetry(struct nvme_dev *dev, struct config cfg, enum telemetr
|
|||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
err = nvme_get_telemetry_max(dev_fd(dev), &da, &max_data_tx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (max_data_tx > DRIVER_MAX_TX_256K)
|
||||
max_data_tx = DRIVER_MAX_TX_256K;
|
||||
|
||||
sprintf(file_path, "%s_%s.bin", cfg.file_prefix, log_name);
|
||||
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
|
@ -452,16 +460,16 @@ static int dump_telemetry(struct nvme_dev *dev, struct config cfg, enum telemetr
|
|||
|
||||
switch (ttype) {
|
||||
case HOSTGENNEW:
|
||||
err = nvme_get_new_host_telemetry(dev_fd(dev), &log,
|
||||
data_area, &log_size);
|
||||
err = nvme_get_telemetry_log(dev_fd(dev), true, false, false, max_data_tx, da,
|
||||
&log, &log_size);
|
||||
break;
|
||||
case HOSTGENOLD:
|
||||
err = nvme_get_host_telemetry(dev_fd(dev), &log,
|
||||
data_area, &log_size);
|
||||
err = nvme_get_telemetry_log(dev_fd(dev), false, false, false, max_data_tx, da,
|
||||
&log, &log_size);
|
||||
break;
|
||||
case CONTROLLER:
|
||||
err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &log,
|
||||
data_area, &log_size);
|
||||
err = nvme_get_telemetry_log(dev_fd(dev), false, true, true, max_data_tx, da, &log,
|
||||
&log_size);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -546,42 +554,42 @@ int solidigm_get_internal_log(int argc, char **argv, struct command *command,
|
|||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Assert log");
|
||||
perror("Error retrieving Assert log");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "EVENT")) {
|
||||
err = dump_event_logs(dev, cfg);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Eventt log");
|
||||
perror("Error retrieving Event log");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "NLOG")) {
|
||||
err = dump_nlogs(dev, cfg, -1);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Nlog");
|
||||
perror("Error retrieving Nlog");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "CONTROLLERINITTELEMETRY")) {
|
||||
err = dump_telemetry(dev, cfg, CONTROLLER);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Telemetry Controller Initated");
|
||||
perror("Error retrieving Telemetry Controller Initiated");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "HOSTINITTELEMETRYNOGEN")) {
|
||||
err = dump_telemetry(dev, cfg, HOSTGENOLD);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Previously existing Telemetry Host Initated");
|
||||
perror("Error retrieving previously existing Telemetry Host Initiated");
|
||||
}
|
||||
if (all || !strcmp(cfg.type, "HOSTINITTELEMETRY")) {
|
||||
err = dump_telemetry(dev, cfg, HOSTGENNEW);
|
||||
if (err == 0)
|
||||
log_count++;
|
||||
else if (err < 0)
|
||||
perror("Telemetry Host Initated");
|
||||
perror("Error retrieving Telemetry Host Initiated");
|
||||
}
|
||||
|
||||
if (log_count == 0) {
|
||||
|
|
|
@ -411,8 +411,8 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd
|
|||
|
||||
lt.fd = dev_fd(dev);
|
||||
|
||||
lt.print_flags = validate_output_format(lt.cfg.output_format);
|
||||
if (lt.print_flags == -EINVAL) {
|
||||
err = validate_output_format(lt.cfg.output_format, <.print_flags);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Invalid output format '%s'\n", lt.cfg.output_format);
|
||||
dev_close(dev);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -100,38 +100,13 @@ static struct lid_dir *get_standard_lids(struct nvme_supported_log_pages *suppor
|
|||
static struct lid_dir standard_dir = { 0 };
|
||||
|
||||
init_lid_dir(&standard_dir);
|
||||
standard_dir.lid[0x00].str = "Supported Log Pages";
|
||||
standard_dir.lid[0x01].str = "Error Information";
|
||||
standard_dir.lid[0x02].str = "SMART / Health Information";
|
||||
standard_dir.lid[0x03].str = "Firmware Slot Information";
|
||||
standard_dir.lid[0x04].str = "Changed Namespace List";
|
||||
standard_dir.lid[0x05].str = "Commands Supported and Effects";
|
||||
standard_dir.lid[0x06].str = "Device Self Test";
|
||||
standard_dir.lid[0x07].str = "Telemetry Host-Initiated";
|
||||
standard_dir.lid[0x08].str = "Telemetry Controller-Initiated";
|
||||
standard_dir.lid[0x09].str = "Endurance Group Information";
|
||||
standard_dir.lid[0x0A].str = "Predictable Latency Per NVM Set";
|
||||
standard_dir.lid[0x0B].str = "Predictable Latency Event Aggregate";
|
||||
standard_dir.lid[0x0C].str = "Asymmetric Namespace Access";
|
||||
standard_dir.lid[0x0D].str = "Persistent Event Log";
|
||||
standard_dir.lid[0x0E].str = "Predictable Latency Event Aggregate";
|
||||
standard_dir.lid[0x0F].str = "Endurance Group Event Aggregate";
|
||||
standard_dir.lid[0x10].str = "Media Unit Status";
|
||||
standard_dir.lid[0x11].str = "Supported Capacity Configuration List";
|
||||
standard_dir.lid[0x12].str = "Feature Identifiers Supported and Effects";
|
||||
standard_dir.lid[0x13].str = "NVMe-MI Commands Supported and Effects";
|
||||
standard_dir.lid[0x14].str = "Command and Feature lockdown";
|
||||
standard_dir.lid[0x15].str = "Boot Partition";
|
||||
standard_dir.lid[0x16].str = "Rotational Media Information";
|
||||
standard_dir.lid[0x70].str = "Discovery";
|
||||
standard_dir.lid[0x80].str = "Reservation Notification";
|
||||
standard_dir.lid[0x81].str = "Sanitize Status";
|
||||
|
||||
for (int lid = 0; lid < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; lid++) {
|
||||
if (!supported->lid_support[lid] || lid >= MIN_VENDOR_LID)
|
||||
continue;
|
||||
|
||||
standard_dir.lid[lid].supported = true;
|
||||
standard_dir.lid[lid].str = nvme_log_to_string(lid);
|
||||
}
|
||||
|
||||
return &standard_dir;
|
||||
|
@ -158,6 +133,14 @@ static struct lid_dir *get_solidigm_lids(struct nvme_supported_log_pages *suppor
|
|||
solidigm_dir.lid[0xC4].str = "Endurance Manager Statistics";
|
||||
solidigm_dir.lid[0xC5].str = "Temperature Statistics";
|
||||
solidigm_dir.lid[0xCA].str = "SMART Attributes";
|
||||
solidigm_dir.lid[0xCB].str = "VU NVMe IO Queue Metrics Log Page";
|
||||
solidigm_dir.lid[0xDD].str = "VU Marketing Description Log Page";
|
||||
solidigm_dir.lid[0xEF].str = "Performance Rating and LBA Access Histogram";
|
||||
solidigm_dir.lid[0xF2].str = "Get Power Usage Log Page";
|
||||
solidigm_dir.lid[0xF6].str = "Vt Histo Get Log Page";
|
||||
solidigm_dir.lid[0xF9].str = "Workload Tracker Get Log Page";
|
||||
solidigm_dir.lid[0xFD].str = "Garbage Control Collection Log Page";
|
||||
solidigm_dir.lid[0xFE].str = "Latency Outlier Log Page";
|
||||
|
||||
update_vendor_lid_supported(supported, &solidigm_dir);
|
||||
|
||||
|
@ -281,15 +264,18 @@ int solidigm_get_log_page_directory_log(int argc, char **argv, struct command *c
|
|||
}
|
||||
|
||||
if (!err) {
|
||||
const enum nvme_print_flags print_flag = validate_output_format(format);
|
||||
enum nvme_print_flags print_flag;
|
||||
|
||||
err = validate_output_format(format, &print_flag);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Error: Invalid output format specified: %s.\n", format);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (print_flag == NORMAL) {
|
||||
supported_log_pages_normal(lid_dirs);
|
||||
} else if (print_flag == JSON) {
|
||||
supported_log_pages_json(lid_dirs);
|
||||
} else {
|
||||
fprintf(stderr, "Error: Invalid output format specified: %s.\n", format);
|
||||
err = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
#include "solidigm-telemetry.h"
|
||||
#include "solidigm-log-page-dir.h"
|
||||
#include "solidigm-market-log.h"
|
||||
#include "solidigm-temp-stats.h"
|
||||
#include "solidigm-get-drive-info.h"
|
||||
#include "solidigm-ocp-version.h"
|
||||
|
||||
#include "plugins/ocp/ocp-clear-fw-update-history.h"
|
||||
#include "plugins/ocp/ocp-clear-features.h"
|
||||
#include "plugins/ocp/ocp-smart-extended-log.h"
|
||||
#include "plugins/ocp/ocp-fw-activation-history.h"
|
||||
|
||||
|
@ -59,6 +62,12 @@ static int clear_fw_update_history(int argc, char **argv, struct command *cmd,
|
|||
return ocp_clear_fw_update_history(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int clear_pcie_correctable_error_counters(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
return ocp_clear_pcie_correctable_errors(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int smart_cloud(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
|
@ -82,3 +91,19 @@ static int get_market_log(int argc, char **argv, struct command *cmd,
|
|||
{
|
||||
return sldgm_get_market_log(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
return sldgm_get_temp_stats_log(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int get_drive_info(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
return sldgm_get_drive_info(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
||||
static int get_cloud_SSDplugin_version(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
return sldgm_ocp_version(argc, argv, cmd, plugin);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "cmd.h"
|
||||
|
||||
#define SOLIDIGM_PLUGIN_VERSION "0.14"
|
||||
#define SOLIDIGM_PLUGIN_VERSION "1.0"
|
||||
|
||||
PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
|
||||
COMMAND_LIST(
|
||||
|
@ -25,9 +25,13 @@ PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_V
|
|||
ENTRY("market-log", "Retrieve Market Log", get_market_log)
|
||||
ENTRY("latency-tracking-log", "Enable/Retrieve Latency tracking Log", get_latency_tracking_log)
|
||||
ENTRY("parse-telemetry-log", "Parse Telemetry Log binary", get_telemetry_log)
|
||||
ENTRY("clear-pcie-correctable-errors ", "Clear PCIe Correctable Error Counters (redirects to ocp plug-in)", clear_pcie_correctable_error_counters)
|
||||
ENTRY("clear-fw-activate-history", "Clear firmware update history log (redirects to ocp plug-in)", clear_fw_update_history)
|
||||
ENTRY("vs-fw-activate-history", "Get firmware activation history log (redirects to ocp plug-in)", fw_activation_history)
|
||||
ENTRY("log-page-directory", "Retrieve log page directory", get_log_page_directory_log)
|
||||
ENTRY("temp-stats", "Retrieve Temperature Statistics log", get_temp_stats_log)
|
||||
ENTRY("vs-drive-info", "Retrieve drive information", get_drive_info)
|
||||
ENTRY("cloud-SSDplugin-version", "Prints plug-in OCP version", get_cloud_SSDplugin_version)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
25
plugins/solidigm/solidigm-ocp-version.c
Normal file
25
plugins/solidigm/solidigm-ocp-version.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nvme.h"
|
||||
|
||||
int sldgm_ocp_version(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Prints OCP extensions version of Solidigm plugin";
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
int err = argconfig_parse(argc, argv, desc, opts);
|
||||
|
||||
if (!err)
|
||||
printf("1.0\n");
|
||||
|
||||
return err;
|
||||
}
|
8
plugins/solidigm/solidigm-ocp-version.h
Normal file
8
plugins/solidigm/solidigm-ocp-version.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
int sldgm_ocp_version(int argc, char **argv, struct command *cmd, struct plugin *plugin);
|
|
@ -69,15 +69,17 @@ static char *id_to_name(__u8 id)
|
|||
case 0xE2:
|
||||
return "media_wear_percentage";
|
||||
case 0xE3:
|
||||
return "host_reads";
|
||||
return "timed_work_load_host_reads";
|
||||
case 0xE4:
|
||||
return "timed_work_load";
|
||||
return "timed_work_load_timer";
|
||||
case 0xE5:
|
||||
return "read_commands_in_flight_counter";
|
||||
case 0xE6:
|
||||
return "write_commands_in_flight_counter";
|
||||
case 0xEA:
|
||||
return "thermal_throttle_status";
|
||||
case 0xEE:
|
||||
return "re_sku_count";
|
||||
case 0xF0:
|
||||
return "retry_buffer_overflow_counter";
|
||||
case 0xF3:
|
||||
|
@ -220,11 +222,11 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
flags = validate_output_format(cfg.output_format);
|
||||
if (flags == -EINVAL) {
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format);
|
||||
dev_close(dev);
|
||||
return flags;
|
||||
return err;
|
||||
}
|
||||
|
||||
uuid_index = solidigm_get_vu_uuid_index(dev);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "solidigm-telemetry/header.h"
|
||||
#include "solidigm-telemetry/config.h"
|
||||
#include "solidigm-telemetry/data-area.h"
|
||||
#include "solidigm-util.h"
|
||||
|
||||
static int read_file2buffer(char *file_name, char **buffer, size_t *length)
|
||||
{
|
||||
|
@ -71,7 +72,7 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
|
|||
struct config cfg = {
|
||||
.host_gen = 1,
|
||||
.ctrl_init = false,
|
||||
.data_area = 3,
|
||||
.data_area = -1,
|
||||
.cfg_file = NULL,
|
||||
.is_input_file = false,
|
||||
};
|
||||
|
@ -90,6 +91,10 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
|
|||
if (err)
|
||||
goto ret;
|
||||
|
||||
/* When not selected on the command line, get minimum data area required */
|
||||
if (cfg.data_area == -1)
|
||||
cfg.data_area = cfg.cfg_file ? 3 : 1;
|
||||
|
||||
if (cfg.is_input_file) {
|
||||
if (optind >= argc) {
|
||||
err = errno = EINVAL;
|
||||
|
@ -138,19 +143,23 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
|
|||
}
|
||||
|
||||
if (!cfg.is_input_file) {
|
||||
if (cfg.ctrl_init)
|
||||
err = nvme_get_ctrl_telemetry(dev_fd(dev), true,
|
||||
&tl.log, cfg.data_area,
|
||||
&tl.log_size);
|
||||
else if (cfg.host_gen)
|
||||
err = nvme_get_new_host_telemetry(dev_fd(dev), &tl.log,
|
||||
cfg.data_area,
|
||||
&tl.log_size);
|
||||
else
|
||||
err = nvme_get_host_telemetry(dev_fd(dev), &tl.log,
|
||||
cfg.data_area,
|
||||
&tl.log_size);
|
||||
size_t max_data_tx;
|
||||
|
||||
err = nvme_get_telemetry_max(dev_fd(dev), NULL, &max_data_tx);
|
||||
if (err < 0) {
|
||||
SOLIDIGM_LOG_WARNING("identify_ctrl: %s",
|
||||
nvme_strerror(errno));
|
||||
goto close_fd;
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
SOLIDIGM_LOG_WARNING("Failed to acquire identify ctrl %d!", err);
|
||||
goto close_fd;
|
||||
}
|
||||
if (max_data_tx > DRIVER_MAX_TX_256K)
|
||||
max_data_tx = DRIVER_MAX_TX_256K;
|
||||
|
||||
err = nvme_get_telemetry_log(dev_fd(dev), cfg.host_gen, cfg.ctrl_init, true,
|
||||
max_data_tx, cfg.data_area, &tl.log, &tl.log_size);
|
||||
if (err < 0) {
|
||||
SOLIDIGM_LOG_WARNING("get-telemetry-log: %s",
|
||||
nvme_strerror(errno));
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <string.h>
|
||||
#include "config.h"
|
||||
|
||||
// max 16 bit unsigned integer nummber 65535
|
||||
// max 16 bit unsigned integer number 65535
|
||||
#define MAX_16BIT_NUM_AS_STRING_SIZE 6
|
||||
|
||||
#define OBJ_NAME_PREFIX "UID_"
|
||||
|
|
|
@ -57,7 +57,7 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl,
|
|||
char err_msg[MAX_WARNING_SIZE];
|
||||
|
||||
snprintf(err_msg, MAX_WARNING_SIZE,
|
||||
"Value crossing 64 bit, byte aligned bounday, not supported. size_bit=%u, offset_bit_from_byte=%u.",
|
||||
"Value crossing 64 bit, byte aligned boundary, not supported. size_bit=%u, offset_bit_from_byte=%u.",
|
||||
size_bit, offset_bit_from_byte);
|
||||
*val_obj = json_object_new_string(err_msg);
|
||||
|
||||
|
|
108
plugins/solidigm/solidigm-temp-stats.c
Normal file
108
plugins/solidigm/solidigm-temp-stats.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "nvme-print.h"
|
||||
#include "solidigm-util.h"
|
||||
|
||||
#define SLDGM_TEMP_STATS_LID 0xC5
|
||||
|
||||
struct temp_stats {
|
||||
__le64 curr;
|
||||
__le64 last_overtemp;
|
||||
__le64 life_overtemp;
|
||||
__le64 highest_temp;
|
||||
__le64 lowest_temp;
|
||||
__u8 rsvd[40];
|
||||
__le64 max_operating_temp;
|
||||
__le64 min_operating_temp;
|
||||
__le64 est_offset;
|
||||
};
|
||||
|
||||
static void show_temp_stats(struct temp_stats *stats)
|
||||
{
|
||||
printf("Current temperature : %"PRIu64"\n", le64_to_cpu(stats->curr));
|
||||
printf("Last critical overtemp flag : %"PRIu64"\n", le64_to_cpu(stats->last_overtemp));
|
||||
printf("Life critical overtemp flag : %"PRIu64"\n", le64_to_cpu(stats->life_overtemp));
|
||||
printf("Highest temperature : %"PRIu64"\n", le64_to_cpu(stats->highest_temp));
|
||||
printf("Lowest temperature : %"PRIu64"\n", le64_to_cpu(stats->lowest_temp));
|
||||
printf("Max operating temperature : %"PRIu64"\n", le64_to_cpu(stats->max_operating_temp));
|
||||
printf("Min operating temperature : %"PRIu64"\n", le64_to_cpu(stats->min_operating_temp));
|
||||
printf("Estimated offset : %"PRIu64"\n", le64_to_cpu(stats->est_offset));
|
||||
}
|
||||
|
||||
int sldgm_get_temp_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
unsigned char buffer[4096] = {0};
|
||||
struct nvme_dev *dev;
|
||||
__u8 uuid_idx;
|
||||
int err;
|
||||
|
||||
const char *desc = "Get/show Temperature Statistics log.";
|
||||
const char *raw = "dump output in binary format";
|
||||
struct config {
|
||||
bool raw_binary;
|
||||
};
|
||||
|
||||
struct config cfg = {
|
||||
.raw_binary = false,
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
err = parse_and_open(&dev, argc, argv, desc, opts);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
uuid_idx = solidigm_get_vu_uuid_index(dev);
|
||||
|
||||
struct nvme_get_log_args args = {
|
||||
.lpo = 0,
|
||||
.result = NULL,
|
||||
.log = buffer,
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.uuidx = uuid_idx,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.lid = SLDGM_TEMP_STATS_LID,
|
||||
.len = sizeof(buffer),
|
||||
.nsid = NVME_NSID_ALL,
|
||||
.csi = NVME_CSI_NVM,
|
||||
.lsi = NVME_LOG_LSI_NONE,
|
||||
.lsp = NVME_LOG_LSP_NONE,
|
||||
.rae = false,
|
||||
.ot = false,
|
||||
};
|
||||
|
||||
err = nvme_get_log(&args);
|
||||
if (!err) {
|
||||
uint64_t *guid = (uint64_t *)&buffer[4080];
|
||||
|
||||
if (guid[1] == 0xC7BB98B7D0324863 && guid[0] == 0xBB2C23990E9C722F) {
|
||||
fprintf(stderr, "Error: Log page has 'OCP unsupported Requirements' GUID\n");
|
||||
err = -EBADMSG;
|
||||
goto closefd;
|
||||
}
|
||||
if (!cfg.raw_binary)
|
||||
show_temp_stats((struct temp_stats *) buffer);
|
||||
else
|
||||
d_raw(buffer, sizeof(struct temp_stats));
|
||||
} else if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
}
|
||||
|
||||
closefd:
|
||||
/* Redundant close() to make static code analysis happy */
|
||||
close(dev->direct.fd);
|
||||
dev_close(dev);
|
||||
return err;
|
||||
}
|
8
plugins/solidigm/solidigm-temp-stats.h
Normal file
8
plugins/solidigm/solidigm-temp-stats.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2023 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
int sldgm_get_temp_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin);
|
|
@ -7,4 +7,6 @@
|
|||
|
||||
#include "nvme.h"
|
||||
|
||||
#define DRIVER_MAX_TX_256K (256 * 1024)
|
||||
|
||||
__u8 solidigm_get_vu_uuid_index(struct nvme_dev *dev);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,7 +5,7 @@
|
|||
#if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ)
|
||||
#define WDC_NVME
|
||||
|
||||
#define WDC_PLUGIN_VERSION "2.3.1"
|
||||
#define WDC_PLUGIN_VERSION "2.3.5"
|
||||
#include "cmd.h"
|
||||
|
||||
PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),
|
||||
|
@ -17,34 +17,72 @@ PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERS
|
|||
ENTRY("id-ctrl", "WDC identify controller", wdc_id_ctrl)
|
||||
ENTRY("purge", "WDC Purge", wdc_purge)
|
||||
ENTRY("purge-monitor", "WDC Purge Monitor", wdc_purge_monitor)
|
||||
ENTRY("vs-internal-log", "WDC Internal Firmware Log", wdc_vs_internal_fw_log)
|
||||
ENTRY("vs-internal-log", "WDC Internal Firmware Log",
|
||||
wdc_vs_internal_fw_log)
|
||||
ENTRY("vs-nand-stats", "WDC NAND Statistics", wdc_vs_nand_stats)
|
||||
ENTRY("vs-smart-add-log", "WDC Additional Smart Log", wdc_vs_smart_add_log)
|
||||
ENTRY("clear-pcie-correctable-errors", "WDC Clear PCIe Correctable Error Count", wdc_clear_pcie_correctable_errors)
|
||||
ENTRY("drive-essentials", "WDC Drive Essentials", wdc_drive_essentials)
|
||||
ENTRY("get-drive-status", "WDC Get Drive Status", wdc_drive_status)
|
||||
ENTRY("clear-assert-dump", "WDC Clear Assert Dump", wdc_clear_assert_dump)
|
||||
ENTRY("vs-smart-add-log", "WDC Additional Smart Log",
|
||||
wdc_vs_smart_add_log)
|
||||
ENTRY("clear-pcie-correctable-errors",
|
||||
"WDC Clear PCIe Correctable Error Count",
|
||||
wdc_clear_pcie_correctable_errors)
|
||||
ENTRY("drive-essentials", "WDC Drive Essentials",
|
||||
wdc_drive_essentials)
|
||||
ENTRY("get-drive-status", "WDC Get Drive Status",
|
||||
wdc_drive_status)
|
||||
ENTRY("clear-assert-dump", "WDC Clear Assert Dump",
|
||||
wdc_clear_assert_dump)
|
||||
ENTRY("drive-resize", "WDC Drive Resize", wdc_drive_resize)
|
||||
ENTRY("vs-fw-activate-history", "WDC Get FW Activate History", wdc_vs_fw_activate_history)
|
||||
ENTRY("clear-fw-activate-history", "WDC Clear FW Activate History", wdc_clear_fw_activate_history)
|
||||
ENTRY("vs-fw-activate-history", "WDC Get FW Activate History",
|
||||
wdc_vs_fw_activate_history)
|
||||
ENTRY("clear-fw-activate-history",
|
||||
"WDC Clear FW Activate History",
|
||||
wdc_clear_fw_activate_history)
|
||||
ENTRY("enc-get-log", "WDC Get Enclosure Log", wdc_enc_get_log)
|
||||
ENTRY("vs-telemetry-controller-option", "WDC Enable/Disable Controller Initiated Telemetry Log", wdc_vs_telemetry_controller_option)
|
||||
ENTRY("vs-error-reason-identifier", "WDC Telemetry Reason Identifier", wdc_reason_identifier)
|
||||
ENTRY("log-page-directory", "WDC Get Log Page Directory", wdc_log_page_directory)
|
||||
ENTRY("namespace-resize", "WDC NamespaceDrive Resize", wdc_namespace_resize)
|
||||
ENTRY("vs-telemetry-controller-option",
|
||||
"WDC Enable/Disable Controller Initiated Telemetry Log",
|
||||
wdc_vs_telemetry_controller_option)
|
||||
ENTRY("vs-error-reason-identifier",
|
||||
"WDC Telemetry Reason Identifier",
|
||||
wdc_reason_identifier)
|
||||
ENTRY("log-page-directory", "WDC Get Log Page Directory",
|
||||
wdc_log_page_directory)
|
||||
ENTRY("namespace-resize", "WDC NamespaceDrive Resize",
|
||||
wdc_namespace_resize)
|
||||
ENTRY("vs-drive-info", "WDC Get Drive Info", wdc_vs_drive_info)
|
||||
ENTRY("vs-temperature-stats", "WDC Get Temperature Stats", wdc_vs_temperature_stats)
|
||||
ENTRY("capabilities", "WDC Device Capabilities", wdc_capabilities)
|
||||
ENTRY("cloud-SSD-plugin-version", "WDC Cloud SSD Plugin Version", wdc_cloud_ssd_plugin_version)
|
||||
ENTRY("vs-pcie-stats", "WDC VS PCIE Statistics", wdc_vs_pcie_stats)
|
||||
ENTRY("get-latency-monitor-log", "WDC Get Latency Monitor Log Page", wdc_get_latency_monitor_log)
|
||||
ENTRY("get-error-recovery-log", "WDC Get Error Recovery Log Page", wdc_get_error_recovery_log)
|
||||
ENTRY("get-dev-capabilities-log", "WDC Get Device Capabilities Log Page", wdc_get_dev_capabilities_log)
|
||||
ENTRY("get-unsupported-reqs-log", "WDC Get Unsupported Requirements Log Page", wdc_get_unsupported_reqs_log)
|
||||
ENTRY("cloud-boot-SSD-version", "WDC Get the Cloud Boot SSD Version", wdc_cloud_boot_SSD_version)
|
||||
ENTRY("vs-cloud-log", "WDC Get the Cloud Log Page", wdc_vs_cloud_log)
|
||||
ENTRY("vs-hw-rev-log", "WDC Get the Hardware Revision Log Page", wdc_vs_hw_rev_log)
|
||||
ENTRY("vs-device-waf", "WDC Calculate Device Write Amplication Factor", wdc_vs_device_waf)
|
||||
ENTRY("vs-temperature-stats", "WDC Get Temperature Stats",
|
||||
wdc_vs_temperature_stats)
|
||||
ENTRY("capabilities", "WDC Device Capabilities",
|
||||
wdc_capabilities)
|
||||
ENTRY("cloud-SSD-plugin-version",
|
||||
"WDC Cloud SSD Plugin Version",
|
||||
wdc_cloud_ssd_plugin_version)
|
||||
ENTRY("vs-pcie-stats", "WDC VS PCIE Statistics",
|
||||
wdc_vs_pcie_stats)
|
||||
ENTRY("get-latency-monitor-log",
|
||||
"WDC Get Latency Monitor Log Page",
|
||||
wdc_get_latency_monitor_log)
|
||||
ENTRY("get-error-recovery-log",
|
||||
"WDC Get Error Recovery Log Page",
|
||||
wdc_get_error_recovery_log)
|
||||
ENTRY("get-dev-capabilities-log",
|
||||
"WDC Get Device Capabilities Log Page",
|
||||
wdc_get_dev_capabilities_log)
|
||||
ENTRY("get-unsupported-reqs-log",
|
||||
"WDC Get Unsupported Requirements Log Page",
|
||||
wdc_get_unsupported_reqs_log)
|
||||
ENTRY("cloud-boot-SSD-version",
|
||||
"WDC Get the Cloud Boot SSD Version",
|
||||
wdc_cloud_boot_SSD_version)
|
||||
ENTRY("vs-cloud-log", "WDC Get the Cloud Log Page",
|
||||
wdc_vs_cloud_log)
|
||||
ENTRY("vs-hw-rev-log", "WDC Get the Hardware Revision Log Page",
|
||||
wdc_vs_hw_rev_log)
|
||||
ENTRY("vs-device-waf",
|
||||
"WDC Calculate Device Write Amplication Factor",
|
||||
wdc_vs_device_waf)
|
||||
ENTRY("set-latency-monitor-feature",
|
||||
"WDC set Latency Monitor feature",
|
||||
wdc_set_latency_monitor_feature)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include "nvme.h"
|
||||
#include "libnvme.h"
|
||||
#include "nvme-print.h"
|
||||
#include "wdc-utils.h"
|
||||
|
||||
int wdc_UtilsSnprintf(char *buffer, unsigned int sizeOfBuffer, const char *format, ...)
|
||||
|
@ -133,8 +136,8 @@ end:
|
|||
/**
|
||||
* Compares the strings ignoring their cases.
|
||||
*
|
||||
* @param pcSrc Points to a null terminated string for comapring.
|
||||
* @param pcDst Points to a null terminated string for comapring.
|
||||
* @param pcSrc Points to a null terminated string for comparing.
|
||||
* @param pcDst Points to a null terminated string for comparing.
|
||||
*
|
||||
* @returns zero if the string matches or
|
||||
* 1 if the pcSrc string is lexically higher than pcDst or
|
||||
|
@ -162,3 +165,42 @@ void wdc_StrFormat(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz)
|
|||
}
|
||||
}
|
||||
|
||||
bool wdc_CheckUuidListSupport(struct nvme_dev *dev, struct nvme_id_uuid_list *uuid_list)
|
||||
{
|
||||
int err;
|
||||
struct nvme_id_ctrl ctrl;
|
||||
|
||||
memset(&ctrl, 0, sizeof(struct nvme_id_ctrl));
|
||||
err = nvme_identify_ctrl(dev_fd(dev), &ctrl);
|
||||
if (err) {
|
||||
fprintf(stderr, "ERROR: WDC: nvme_identify_ctrl() failed 0x%x\n", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ctrl.ctratt & NVME_CTRL_CTRATT_UUID_LIST) == NVME_CTRL_CTRATT_UUID_LIST) {
|
||||
err = nvme_identify_uuid(dev_fd(dev), uuid_list);
|
||||
if (!err)
|
||||
return true;
|
||||
else if (err > 0)
|
||||
nvme_show_status(err);
|
||||
else
|
||||
nvme_show_error("identify UUID list: %s", nvme_strerror(errno));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wdc_UuidEqual(struct nvme_id_uuid_list_entry *entry1, struct nvme_id_uuid_list_entry *entry2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (entry1->uuid[i] != entry2->uuid[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 16)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -76,4 +77,5 @@ int wdc_UtilsStrCompare(char *pcSrc, char *pcDst);
|
|||
int wdc_UtilsCreateDir(char *path);
|
||||
int wdc_WriteToFile(char *fileName, char *buffer, unsigned int bufferLen);
|
||||
void wdc_StrFormat(char *formatter, size_t fmt_sz, char *tofmt, size_t tofmtsz);
|
||||
|
||||
bool wdc_CheckUuidListSupport(struct nvme_dev *dev, struct nvme_id_uuid_list *uuid_list);
|
||||
bool wdc_UuidEqual(struct nvme_id_uuid_list_entry *entry1, struct nvme_id_uuid_list_entry *entry2);
|
||||
|
|
|
@ -54,7 +54,7 @@ static int show_ymtc_smart_log(struct nvme_dev *dev, __u32 nsid,
|
|||
/* Table Title */
|
||||
printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
|
||||
dev->name, nsid);
|
||||
/* Clumn Name*/
|
||||
/* Column Name*/
|
||||
printf("key normalized raw\n");
|
||||
/* 00 SI_VD_PROGRAM_FAIL */
|
||||
get_ymtc_smart_info(smart, SI_VD_PROGRAM_FAIL, nm, raw);
|
||||
|
|
|
@ -34,7 +34,7 @@ typedef unsigned char u8;
|
|||
#define SI_VD_THERMAL_THROTTLE_TIME_ID 0xEB
|
||||
#define SI_VD_FLASH_MEDIA_ERROR_ID 0xED
|
||||
|
||||
/* Addtional smart internal ID */
|
||||
/* Additional smart internal ID */
|
||||
typedef enum
|
||||
{
|
||||
/* smart attr following intel */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nvme.h"
|
||||
#include "libnvme.h"
|
||||
#include "nvme-print.h"
|
||||
#include "util/cleanup.h"
|
||||
|
||||
#define CREATE_CMD
|
||||
#include "zns.h"
|
||||
|
@ -135,8 +136,8 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl
|
|||
if (err)
|
||||
return errno;
|
||||
|
||||
err = flags = validate_output_format(cfg.output_format);
|
||||
if (flags < 0)
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (err < 0)
|
||||
goto close_dev;
|
||||
|
||||
err = nvme_zns_identify_ctrl(dev_fd(dev), &ctrl);
|
||||
|
@ -188,8 +189,8 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
|
|||
if (err)
|
||||
return errno;
|
||||
|
||||
flags = validate_output_format(cfg.output_format);
|
||||
if (flags < 0)
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (err < 0)
|
||||
goto close_dev;
|
||||
if (cfg.vendor_specific)
|
||||
flags |= VS;
|
||||
|
@ -560,7 +561,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
|
|||
const char *desc = "Set Zone Descriptor Extension\n";
|
||||
const char *zslba = "starting LBA of the zone for this command";
|
||||
const char *zrwaa = "Allocate Zone Random Write Area to zone";
|
||||
const char *data = "optional file for zone extention data (default stdin)";
|
||||
const char *data = "optional file for zone extension data (default stdin)";
|
||||
const char *timeout = "timeout value, in milliseconds";
|
||||
|
||||
int ffd = STDIN_FILENO, err;
|
||||
|
@ -603,7 +604,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
|
|||
|
||||
if (!data_len || data_len < 0) {
|
||||
fprintf(stderr,
|
||||
"zone format does not provide descriptor extention\n");
|
||||
"zone format does not provide descriptor extension\n");
|
||||
errno = EINVAL;
|
||||
err = -1;
|
||||
goto close_dev;
|
||||
|
@ -765,8 +766,8 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu
|
|||
if (err)
|
||||
return errno;
|
||||
|
||||
flags = validate_output_format(cfg.output_format);
|
||||
if (flags < 0)
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (err < 0)
|
||||
goto close_dev;
|
||||
|
||||
if (!cfg.namespace_id) {
|
||||
|
@ -833,8 +834,8 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
|
|||
int zdes = 0, err = -1;
|
||||
struct nvme_dev *dev;
|
||||
__u32 report_size;
|
||||
bool huge = false;
|
||||
struct nvme_zone_report *report, *buff;
|
||||
_cleanup_huge_ struct nvme_mem_huge mh = { 0, };
|
||||
|
||||
unsigned int nr_zones_chunks = 1024, /* 1024 entries * 64 bytes per entry = 64k byte transfer */
|
||||
nr_zones_retrieved = 0,
|
||||
|
@ -846,7 +847,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
|
|||
struct nvme_id_ns id_ns;
|
||||
uint8_t lbaf;
|
||||
__le64 zsze;
|
||||
struct json_object *zone_list = 0;
|
||||
struct json_object *zone_list = NULL;
|
||||
|
||||
struct config {
|
||||
char *output_format;
|
||||
|
@ -880,8 +881,8 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
|
|||
if (err)
|
||||
return errno;
|
||||
|
||||
flags = validate_output_format(cfg.output_format);
|
||||
if (flags < 0)
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (err < 0)
|
||||
goto close_dev;
|
||||
if (cfg.verbose)
|
||||
flags |= VERBOSE;
|
||||
|
@ -949,7 +950,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
|
|||
log_len = sizeof(struct nvme_zone_report) + ((sizeof(struct nvme_zns_desc) * nr_zones_chunks) + (nr_zones_chunks * zdes));
|
||||
report_size = log_len;
|
||||
|
||||
report = nvme_alloc_huge(report_size, &huge);
|
||||
report = nvme_alloc_huge(report_size, &mh);
|
||||
if (!report) {
|
||||
perror("alloc");
|
||||
err = -ENOMEM;
|
||||
|
@ -957,10 +958,8 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
|
|||
}
|
||||
|
||||
offset = cfg.zslba;
|
||||
if (flags & JSON)
|
||||
zone_list = json_create_array();
|
||||
else
|
||||
printf("nr_zones: %"PRIu64"\n", (uint64_t)le64_to_cpu(total_nr_zones));
|
||||
|
||||
nvme_zns_start_zone_list(total_nr_zones, &zone_list, flags);
|
||||
|
||||
while (nr_zones_retrieved < nr_zones) {
|
||||
if (nr_zones_retrieved >= nr_zones)
|
||||
|
@ -989,15 +988,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
|
|||
offset = le64_to_cpu(report->entries[nr_zones_chunks-1].zslba) + zsze;
|
||||
}
|
||||
|
||||
if (flags & JSON) {
|
||||
struct print_ops *ops;
|
||||
|
||||
ops = nvme_get_json_print_ops(flags);
|
||||
if (ops)
|
||||
ops->zns_finish_zone_list(total_nr_zones, zone_list);
|
||||
}
|
||||
|
||||
nvme_free_huge(report, huge);
|
||||
nvme_zns_finish_zone_list(total_nr_zones, zone_list, flags);
|
||||
|
||||
free_buff:
|
||||
free(buff);
|
||||
|
@ -1256,8 +1247,8 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct
|
|||
if (err)
|
||||
return errno;
|
||||
|
||||
flags = validate_output_format(cfg.output_format);
|
||||
if (flags < 0)
|
||||
err = validate_output_format(cfg.output_format, &flags);
|
||||
if (err < 0)
|
||||
goto close_dev;
|
||||
|
||||
if (!cfg.namespace_id) {
|
||||
|
|
|
@ -15,7 +15,7 @@ PLUGIN(NAME("zns", "Zoned Namespace Command Set", NVME_VERSION),
|
|||
ENTRY("report-zones", "Report zones associated to a Zoned Namespace", report_zones)
|
||||
ENTRY("reset-zone", "Reset one or more zones", reset_zone)
|
||||
ENTRY("close-zone", "Close one or more zones", close_zone)
|
||||
ENTRY("finish-zone", "Finishe one or more zones", finish_zone)
|
||||
ENTRY("finish-zone", "Finish one or more zones", finish_zone)
|
||||
ENTRY("open-zone", "Open one or more zones", open_zone)
|
||||
ENTRY("offline-zone", "Offline one or more zones", offline_zone)
|
||||
ENTRY("set-zone-desc", "Attach zone descriptor extension data to a zone", set_zone_desc)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue